jonathancammack / rpms / openssh

Forked from rpms/openssh 8 months ago
Clone

Blame SOURCES/pam_ssh_agent_auth-0.9.3-command.patch

f8987c
From b0695cc9f5478daa14d3f451ecdd39ba6e6abe0f Mon Sep 17 00:00:00 2001
f8987c
From: Jakub Jelen <jjelen@redhat.com>
f8987c
Date: Tue, 19 Jan 2016 15:29:22 +0100
f8987c
Subject: [PATCH] authorized_keys_command
f8987c
f8987c
---
f8987c
 pam_ssh_agent_auth-0.9.3/CONTRIBUTORS              |   2 +
f8987c
 pam_ssh_agent_auth-0.9.3/Makefile.in               |  28 +-
f8987c
 pam_ssh_agent_auth-0.9.3/README                    |  38 +++
f8987c
 pam_ssh_agent_auth-0.9.3/configure.ac              |  27 +-
f8987c
 pam_ssh_agent_auth-0.9.3/get_command_line.c        | 113 +++++++
f8987c
 pam_ssh_agent_auth-0.9.3/get_command_line.h        |  40 +++
f8987c
 pam_ssh_agent_auth-0.9.3/identity.h                |  24 ++
f8987c
 pam_ssh_agent_auth-0.9.3/iterate_ssh_agent_keys.c  | 137 ++++++++-
f8987c
 pam_ssh_agent_auth-0.9.3/iterate_ssh_agent_keys.h  |   2 +-
f8987c
 pam_ssh_agent_auth-0.9.3/pam_ssh_agent_auth.c      |  16 +-
f8987c
 pam_ssh_agent_auth-0.9.3/pam_ssh_agent_auth.pod    |  50 ++-
f8987c
 pam_ssh_agent_auth-0.9.3/pam_static_macros.h       |  29 ++
f8987c
 .../pam_user_authorized_keys.c                     |  23 +-
f8987c
 .../pam_user_authorized_keys.h                     |   2 +-
f8987c
 pam_ssh_agent_auth-0.9.3/pam_user_key_allowed2.c   | 334 ++++++++++++++++-----
f8987c
 pam_ssh_agent_auth-0.9.3/pam_user_key_allowed2.h   |   3 +-
f8987c
 pam_ssh_agent_auth-0.9.3/secure_filename.c         |  51 +++-
f8987c
 pam_ssh_agent_auth-0.9.3/secure_filename.h         |   4 +-
f8987c
 pam_ssh_agent_auth-0.9.3/userauth_pubkey_from_id.c |  20 +-
f8987c
 pam_ssh_agent_auth-0.9.3/userauth_pubkey_from_id.h |   2 +-
f8987c
 20 files changed, 805 insertions(+), 140 deletions(-)
f8987c
 create mode 100644 pam_ssh_agent_auth-0.9.3/README
f8987c
 create mode 100644 pam_ssh_agent_auth-0.9.3/get_command_line.c
f8987c
 create mode 100644 pam_ssh_agent_auth-0.9.3/get_command_line.h
f8987c
f8987c
diff --git a/pam_ssh_agent_auth-0.9.3/CONTRIBUTORS b/pam_ssh_agent_auth-0.9.3/CONTRIBUTORS
f8987c
index d5a21cb..22b424a 100644
f8987c
--- a/pam_ssh_agent_auth-0.9.3/CONTRIBUTORS
f8987c
+++ b/pam_ssh_agent_auth-0.9.3/CONTRIBUTORS
f8987c
@@ -1,3 +1,5 @@
f8987c
 * Foremost, OpenSSH from which this project is derived.
f8987c
 * Jamie Beverly
f8987c
 * Rafael D'Halleweyn - 2011-06-05 18:56:24 EDT
f8987c
+* Jan-Pieter Cornet ( johnpc ) - 2012-03-23 03:25:52 PDT
f8987c
+* chrysn@fsfe.org
f8987c
diff --git a/pam_ssh_agent_auth-0.9.3/Makefile.in b/pam_ssh_agent_auth-0.9.3/Makefile.in
f8987c
index 47bb103..4977838 100644
f8987c
--- a/pam_ssh_agent_auth-0.9.3/Makefile.in
f8987c
+++ b/pam_ssh_agent_auth-0.9.3/Makefile.in
f8987c
@@ -1,4 +1,28 @@
f8987c
 # $Id: Makefile.in,v 1.289 2008/03/13 01:41:31 djm Exp $
f8987c
+#
f8987c
+# Copyright (c) 2000 Markus Friedl.  All rights reserved.
f8987c
+# Modifications Copyright (c) 2008-2014 Jamie Beverly. All Rights reserved
f8987c
+#
f8987c
+# Redistribution and use in source and binary forms, with or without
f8987c
+# modification, are permitted provided that the following conditions
f8987c
+# are met:
f8987c
+# 1. Redistributions of source code must retain the above copyright
f8987c
+#    notice, this list of conditions and the following disclaimer.
f8987c
+# 2. Redistributions in binary form must reproduce the above copyright
f8987c
+#    notice, this list of conditions and the following disclaimer in the
f8987c
+#    documentation and/or other materials provided with the distribution.
f8987c
+#
f8987c
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
f8987c
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
f8987c
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
f8987c
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
f8987c
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
f8987c
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
f8987c
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
f8987c
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
f8987c
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
f8987c
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
f8987c
+#
f8987c
 
f8987c
 # uncomment if you run a non bourne compatable shell. Ie. csh
f8987c
 #SHELL = @SH@
f8987c
@@ -46,9 +70,9 @@ INSTALL_SSH_RAND_HELPER=@INSTALL_SSH_RAND_HELPER@
f8987c
 
f8987c
 PAM_MODULES=pam_ssh_agent_auth.so
f8987c
 
f8987c
-SSHOBJS=xmalloc.o atomicio.o authfd.o bufaux.o bufbn.o buffer.o cleanup.o entropy.o fatal.o key.o log.o misc.o secure_filename.o ssh-dss.o ssh-rsa.o uuencode.o compat.o
f8987c
+SSHOBJS=xmalloc.o atomicio.o authfd.o bufaux.o bufbn.o buffer.o cleanup.o entropy.o fatal.o key.o log.o misc.o secure_filename.o ssh-dss.o ssh-rsa.o uuencode.o compat.o uidswap.o
f8987c
 
f8987c
-PAM_SSH_AGENT_AUTH_OBJS=pam_user_key_allowed2.o iterate_ssh_agent_keys.o userauth_pubkey_from_id.o pam_user_authorized_keys.o secure_filename.o
f8987c
+PAM_SSH_AGENT_AUTH_OBJS=pam_user_key_allowed2.o iterate_ssh_agent_keys.o userauth_pubkey_from_id.o pam_user_authorized_keys.o secure_filename.o get_command_line.o
f8987c
 
f8987c
 
f8987c
 MANPAGES_IN	= pam_ssh_agent_auth.pod
f8987c
diff --git a/pam_ssh_agent_auth-0.9.3/README b/pam_ssh_agent_auth-0.9.3/README
f8987c
new file mode 100644
f8987c
index 0000000..c1a49ef
f8987c
--- /dev/null
f8987c
+++ b/pam_ssh_agent_auth-0.9.3/README
f8987c
@@ -0,0 +1,38 @@
f8987c
+pam_ssh_agent_auth is a PAM module which permits PAM authentication via your
f8987c
+keyring in a forwarded ssh-agent.
f8987c
+
f8987c
+Release 0.10.1 is stable, and has been tested on FreeBSD, Solaris 10, Solaris 11,
f8987c
+RHEL5, RHEL6, Debian Wheezy, Ubuntu 12.04 (LTS), Ubuntu 13.10,
f8987c
+and MacOS X 10.7.
f8987c
+
f8987c
+This module can be used to provide authentication for anything run locally that
f8987c
+supports PAM. It was written specifically with the intention of permitting
f8987c
+authentication for sudo without password entry, and also has been proven useful
f8987c
+for use with su as an alternative to wheel.
f8987c
+
f8987c
+It serves as middle ground between the two most common, and suboptimal
f8987c
+alternatives for large-scale system administration: allowing rootlogin via ssh,
f8987c
+or using NOPASSWD in sudoers. This module allows for ssh public-key
f8987c
+authentication, and it does this by leveraging an authentication mechanism you
f8987c
+are probably already using, ssh-agent.
f8987c
+
f8987c
+There are caveats of course, ssh-agent forwarding has it’s own security risks
f8987c
+which must be carefully considered for your environment. In cases where there
f8987c
+are not untrustworthy intermediate servers, and you wish to retain traceability,
f8987c
+accountability, and required authentication for privileged command invocation,
f8987c
+the benefits should outweigh the risks. Release 0.10.1 can be downloaded from
f8987c
+SourceForge: https://sourceforge.net/project/showfiles.php?group_id=249556
f8987c
+
f8987c
+If you encounter any issues with usability or security, please use the project's
f8987c
+SourceForge tracker:
f8987c
+https://sourceforge.net/tracker2/?group_id=249556&atid=1126337
f8987c
+
f8987c
+Note that if you wish to use this for sudo, you will need a version of sudo that
f8987c
+preserves the env_keep environment during authentication; and ideally a version
f8987c
+incorporating my minor patch which ensures RUSER is set during PAM authentication.
f8987c
+
f8987c
+sudo 1.6.8p12 does not work correctly with this PAM module, because it clears the
f8987c
+environment (even env_keep variables) prior to attempting PAM authentication.
f8987c
+
f8987c
+sudo 1.7.2p1 or later is preferred, as it correctly sets PAM_RUSER for
f8987c
+authentication.
f8987c
diff --git a/pam_ssh_agent_auth-0.9.3/configure.ac b/pam_ssh_agent_auth-0.9.3/configure.ac
f8987c
index 1f372ce..4eb1f32 100644
f8987c
--- a/pam_ssh_agent_auth-0.9.3/configure.ac
f8987c
+++ b/pam_ssh_agent_auth-0.9.3/configure.ac
f8987c
@@ -18,8 +18,10 @@ AC_INIT(OpenSSH, Portable, openssh-unix-dev@mindrot.org)
f8987c
 AC_REVISION($Revision: 1.397 $)
f8987c
 AC_CONFIG_SRCDIR([pam_ssh_agent_auth.c])
f8987c
 
f8987c
-AC_CONFIG_HEADER(config.h)
f8987c
+AC_CONFIG_SRCDIR([config.h.in])
f8987c
+AC_CONFIG_HEADERS([config.h])
f8987c
 AC_PROG_CC
f8987c
+AC_C_INLINE
f8987c
 AC_CANONICAL_HOST
f8987c
 AC_C_BIGENDIAN
f8987c
 
f8987c
@@ -117,7 +119,6 @@ if test -z "$LD" ; then
f8987c
 fi
f8987c
 AC_SUBST(LD)
f8987c
 
f8987c
-AC_C_INLINE
f8987c
 
f8987c
 AC_CHECK_DECL(LLONG_MAX, have_llong_max=1, , [#include <limits.h>])
f8987c
 
f8987c
@@ -151,7 +152,7 @@ if test "$GCC" = "yes" || test "$GCC" = "egcs"; then
f8987c
 		     ;;
f8987c
 		2.*) no_attrib_nonnull=1 ;;
f8987c
 		3.*) CFLAGS="$CFLAGS -Wsign-compare" ;;
f8987c
-		4.*) CFLAGS="$CFLAGS -Wsign-compare -Wno-pointer-sign" ;;
f8987c
+		4.*) CFLAGS="$CFLAGS -Wsign-compare -Wall -Wextra" ;;
f8987c
 		*) ;;
f8987c
 	esac
f8987c
 
f8987c
@@ -1656,11 +1657,11 @@ fi
f8987c
 
f8987c
 if test "x$check_for_conflicting_getspnam" = "x1"; then
f8987c
 	AC_MSG_CHECKING(for conflicting getspnam in shadow.h)
f8987c
-	AC_COMPILE_IFELSE(
f8987c
+	AC_COMPILE_IFELSE([AC_LANG_SOURCE(
f8987c
 		[
f8987c
 #include <shadow.h>
f8987c
 int main(void) {exit(0);}
f8987c
-		],
f8987c
+		])],
f8987c
 		[
f8987c
 			AC_MSG_RESULT(no)
f8987c
 		],
f8987c
@@ -2720,7 +2721,7 @@ fi
f8987c
 dnl make sure we're using the real structure members and not defines
f8987c
 AC_CACHE_CHECK([for msg_accrights field in struct msghdr],
f8987c
 		ac_cv_have_accrights_in_msghdr, [
f8987c
-	AC_COMPILE_IFELSE(
f8987c
+	AC_COMPILE_IFELSE([AC_LANG_SOURCE(
f8987c
 		[
f8987c
 #include <sys/types.h>
f8987c
 #include <sys/socket.h>
f8987c
@@ -2734,7 +2735,7 @@ struct msghdr m;
f8987c
 m.msg_accrights = 0;
f8987c
 exit(0);
f8987c
 }
f8987c
-		],
f8987c
+		])],
f8987c
 		[ ac_cv_have_accrights_in_msghdr="yes" ],
f8987c
 		[ ac_cv_have_accrights_in_msghdr="no" ]
f8987c
 	)
f8987c
@@ -2747,7 +2748,7 @@ fi
f8987c
 
f8987c
 AC_CACHE_CHECK([for msg_control field in struct msghdr],
f8987c
 		ac_cv_have_control_in_msghdr, [
f8987c
-	AC_COMPILE_IFELSE(
f8987c
+	AC_COMPILE_IFELSE([AC_LANG_SOURCE(
f8987c
 		[
f8987c
 #include <sys/types.h>
f8987c
 #include <sys/socket.h>
f8987c
@@ -2761,7 +2762,7 @@ struct msghdr m;
f8987c
 m.msg_control = 0;
f8987c
 exit(0);
f8987c
 }
f8987c
-		],
f8987c
+		])],
f8987c
 		[ ac_cv_have_control_in_msghdr="yes" ],
f8987c
 		[ ac_cv_have_control_in_msghdr="no" ]
f8987c
 	)
f8987c
@@ -2891,14 +2892,14 @@ AC_SEARCH_LIBS(getrrsetbyname, resolv,
f8987c
 		    saved_LIBS="$LIBS"
f8987c
 		    LIBS="$LIBS -lresolv"
f8987c
 		    AC_MSG_CHECKING(for res_query in -lresolv)
f8987c
-		    AC_LINK_IFELSE([
f8987c
+		    AC_LINK_IFELSE([AC_LANG_SOURCE([
f8987c
 #include <resolv.h>
f8987c
 int main()
f8987c
 {
f8987c
 	res_query (0, 0, 0, 0, 0);
f8987c
 	return 0;
f8987c
 }
f8987c
-			],
f8987c
+			])],
f8987c
 			[LIBS="$LIBS -lresolv"
f8987c
 			 AC_MSG_RESULT(yes)],
f8987c
 			[LIBS="$saved_LIBS"
f8987c
@@ -2915,7 +2916,7 @@ int main()
f8987c
 	])
f8987c
 
f8987c
 AC_MSG_CHECKING(if struct __res_state _res is an extern)
f8987c
-AC_LINK_IFELSE([
f8987c
+AC_LINK_IFELSE([AC_LANG_SOURCE([
f8987c
 #include <stdio.h>
f8987c
 #if HAVE_SYS_TYPES_H
f8987c
 # include <sys/types.h>
f8987c
@@ -2925,7 +2926,7 @@ AC_LINK_IFELSE([
f8987c
 #include <resolv.h>
f8987c
 extern struct __res_state _res;
f8987c
 int main() { return 0; }
f8987c
-		],
f8987c
+		])],
f8987c
 		[AC_MSG_RESULT(yes)
f8987c
 		 AC_DEFINE(HAVE__RES_EXTERN, 1,
f8987c
 		    [Define if you have struct __res_state _res as an extern])
f8987c
diff --git a/pam_ssh_agent_auth-0.9.3/get_command_line.c b/pam_ssh_agent_auth-0.9.3/get_command_line.c
f8987c
new file mode 100644
f8987c
index 0000000..e880fee
f8987c
--- /dev/null
f8987c
+++ b/pam_ssh_agent_auth-0.9.3/get_command_line.c
f8987c
@@ -0,0 +1,113 @@
f8987c
+/*
f8987c
+ * Copyright (c) 2014, Jamie Beverly.
f8987c
+ * All rights reserved.
f8987c
+ *
f8987c
+ * Redistribution and use in source and binary forms, with or without modification, are
f8987c
+ * permitted provided that the following conditions are met:
f8987c
+ *
f8987c
+ *    1. Redistributions of source code must retain the above copyright notice, this list of
f8987c
+ *       conditions and the following disclaimer.
f8987c
+ *
f8987c
+ *    2. Redistributions in binary form must reproduce the above copyright notice, this list
f8987c
+ *       of conditions and the following disclaimer in the documentation and/or other materials
f8987c
+ *       provided with the distribution.
f8987c
+ *
f8987c
+ * THIS SOFTWARE IS PROVIDED BY Jamie Beverly ``AS IS'' AND ANY EXPRESS OR IMPLIED
f8987c
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
f8987c
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Jamie Beverly OR
f8987c
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
f8987c
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
f8987c
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
f8987c
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
f8987c
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
f8987c
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
f8987c
+ *
f8987c
+ * The views and conclusions contained in the software and documentation are those of the
f8987c
+ * authors and should not be interpreted as representing official policies, either expressed
f8987c
+ * or implied, of Jamie Beverly.
f8987c
+ */
f8987c
+
f8987c
+#include <stdio.h>
f8987c
+#include <errno.h>
f8987c
+#include <string.h>
f8987c
+
f8987c
+#include "includes.h"
f8987c
+#include "xmalloc.h"
f8987c
+#include "get_command_line.h"
f8987c
+
f8987c
+#ifdef HAVE_PROC_PID_CMDLINE
f8987c
+
f8987c
+static size_t
f8987c
+proc_pid_cmdline(char *** inargv)
f8987c
+{
f8987c
+    pid_t pid;
f8987c
+    FILE *f = NULL;
f8987c
+    char filename[64] = { 0 }, c = '\0';
f8987c
+    char ** argv;
f8987c
+    char argbuf[MAX_LEN_PER_CMDLINE_ARG + 1] = { 0 };
f8987c
+    size_t count = 0, len = 0;
f8987c
+
f8987c
+    pid = getpid();
f8987c
+    argv = NULL;
f8987c
+
f8987c
+    snprintf(filename, sizeof(filename), "/proc/%d/cmdline", pid);
f8987c
+    f = fopen(filename, "r");
f8987c
+
f8987c
+    if (f) { 
f8987c
+        while (!feof(f) && count < MAX_CMDLINE_ARGS) {
f8987c
+            if (len > MAX_LEN_PER_CMDLINE_ARG) {
f8987c
+                while (!feof(f) && (c = fgetc(f)) != '\0');
f8987c
+            }
f8987c
+            else {
f8987c
+                c = fgetc(f);
f8987c
+            }
f8987c
+            switch (c) {
f8987c
+                case EOF:
f8987c
+                case '\0':
f8987c
+                    if (len > 0) { 
f8987c
+                        argv = xrealloc(argv, count + 1, sizeof(*argv));
f8987c
+                        argv[count] = xcalloc(len + 1, sizeof(*argv[count]));
f8987c
+                        strncpy(argv[count++], argbuf, len);
f8987c
+                        memset(argbuf, '\0', MAX_LEN_PER_CMDLINE_ARG + 1);
f8987c
+                        len = 0;
f8987c
+                    }
f8987c
+                    break;
f8987c
+                default:
f8987c
+                    argbuf[len++] = c;
f8987c
+                    break;
f8987c
+            }
f8987c
+        }
f8987c
+        fclose(f);
f8987c
+    }
f8987c
+    *inargv = argv;
f8987c
+    return count;
f8987c
+}
f8987c
+#endif
f8987c
+
f8987c
+
f8987c
+/*
f8987c
+ * takes a pointer to an unallocated array of arrays of strings, populates the
f8987c
+ * given pointer with the address of the allocated array of strings collected
f8987c
+ */
f8987c
+size_t 
f8987c
+pamsshagentauth_get_command_line(char *** argv)
f8987c
+{
f8987c
+#ifdef HAVE_PROC_PID_CMDLINE
f8987c
+    return proc_pid_cmdline(argv);
f8987c
+#else
f8987c
+    /* No other supported implementations at this time */
f8987c
+    return 0;
f8987c
+#endif
f8987c
+}
f8987c
+
f8987c
+void
f8987c
+pamsshagentauth_free_command_line(char ** argv, size_t n_args)
f8987c
+{
f8987c
+    size_t i;
f8987c
+    for (i = 0; i < n_args; i++)
f8987c
+        free(argv[i]);
f8987c
+
f8987c
+    free(argv);
f8987c
+    return;
f8987c
+}
f8987c
+
f8987c
diff --git a/pam_ssh_agent_auth-0.9.3/get_command_line.h b/pam_ssh_agent_auth-0.9.3/get_command_line.h
f8987c
new file mode 100644
f8987c
index 0000000..37cd077
f8987c
--- /dev/null
f8987c
+++ b/pam_ssh_agent_auth-0.9.3/get_command_line.h
f8987c
@@ -0,0 +1,40 @@
f8987c
+/*
f8987c
+ * Copyright (c) 2014, Jamie Beverly.
f8987c
+ * All rights reserved.
f8987c
+ *
f8987c
+ * Redistribution and use in source and binary forms, with or without modification, are
f8987c
+ * permitted provided that the following conditions are met:
f8987c
+ *
f8987c
+ *    1. Redistributions of source code must retain the above copyright notice, this list of
f8987c
+ *       conditions and the following disclaimer.
f8987c
+ *
f8987c
+ *    2. Redistributions in binary form must reproduce the above copyright notice, this list
f8987c
+ *       of conditions and the following disclaimer in the documentation and/or other materials
f8987c
+ *       provided with the distribution.
f8987c
+ *
f8987c
+ * THIS SOFTWARE IS PROVIDED BY Jamie Beverly ``AS IS'' AND ANY EXPRESS OR IMPLIED
f8987c
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
f8987c
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Jamie Beverly OR
f8987c
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
f8987c
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
f8987c
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
f8987c
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
f8987c
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
f8987c
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
f8987c
+ *
f8987c
+ * The views and conclusions contained in the software and documentation are those of the
f8987c
+ * authors and should not be interpreted as representing official policies, either expressed
f8987c
+ * or implied, of Jamie Beverly.
f8987c
+ */
f8987c
+
f8987c
+#ifndef _GET_COMMAND_LINE_H
f8987c
+#define _GET_COMMAND_LINE_H
f8987c
+
f8987c
+#include "includes.h"
f8987c
+
f8987c
+size_t pamsshagentauth_get_command_line(char ***);
f8987c
+void pamsshagentauth_free_command_line(char **, size_t);
f8987c
+#define MAX_CMDLINE_ARGS 255
f8987c
+#define MAX_LEN_PER_CMDLINE_ARG 255
f8987c
+
f8987c
+#endif
f8987c
diff --git a/pam_ssh_agent_auth-0.9.3/identity.h b/pam_ssh_agent_auth-0.9.3/identity.h
f8987c
index eb21320..0bde782 100644
f8987c
--- a/pam_ssh_agent_auth-0.9.3/identity.h
f8987c
+++ b/pam_ssh_agent_auth-0.9.3/identity.h
f8987c
@@ -1,3 +1,27 @@
f8987c
+/*
f8987c
+ * Copyright (c) 2000 Markus Friedl.  All rights reserved.
f8987c
+ *
f8987c
+ * Redistribution and use in source and binary forms, with or without
f8987c
+ * modification, are permitted provided that the following conditions
f8987c
+ * are met:
f8987c
+ * 1. Redistributions of source code must retain the above copyright
f8987c
+ *    notice, this list of conditions and the following disclaimer.
f8987c
+ * 2. Redistributions in binary form must reproduce the above copyright
f8987c
+ *    notice, this list of conditions and the following disclaimer in the
f8987c
+ *    documentation and/or other materials provided with the distribution.
f8987c
+ *
f8987c
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
f8987c
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
f8987c
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
f8987c
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
f8987c
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
f8987c
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
f8987c
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
f8987c
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
f8987c
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
f8987c
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
f8987c
+ */
f8987c
+
f8987c
 #ifndef _IDENTITY_H
f8987c
 #define _IDENTITY_H
f8987c
 #include "includes.h"
f8987c
diff --git a/pam_ssh_agent_auth-0.9.3/iterate_ssh_agent_keys.c b/pam_ssh_agent_auth-0.9.3/iterate_ssh_agent_keys.c
f8987c
index 11ab6e2..6b4d531 100644
f8987c
--- a/pam_ssh_agent_auth-0.9.3/iterate_ssh_agent_keys.c
f8987c
+++ b/pam_ssh_agent_auth-0.9.3/iterate_ssh_agent_keys.c
f8987c
@@ -28,6 +28,8 @@
f8987c
  */
f8987c
 
f8987c
 
f8987c
+#include <string.h>
f8987c
+
f8987c
 #include "includes.h"
f8987c
 #include "config.h"
f8987c
 
f8987c
@@ -48,26 +50,75 @@
f8987c
 #include <errno.h>
f8987c
 #include <fcntl.h>
f8987c
 #include <openssl/evp.h>
f8987c
+#include "ssh2.h"
f8987c
+#include "misc.h"
f8987c
 
f8987c
 #include "userauth_pubkey_from_id.h"
f8987c
 #include "identity.h"
f8987c
+#include "get_command_line.h"
f8987c
+extern char **environ;
f8987c
+
f8987c
+#define PAM_SSH_AGENT_AUTH_REQUESTv1 101
f8987c
+
f8987c
+static char *
f8987c
+log_action(char ** action, size_t count)
f8987c
+{
f8987c
+    size_t i;
f8987c
+    char *buf = NULL;
f8987c
+
f8987c
+    if (count == 0)
f8987c
+        return NULL;
f8987c
+   
f8987c
+    buf = xcalloc((count * MAX_LEN_PER_CMDLINE_ARG) + (count * 3), sizeof(*buf));
f8987c
+    for (i = 0; i < count; i++) {
f8987c
+        strcat(buf, (i > 0) ? " '" : "'");
f8987c
+        strncat(buf, action[i], MAX_LEN_PER_CMDLINE_ARG);
f8987c
+        strcat(buf, "'");
f8987c
+    }
f8987c
+    return buf;
f8987c
+}
f8987c
+
f8987c
+void
f8987c
+agent_action(Buffer *buf, char ** action, size_t count)
f8987c
+{
f8987c
+    size_t i;
f8987c
+    buffer_init(buf);
f8987c
 
f8987c
-u_char * session_id2 = NULL;
f8987c
-uint8_t session_id_len = 0;
f8987c
+    buffer_put_int(buf, count);
f8987c
+
f8987c
+    for (i = 0; i < count; i++) {
f8987c
+        buffer_put_cstring(buf, action[i]);
f8987c
+    }
f8987c
+}
f8987c
 
f8987c
-u_char *
f8987c
-session_id2_gen()
f8987c
+void
f8987c
+session_id2_gen(Buffer * session_id2, const char * user,
f8987c
+                const char * ruser, const char * servicename)
f8987c
 {
f8987c
     char *cookie = NULL;
f8987c
     uint8_t i = 0;
f8987c
     uint32_t rnd = 0;
f8987c
+    uint8_t cookie_len;
f8987c
+    char hostname[256] = { 0 };
f8987c
+    char pwd[1024] = { 0 };
f8987c
+    time_t ts;
f8987c
+    char ** reported_argv = NULL;
f8987c
+    size_t count = 0;
f8987c
+    char * action_logbuf = NULL;
f8987c
+    Buffer action_agentbuf;
f8987c
+    uint8_t free_logbuf = 0;
f8987c
+    char * retc;
f8987c
+    int32_t reti;
f8987c
 
f8987c
     rnd = arc4random();
f8987c
-    session_id_len = (uint8_t) rnd;
f8987c
+    cookie_len = ((uint8_t) rnd);
f8987c
+    while (cookie_len < 16) { 
f8987c
+        cookie_len += 16;                                          /* Add 16 bytes to the size to ensure that while the length is random, the length is always reasonable; ticket #18 */
f8987c
+    }
f8987c
 
f8987c
-    cookie = calloc(1,session_id_len);
f8987c
+    cookie = xcalloc(1, cookie_len);
f8987c
 
f8987c
-    for (i = 0; i < session_id_len; i++) {
f8987c
+    for (i = 0; i < cookie_len; i++) {
f8987c
         if (i % 4 == 0) {
f8987c
             rnd = arc4random();
f8987c
         }
f8987c
@@ -75,7 +126,64 @@ session_id2_gen()
f8987c
         rnd >>= 8;
f8987c
     }
f8987c
 
f8987c
-    return cookie;
f8987c
+    count = pamsshagentauth_get_command_line(&reported_argv);
f8987c
+    if (count > 0) { 
f8987c
+        free_logbuf = 1;
f8987c
+        action_logbuf = log_action(reported_argv, count);
f8987c
+        agent_action(&action_agentbuf, reported_argv, count);
f8987c
+        pamsshagentauth_free_command_line(reported_argv, count);
f8987c
+    }
f8987c
+    else {
f8987c
+        action_logbuf = "unknown on this platform";
f8987c
+        buffer_init(&action_agentbuf); /* stays empty, means unavailable */
f8987c
+    }
f8987c
+    
f8987c
+    /*
f8987c
+    action = getenv("SUDO_COMMAND");
f8987c
+    if(!action) {
f8987c
+        action = getenv("PAM_AUTHORIZED_ACTION");
f8987c
+        if(!action) {
f8987c
+            action = empty;
f8987c
+        }
f8987c
+    }
f8987c
+    */
f8987c
+
f8987c
+    reti = gethostname(hostname, sizeof(hostname) - 1);
f8987c
+    retc = getcwd(pwd, sizeof(pwd) - 1);
f8987c
+    time(&ts);
f8987c
+
f8987c
+    buffer_init(session_id2);
f8987c
+
f8987c
+    buffer_put_int(session_id2, PAM_SSH_AGENT_AUTH_REQUESTv1);
f8987c
+    /* debug3("cookie: %s", tohex(cookie, cookie_len)); */
f8987c
+    buffer_put_string(session_id2, cookie, cookie_len);
f8987c
+    /* debug3("user: %s", user); */
f8987c
+    buffer_put_cstring(session_id2, user);
f8987c
+    /* debug3("ruser: %s", ruser); */
f8987c
+    buffer_put_cstring(session_id2, ruser);
f8987c
+    /* debug3("servicename: %s", servicename); */
f8987c
+    buffer_put_cstring(session_id2, servicename);
f8987c
+    /* debug3("pwd: %s", pwd); */
f8987c
+    if(retc)
f8987c
+        buffer_put_cstring(session_id2, pwd);
f8987c
+    else
f8987c
+        buffer_put_cstring(session_id2, "");
f8987c
+    /* debug3("action: %s", action_logbuf); */
f8987c
+    buffer_put_string(session_id2, action_agentbuf.buf + action_agentbuf.offset, action_agentbuf.end - action_agentbuf.offset);
f8987c
+    if (free_logbuf) { 
f8987c
+        free(action_logbuf);
f8987c
+        buffer_free(&action_agentbuf);
f8987c
+    }
f8987c
+    /* debug3("hostname: %s", hostname); */
f8987c
+    if(reti >= 0)
f8987c
+        buffer_put_cstring(session_id2, hostname);
f8987c
+    else
f8987c
+        buffer_put_cstring(session_id2, "");
f8987c
+    /* debug3("ts: %ld", ts); */
f8987c
+    buffer_put_int64(session_id2, (uint64_t) ts);
f8987c
+
f8987c
+    free(cookie);
f8987c
+    return;
f8987c
 }
f8987c
 
f8987c
 /* 
f8987c
@@ -174,19 +282,21 @@ ssh_get_authentication_connection_for_uid(uid_t uid)
f8987c
 }
f8987c
 
f8987c
 int
f8987c
-find_authorized_keys(uid_t uid)
f8987c
+find_authorized_keys(const char * user, const char * ruser, const char * servicename)
f8987c
 {
f8987c
+    Buffer session_id2 = { 0 };
f8987c
     Identity *id;
f8987c
     Key *key;
f8987c
     AuthenticationConnection *ac;
f8987c
     char *comment;
f8987c
     uint8_t retval = 0;
f8987c
+    uid_t uid = getpwnam(ruser)->pw_uid;
f8987c
 
f8987c
     OpenSSL_add_all_digests();
f8987c
-    session_id2 = session_id2_gen();
f8987c
+    session_id2_gen(&session_id2, user, ruser, servicename);
f8987c
 
f8987c
     if ((ac = ssh_get_authentication_connection_for_uid(uid))) {
f8987c
-        verbose("Contacted ssh-agent of user %s (%u)", getpwuid(uid)->pw_name, uid);
f8987c
+        verbose("Contacted ssh-agent of user %s (%u)", ruser, uid);
f8987c
         for (key = ssh_get_first_identity(ac, &comment, 2); key != NULL; key = ssh_get_next_identity(ac, &comment, 2)) 
f8987c
         {
f8987c
             if(key != NULL) {
f8987c
@@ -194,7 +304,7 @@ find_authorized_keys(uid_t uid)
f8987c
                 id->key = key;
f8987c
                 id->filename = comment;
f8987c
                 id->ac = ac;
f8987c
-                if(userauth_pubkey_from_id(id)) {
f8987c
+                if(userauth_pubkey_from_id(ruser, id, &session_id2)) {
f8987c
                     retval = 1;
f8987c
                 }
f8987c
                 free(id->filename);
f8987c
@@ -204,12 +314,13 @@ find_authorized_keys(uid_t uid)
f8987c
                     break;
f8987c
             }
f8987c
         }
f8987c
+        buffer_free(&session_id2);
f8987c
         ssh_close_authentication_connection(ac);
f8987c
     }
f8987c
     else {
f8987c
         verbose("No ssh-agent could be contacted");
f8987c
     }
f8987c
-    free(session_id2);
f8987c
+    /*free(session_id2);*/
f8987c
     EVP_cleanup();
f8987c
     return retval;
f8987c
 }
f8987c
diff --git a/pam_ssh_agent_auth-0.9.3/iterate_ssh_agent_keys.h b/pam_ssh_agent_auth-0.9.3/iterate_ssh_agent_keys.h
f8987c
index ed7549e..e6c75aa 100644
f8987c
--- a/pam_ssh_agent_auth-0.9.3/iterate_ssh_agent_keys.h
f8987c
+++ b/pam_ssh_agent_auth-0.9.3/iterate_ssh_agent_keys.h
f8987c
@@ -31,6 +31,6 @@
f8987c
 #ifndef _ITERATE_SSH_AGENT_KEYS_H
f8987c
 #define _ITERATE_SSH_AGENT_KEYS_H
f8987c
 
f8987c
-int find_authorized_keys(uid_t);
f8987c
+int find_authorized_keys(const char * user, const char * ruser, const char * servicename);
f8987c
 
f8987c
 #endif
f8987c
diff --git a/pam_ssh_agent_auth-0.9.3/pam_ssh_agent_auth.c b/pam_ssh_agent_auth-0.9.3/pam_ssh_agent_auth.c
f8987c
index d3f4325..37309f7 100644
f8987c
--- a/pam_ssh_agent_auth-0.9.3/pam_ssh_agent_auth.c
f8987c
+++ b/pam_ssh_agent_auth-0.9.3/pam_ssh_agent_auth.c
f8987c
@@ -59,9 +59,12 @@
f8987c
 #include "pam_user_authorized_keys.h"
f8987c
 
f8987c
 #define strncasecmp_literal(A,B) strncasecmp( A, B, sizeof(B) - 1)
f8987c
+#define UNUSED(expr) do { (void)(expr); } while (0)
f8987c
 
f8987c
 char           *authorized_keys_file = NULL;
f8987c
 uint8_t         allow_user_owned_authorized_keys_file = 0;
f8987c
+char           *authorized_keys_command = NULL;
f8987c
+char           *authorized_keys_command_user = NULL;
f8987c
 
f8987c
 #if ! HAVE___PROGNAME || HAVE_BUNDLE
f8987c
 char           *__progname;
f8987c
@@ -90,6 +93,7 @@ pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char **argv)
f8987c
     facility = SYSLOG_FACILITY_AUTHPRIV;
f8987c
 #endif
f8987c
 
f8987c
+    UNUSED(flags);
f8987c
     pam_get_item(pamh, PAM_SERVICE, (void *) &servicename);
f8987c
 /*
f8987c
  * XXX: 
f8987c
@@ -113,6 +117,12 @@ pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char **argv)
f8987c
         if(strncasecmp_literal(*argv_ptr, "file=") == 0 ) { 
f8987c
             authorized_keys_file_input = *argv_ptr + sizeof("file=") - 1;
f8987c
         }
f8987c
+        if(strncasecmp_literal(*argv_ptr, "authorized_keys_command=") == 0 ) { 
f8987c
+            authorized_keys_command = *argv_ptr + sizeof("authorized_keys_command=") - 1;
f8987c
+        }
f8987c
+        if(strncasecmp_literal(*argv_ptr, "authorized_keys_command_user=") == 0 ) { 
f8987c
+            authorized_keys_command_user = *argv_ptr + sizeof("authorized_keys_command_user=") - 1;
f8987c
+        }
f8987c
 #ifdef ENABLE_SUDO_HACK
f8987c
         if(strncasecmp_literal(*argv_ptr, "sudo_service_name=") == 0) { 
f8987c
             strncpy( sudo_service_name, *argv_ptr + sizeof("sudo_service_name=") - 1, sizeof(sudo_service_name) - 1);
f8987c
@@ -182,7 +192,7 @@ pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char **argv)
f8987c
         /* 
f8987c
          * this pw_uid is used to validate the SSH_AUTH_SOCK, and so must be the uid of the ruser invoking the program, not the target-user
f8987c
          */
f8987c
-        if(find_authorized_keys(getpwnam(ruser)->pw_uid)) {
f8987c
+        if(find_authorized_keys(user, ruser, servicename)) { /* getpwnam(ruser)->pw_uid)) { */
f8987c
             logit("Authenticated: `%s' as `%s' using %s", ruser, user, authorized_keys_file);
f8987c
             retval = PAM_SUCCESS;
f8987c
         } else {
f8987c
@@ -207,6 +217,10 @@ cleanexit:
f8987c
 PAM_EXTERN int __attribute__ ((visibility ("default")))
f8987c
 pam_sm_setcred(pam_handle_t * pamh, int flags, int argc, const char **argv)
f8987c
 {
f8987c
+    UNUSED(pamh);
f8987c
+    UNUSED(flags);
f8987c
+    UNUSED(argc);
f8987c
+    UNUSED(argv);
f8987c
     return PAM_SUCCESS;
f8987c
 }
f8987c
 
f8987c
diff --git a/pam_ssh_agent_auth-0.9.3/pam_ssh_agent_auth.pod b/pam_ssh_agent_auth-0.9.3/pam_ssh_agent_auth.pod
f8987c
index 4570746..76b1f0f 100644
f8987c
--- a/pam_ssh_agent_auth-0.9.3/pam_ssh_agent_auth.pod
f8987c
+++ b/pam_ssh_agent_auth-0.9.3/pam_ssh_agent_auth.pod
f8987c
@@ -1,8 +1,12 @@
f8987c
-=head1 PAM_SSH_AGENT_AUTH
f8987c
+=head1 NAME
f8987c
+
f8987c
+pam_ssh_agent_auth - PAM module for granting permissions based on SSH agent requests
f8987c
+
f8987c
+=head1 DESCRIPTION
f8987c
 
f8987c
 This module provides authentication via ssh-agent.  If an ssh-agent listening at SSH_AUTH_SOCK can successfully authenticate that it has the secret key for a public key in the specified file, authentication is granted, otherwise authentication fails.
f8987c
 
f8987c
-=head1 SUMMARY
f8987c
+=head1 CONFIGURATION
f8987c
 
f8987c
 =over
f8987c
 
f8987c
@@ -10,7 +14,8 @@ This module provides authentication via ssh-agent.  If an ssh-agent listening at
f8987c
  auth	sufficient	pam_ssh_agent_auth.so file=/etc/security/authorized_keys
f8987c
 
f8987c
 =item /etc/sudoers:
f8987c
-
f8987c
+ 
f8987c
+In older versions of sudo (< 1.8.5) it was necessary to set:
f8987c
  Defaults    env_keep += "SSH_AUTH_SOCK"
f8987c
 
f8987c
 =back
f8987c
@@ -33,6 +38,15 @@ Specify the path to the authorized_keys file(s) you would like to use for authen
f8987c
 A flag which enables authorized_keys files to be owned by the invoking user, instead of root. This flag is enabled automatically whenever
f8987c
 the expansions %h or ~ are used.
f8987c
 
f8987c
+=item authorized_keys_command=<path to executable>
f8987c
+
f8987c
+Specify an external command to run, which should take a single argument, the username of the person being authenticated, and emit to its stdout a file in authorized_keys format.
f8987c
+This is ideally suited for use with sssd's sss_ssh_authorizedkeys, for authenticating users via authorized_keys stored in ldap or other sssd supported security service.
f8987c
+
f8987c
+=item authorized_keys_command_user=<username>
f8987c
+
f8987c
+Specify a user to run the authorized_keys_command as. If this option is not specified, the authorized_keys_command will be run as the user being authenticated.
f8987c
+
f8987c
 =item debug
f8987c
 
f8987c
 A flag which enables verbose logging
f8987c
@@ -105,4 +119,34 @@ so this file must be owned by root.
f8987c
 
f8987c
 =back
f8987c
 
f8987c
+=head1 COPYRIGHT
f8987c
+
f8987c
+ Copyright (c) 2008-2014, Jamie Beverly.
f8987c
+ And is based on openssh, and the included works by Markus Friedl, Darren Tucker,
f8987c
+ Todd C. Miller, Ben Lindstrom, Tim Rice, Damien Miller, and many others.
f8987c
+
f8987c
+ All rights reserved.
f8987c
+
f8987c
+ See sources for complete attributions.
f8987c
+ 
f8987c
+ Redistribution and use in source and binary forms, with or without modification, are
f8987c
+ permitted provided that the following conditions are met:
f8987c
+
f8987c
+ 1. Redistributions of source code must retain the above copyright notice, this list of
f8987c
+    conditions and the following disclaimer.
f8987c
+
f8987c
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list
f8987c
+    of conditions and the following disclaimer in the documentation and/or other materials
f8987c
+    provided with the distribution.
f8987c
+
f8987c
+ THIS SOFTWARE IS PROVIDED BY Jamie Beverly ``AS IS'' AND ANY EXPRESS OR IMPLIED
f8987c
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
f8987c
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Jamie Beverly OR
f8987c
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
f8987c
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
f8987c
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
f8987c
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
f8987c
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
f8987c
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
f8987c
+
f8987c
 =cut
f8987c
diff --git a/pam_ssh_agent_auth-0.9.3/pam_static_macros.h b/pam_ssh_agent_auth-0.9.3/pam_static_macros.h
f8987c
index a4938d3..a991704 100644
f8987c
--- a/pam_ssh_agent_auth-0.9.3/pam_static_macros.h
f8987c
+++ b/pam_ssh_agent_auth-0.9.3/pam_static_macros.h
f8987c
@@ -1,3 +1,32 @@
f8987c
+/*
f8987c
+ * Copyright (c) 2008, Jamie Beverly.
f8987c
+ * All rights reserved.
f8987c
+ *
f8987c
+ * Redistribution and use in source and binary forms, with or without modification, are
f8987c
+ * permitted provided that the following conditions are met:
f8987c
+ *
f8987c
+ *    1. Redistributions of source code must retain the above copyright notice, this list of
f8987c
+ *       conditions and the following disclaimer.
f8987c
+ *
f8987c
+ *    2. Redistributions in binary form must reproduce the above copyright notice, this list
f8987c
+ *       of conditions and the following disclaimer in the documentation and/or other materials
f8987c
+ *       provided with the distribution.
f8987c
+ *
f8987c
+ * THIS SOFTWARE IS PROVIDED BY Jamie Beverly ``AS IS'' AND ANY EXPRESS OR IMPLIED
f8987c
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
f8987c
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Jamie Beverly OR
f8987c
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
f8987c
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
f8987c
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
f8987c
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
f8987c
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
f8987c
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
f8987c
+ *
f8987c
+ * The views and conclusions contained in the software and documentation are those of the
f8987c
+ * authors and should not be interpreted as representing official policies, either expressed
f8987c
+ * or implied, of Jamie Beverly.
f8987c
+ */
f8987c
+
f8987c
 #ifndef __PAM_STATIC_MACROS_H
f8987c
 #define __PAM_STATIC_MACROS_H
f8987c
 
f8987c
diff --git a/pam_ssh_agent_auth-0.9.3/pam_user_authorized_keys.c b/pam_ssh_agent_auth-0.9.3/pam_user_authorized_keys.c
f8987c
index 60bef68..abc0a62 100644
f8987c
--- a/pam_ssh_agent_auth-0.9.3/pam_user_authorized_keys.c
f8987c
+++ b/pam_ssh_agent_auth-0.9.3/pam_user_authorized_keys.c
f8987c
@@ -1,4 +1,4 @@
f8987c
-/*
f8987c
+/* 
f8987c
  * Copyright (c) 2008, Jamie Beverly. 
f8987c
  * All rights reserved.
f8987c
  * 
f8987c
@@ -80,9 +80,15 @@
f8987c
 #include "identity.h"
f8987c
 #include "pam_user_key_allowed2.h"
f8987c
 
f8987c
-extern char    *authorized_keys_file;
f8987c
-extern uint8_t  allow_user_owned_authorized_keys_file;
f8987c
-uid_t           authorized_keys_file_allowed_owner_uid;
f8987c
+extern char *authorized_keys_file;
f8987c
+
f8987c
+extern char *authorized_keys_command;
f8987c
+
f8987c
+extern char *authorized_keys_command_user;
f8987c
+
f8987c
+extern uint8_t allow_user_owned_authorized_keys_file;
f8987c
+
f8987c
+uid_t authorized_keys_file_allowed_owner_uid;
f8987c
 
f8987c
 void
f8987c
 parse_authorized_key_file(const char *user, const char *authorized_keys_file_input)
f8987c
@@ -137,8 +143,11 @@ parse_authorized_key_file(const char *user, const char *authorized_keys_file_inp
f8987c
 }
f8987c
 
f8987c
 int
f8987c
-pam_user_key_allowed(Key * key)
f8987c
+pam_user_key_allowed(const char *ruser, Key * key)
f8987c
 {
f8987c
     return pam_user_key_allowed2(getpwuid(authorized_keys_file_allowed_owner_uid), key, authorized_keys_file)
f8987c
-        || pam_user_key_allowed2(getpwuid(0), key, authorized_keys_file);
f8987c
+        || pam_user_key_allowed2(getpwuid(0), key, authorized_keys_file)
f8987c
+        || pam_user_key_command_allowed2(authorized_keys_command,
f8987c
+                                         authorized_keys_command_user,
f8987c
+                                         getpwnam(ruser), key);
f8987c
 }
f8987c
diff --git a/pam_ssh_agent_auth-0.9.3/pam_user_authorized_keys.h b/pam_ssh_agent_auth-0.9.3/pam_user_authorized_keys.h
f8987c
index ae9a4b8..a871bf0 100644
f8987c
--- a/pam_ssh_agent_auth-0.9.3/pam_user_authorized_keys.h
f8987c
+++ b/pam_ssh_agent_auth-0.9.3/pam_user_authorized_keys.h
f8987c
@@ -32,7 +32,7 @@
f8987c
 #define _PAM_USER_KEY_ALLOWED_H
f8987c
 
f8987c
 #include "identity.h"
f8987c
-int pam_user_key_allowed(Key *);
f8987c
+int pam_user_key_allowed(const char *, Key *);
f8987c
 void parse_authorized_key_file(const char *, const char *);
f8987c
 
f8987c
 #endif
f8987c
diff --git a/pam_ssh_agent_auth-0.9.3/pam_user_key_allowed2.c b/pam_ssh_agent_auth-0.9.3/pam_user_key_allowed2.c
f8987c
index c6680e4..4aceecb 100644
f8987c
--- a/pam_ssh_agent_auth-0.9.3/pam_user_key_allowed2.c
f8987c
+++ b/pam_ssh_agent_auth-0.9.3/pam_user_key_allowed2.c
f8987c
@@ -1,4 +1,4 @@
f8987c
-/*
f8987c
+/* 
f8987c
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
f8987c
  *
f8987c
  * Redistribution and use in source and binary forms, with or without
f8987c
@@ -33,9 +33,14 @@
f8987c
 
f8987c
 #include <sys/types.h>
f8987c
 #include <sys/stat.h>
f8987c
+#include <sys/wait.h>
f8987c
+#include <fcntl.h>
f8987c
 
f8987c
 #include <pwd.h>
f8987c
 #include <stdio.h>
f8987c
+#include <signal.h>
f8987c
+#include <errno.h>
f8987c
+#include <string.h>
f8987c
 
f8987c
 #include "xmalloc.h"
f8987c
 #include "ssh.h"
f8987c
@@ -48,87 +53,263 @@
f8987c
 #include "pathnames.h"
f8987c
 #include "misc.h"
f8987c
 #include "secure_filename.h"
f8987c
+#include "uidswap.h"
f8987c
+#include <unistd.h>
f8987c
 
f8987c
 #include "identity.h"
f8987c
 
f8987c
 /* return 1 if user allows given key */
f8987c
 /* Modified slightly from original found in auth2-pubkey.c */
f8987c
+static int
f8987c
+pamsshagentauth_check_authkeys_file(FILE * f, char *file, Key * key)
f8987c
+{
f8987c
+    char line[SSH_MAX_PUBKEY_BYTES];
f8987c
+    int found_key = 0;
f8987c
+    u_long linenum = 0;
f8987c
+    Key *found;
f8987c
+    char *fp;
f8987c
+
f8987c
+    found_key = 0;
f8987c
+    found = key_new(key->type);
f8987c
+
f8987c
+    while(read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
f8987c
+        char *cp = NULL; /* *key_options = NULL; */
f8987c
+
f8987c
+        /* Skip leading whitespace, empty and comment lines. */
f8987c
+        for(cp = line; *cp == ' ' || *cp == '\t'; cp++);
f8987c
+        if(!*cp || *cp == '\n' || *cp == '#')
f8987c
+            continue;
f8987c
+
f8987c
+        if(key_read(found, &cp) != 1) {
f8987c
+            /* no key? check if there are options for this key */
f8987c
+            int quoted = 0;
f8987c
+
f8987c
+            verbose("user_key_allowed: check options: '%s'", cp);
f8987c
+            /* key_options = cp; */
f8987c
+            for(; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
f8987c
+                if(*cp == '\\' && cp[1] == '"')
f8987c
+                    cp++;                                  /* Skip both */
f8987c
+                else if(*cp == '"')
f8987c
+                    quoted = !quoted;
f8987c
+            }
f8987c
+            /* Skip remaining whitespace. */
f8987c
+            for(; *cp == ' ' || *cp == '\t'; cp++);
f8987c
+            if(key_read(found, &cp) != 1) {
f8987c
+                verbose("user_key_allowed: advance: '%s'", cp);
f8987c
+                /* still no key? advance to next line */
f8987c
+                continue;
f8987c
+            }
f8987c
+        }
f8987c
+        if(key_equal(found, key)) {
f8987c
+            found_key = 1;
f8987c
+            logit("matching key found: file/command %s, line %lu", file,
f8987c
+                                  linenum);
f8987c
+            fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
f8987c
+            logit("Found matching %s key: %s",
f8987c
+                                  key_type(found), fp);
f8987c
+            free(fp);
f8987c
+            break;
f8987c
+        }
f8987c
+    }
f8987c
+    key_free(found);
f8987c
+    if(!found_key)
f8987c
+        verbose("key not found");
f8987c
+    return found_key;
f8987c
+}
f8987c
+
f8987c
+/* 
f8987c
+ * Checks whether key is allowed in file.
f8987c
+ * returns 1 if the key is allowed or 0 otherwise.
f8987c
+ */
f8987c
 int
f8987c
 pam_user_key_allowed2(struct passwd *pw, Key *key, char *file)
f8987c
 {
f8987c
-	char line[SSH_MAX_PUBKEY_BYTES];
f8987c
-	int found_key = 0;
f8987c
-	FILE *f;
f8987c
-	u_long linenum = 0;
f8987c
-	struct stat st;
f8987c
-	Key *found;
f8987c
-	char *fp;
f8987c
-
f8987c
-	verbose("trying public key file %s", file);
f8987c
-
f8987c
-	/* Fail not so quietly if file does not exist */
f8987c
-	if (stat(file, &st) < 0) {
f8987c
+    FILE *f;
f8987c
+    int found_key = 0;
f8987c
+    struct stat st;
f8987c
+    char buf[SSH_MAX_PUBKEY_BYTES];
f8987c
+
f8987c
+    /* Temporarily use the user's uid. */
f8987c
+    verbose("trying public key file %s", file);
f8987c
+
f8987c
+    /* Fail not so quietly if file does not exist */
f8987c
+    if(stat(file, &st) < 0) {
f8987c
         verbose("File not found: %s", file);
f8987c
-		return 0;
f8987c
-	}
f8987c
-	/* Open the file containing the authorized keys. */
f8987c
-	f = fopen(file, "r");
f8987c
-	if (!f) {
f8987c
-		return 0;
f8987c
-	}
f8987c
-	if (
f8987c
-	    secure_filename(f, file, pw, line, sizeof(line)) != 0) {
f8987c
-		fclose(f);
f8987c
-		logit("Authentication refused: %s", line);
f8987c
-		return 0;
f8987c
-	}
f8987c
-
f8987c
-	found_key = 0;
f8987c
-	found = key_new(key->type);
f8987c
-
f8987c
-	while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
f8987c
-		char *cp, *key_options = NULL;
f8987c
-
f8987c
-		/* Skip leading whitespace, empty and comment lines. */
f8987c
-		for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
f8987c
-			;
f8987c
-		if (!*cp || *cp == '\n' || *cp == '#')
f8987c
-			continue;
f8987c
-
f8987c
-		if (key_read(found, &cp) != 1) {
f8987c
-			/* no key?  check if there are options for this key */
f8987c
-			int quoted = 0;
f8987c
-			verbose("user_key_allowed: check options: '%s'", cp);
f8987c
-			key_options = cp;
f8987c
-			for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
f8987c
-				if (*cp == '\\' && cp[1] == '"')
f8987c
-					cp++;	/* Skip both */
f8987c
-				else if (*cp == '"')
f8987c
-					quoted = !quoted;
f8987c
-			}
f8987c
-			/* Skip remaining whitespace. */
f8987c
-			for (; *cp == ' ' || *cp == '\t'; cp++)
f8987c
-				;
f8987c
-			if (key_read(found, &cp) != 1) {
f8987c
-				verbose("user_key_allowed: advance: '%s'", cp);
f8987c
-				/* still no key?  advance to next line*/
f8987c
-				continue;
f8987c
-			}
f8987c
-		}
f8987c
-		if (key_equal(found, key)) {
f8987c
-			found_key = 1;
f8987c
-			logit("matching key found: file %s, line %lu",
f8987c
-			    file, linenum);
f8987c
-			fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
f8987c
-			logit("Found matching %s key: %s",
f8987c
-			    key_type(found), fp);
f8987c
-			free(fp);
f8987c
-			break;
f8987c
-		}
f8987c
-	}
f8987c
-	fclose(f);
f8987c
-	key_free(found);
f8987c
-	if (!found_key)
f8987c
-		verbose("key not found");
f8987c
-	return found_key;
f8987c
+        return 0;
f8987c
+    }
f8987c
+
f8987c
+    /* Open the file containing the authorized keys. */
f8987c
+    f = fopen(file, "r");
f8987c
+    if(!f) {
f8987c
+        return 0;
f8987c
+    }
f8987c
+
f8987c
+    if(secure_filename(f, file, pw, buf, sizeof(buf)) != 0) {
f8987c
+        fclose(f);
f8987c
+        logit("Authentication refused: %s", buf);
f8987c
+        return 0;
f8987c
+    }
f8987c
+
f8987c
+    found_key = pamsshagentauth_check_authkeys_file(f, file, key);
f8987c
+    fclose(f);
f8987c
+    return found_key;
f8987c
+}
f8987c
+
f8987c
+/* 
f8987c
+ * Checks whether key is allowed in output of command.
f8987c
+ * returns 1 if the key is allowed or 0 otherwise.
f8987c
+ */
f8987c
+int
f8987c
+pam_user_key_command_allowed2(char *authorized_keys_command,
f8987c
+                          char *authorized_keys_command_user,
f8987c
+                          struct passwd *user_pw, Key * key)
f8987c
+{
f8987c
+    FILE *f;
f8987c
+    int ok, found_key = 0;
f8987c
+    struct passwd *pw;
f8987c
+    struct stat st;
f8987c
+    int status, devnull, p[2], i;
f8987c
+    pid_t pid;
f8987c
+    char errmsg[512];
f8987c
+    char username[512] = { 0 };
f8987c
+    
f8987c
+
f8987c
+
f8987c
+    if(authorized_keys_command == NULL || authorized_keys_command[0] != '/')
f8987c
+        return 0;
f8987c
+
f8987c
+
f8987c
+    /* getpwnam of authorized_keys_command_user will overwrite the statics used by getpwnam (including pw_name) */
f8987c
+    strncpy(username, user_pw->pw_name, sizeof(username) - 1);
f8987c
+
f8987c
+    /* If no user specified to run commands the default to target user */
f8987c
+    if(authorized_keys_command_user == NULL) {
f8987c
+        pw = user_pw;
f8987c
+    }
f8987c
+    else {
f8987c
+        pw = getpwnam(authorized_keys_command_user);
f8987c
+        if(pw == NULL) {
f8987c
+            error("authorized_keys_command_user \"%s\" not found: %s",
f8987c
+                 authorized_keys_command_user, strerror(errno));
f8987c
+            return 0;
f8987c
+        }
f8987c
+    }
f8987c
+
f8987c
+    temporarily_use_uid(pw);
f8987c
+
f8987c
+    if(stat(authorized_keys_command, &st) < 0) {
f8987c
+        error
f8987c
+            ("Could not stat AuthorizedKeysCommand \"%s\": %s",
f8987c
+             authorized_keys_command, strerror(errno));
f8987c
+        goto out;
f8987c
+    }
f8987c
+    if(pamsshagentauth_auth_secure_path
f8987c
+       (authorized_keys_command, &st, NULL, 0, errmsg, sizeof(errmsg)) != 0) {
f8987c
+        error("Unsafe AuthorizedKeysCommand: %s", errmsg);
f8987c
+        goto out;
f8987c
+    }
f8987c
+
f8987c
+    /* open the pipe and read the keys */
f8987c
+    if(pipe(p) != 0) {
f8987c
+        error("%s: pipe: %s", __func__, strerror(errno));
f8987c
+        goto out;
f8987c
+    }
f8987c
+
f8987c
+    debug("Running AuthorizedKeysCommand: \"%s\" as \"%s\" with argument: \"%s\"",
f8987c
+                          authorized_keys_command, pw->pw_name, username);
f8987c
+
f8987c
+    /* 
f8987c
+     * Don't want to call this in the child, where it can fatal() and
f8987c
+     * run cleanup_exit() code.
f8987c
+     */
f8987c
+    restore_uid();
f8987c
+
f8987c
+    switch ((pid = fork())) {
f8987c
+    case -1:                                              /* error */
f8987c
+        error("%s: fork: %s", __func__, strerror(errno));
f8987c
+        close(p[0]);
f8987c
+        close(p[1]);
f8987c
+        return 0;
f8987c
+    case 0:                                               /* child */
f8987c
+        for(i = 0; i < NSIG; i++)
f8987c
+            signal(i, SIG_DFL);
f8987c
+
f8987c
+        /* do this before the setresuid so thta they can be logged */
f8987c
+        if((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) {
f8987c
+            error("%s: open %s: %s", __func__, _PATH_DEVNULL,
f8987c
+                                     strerror(errno));
f8987c
+            _exit(1);
f8987c
+        }
f8987c
+        if(dup2(devnull, STDIN_FILENO) == -1 || dup2(p[1], STDOUT_FILENO) == -1
f8987c
+           || dup2(devnull, STDERR_FILENO) == -1) {
f8987c
+            error("%s: dup2: %s", __func__, strerror(errno));
f8987c
+            _exit(1);
f8987c
+        }
f8987c
+#if defined(HAVE_SETRESGID) && !defined(BROKEN_SETRESGID)
f8987c
+        if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) {
f8987c
+#else
f8987c
+        if (setgid(pw->pw_gid) != 0 || setegid(pw->pw_gid) != 0) {
f8987c
+#endif
f8987c
+            error("setresgid %u: %s", (u_int) pw->pw_gid,
f8987c
+                                     strerror(errno));
f8987c
+            _exit(1);
f8987c
+        }
f8987c
+
f8987c
+#ifdef HAVE_SETRESUID
f8987c
+        if(setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0) {
f8987c
+#else
f8987c
+        if (setuid(pw->pw_uid) != 0 || seteuid(pw->pw_uid) != 0) {
f8987c
+#endif
f8987c
+            error("setresuid %u: %s", (u_int) pw->pw_uid,
f8987c
+                                     strerror(errno));
f8987c
+            _exit(1);
f8987c
+        }
f8987c
+
f8987c
+        close(p[0]);
f8987c
+        closefrom(STDERR_FILENO + 1);
f8987c
+
f8987c
+        execl(authorized_keys_command, authorized_keys_command, username, (char *)NULL);
f8987c
+
f8987c
+        /* pretty sure this will barf because we are now suid, but since we
f8987c
+           should't reach this anyway, I'll leave it here */
f8987c
+        error("AuthorizedKeysCommand %s exec failed: %s",
f8987c
+                                 authorized_keys_command, strerror(errno));
f8987c
+        _exit(127);
f8987c
+    default:                                              /* parent */
f8987c
+        break;
f8987c
+    }
f8987c
+
f8987c
+    temporarily_use_uid(pw);
f8987c
+
f8987c
+    close(p[1]);
f8987c
+    if((f = fdopen(p[0], "r")) == NULL) {
f8987c
+        error("%s: fdopen: %s", __func__, strerror(errno));
f8987c
+        close(p[0]);
f8987c
+        /* Don't leave zombie child */
f8987c
+        while(waitpid(pid, NULL, 0) == -1 && errno == EINTR);
f8987c
+        goto out;
f8987c
+    }
f8987c
+    ok = pamsshagentauth_check_authkeys_file(f, authorized_keys_command, key);
f8987c
+    fclose(f);
f8987c
+
f8987c
+    while(waitpid(pid, &status, 0) == -1) {
f8987c
+        if(errno != EINTR) {
f8987c
+            error("%s: waitpid: %s", __func__,
f8987c
+                                     strerror(errno));
f8987c
+            goto out;
f8987c
+        }
f8987c
+    }
f8987c
+    if(WIFSIGNALED(status)) {
f8987c
+        error("AuthorizedKeysCommand %s exited on signal %d",
f8987c
+                                 authorized_keys_command, WTERMSIG(status));
f8987c
+        goto out;
f8987c
+    } else if(WEXITSTATUS(status) != 0) {
f8987c
+        error("AuthorizedKeysCommand %s returned status %d",
f8987c
+                                 authorized_keys_command, WEXITSTATUS(status));
f8987c
+        goto out;
f8987c
+    }
f8987c
+    found_key = ok;
f8987c
+  out:
f8987c
+    restore_uid();
f8987c
+    return found_key;
f8987c
 }
f8987c
diff --git a/pam_ssh_agent_auth-0.9.3/pam_user_key_allowed2.h b/pam_ssh_agent_auth-0.9.3/pam_user_key_allowed2.h
f8987c
index 416d055..24533a0 100644
f8987c
--- a/pam_ssh_agent_auth-0.9.3/pam_user_key_allowed2.h
f8987c
+++ b/pam_ssh_agent_auth-0.9.3/pam_user_key_allowed2.h
f8987c
@@ -32,5 +32,6 @@
f8987c
 
f8987c
 #include "identity.h"
f8987c
 int pam_user_key_allowed2(struct passwd *, Key *, char *);
f8987c
+int pam_user_key_command_allowed2(char *, char *, struct passwd *, Key *);
f8987c
 
f8987c
 #endif
f8987c
diff --git a/pam_ssh_agent_auth-0.9.3/secure_filename.c b/pam_ssh_agent_auth-0.9.3/secure_filename.c
f8987c
index c24cab2..d685599 100644
f8987c
--- a/pam_ssh_agent_auth-0.9.3/secure_filename.c
f8987c
+++ b/pam_ssh_agent_auth-0.9.3/secure_filename.c
f8987c
@@ -71,29 +71,38 @@
f8987c
  * Returns 0 on success and -1 on failure
f8987c
  */
f8987c
 int
f8987c
-secure_filename(FILE *f, const char *file, struct passwd *pw,
f8987c
-    char *err, size_t errlen)
f8987c
+pamsshagentauth_auth_secure_path(const char *name, struct stat *stp,
f8987c
+        const char *pw_dir, uid_t uid, char *err, size_t errlen)
f8987c
 {
f8987c
-	uid_t uid = pw->pw_uid;
f8987c
 	char buf[MAXPATHLEN], homedir[MAXPATHLEN];
f8987c
 	char *cp;
f8987c
 	int comparehome = 0;
f8987c
 	struct stat st;
f8987c
 
f8987c
-    verbose("secure_filename: checking for uid: %u", uid);
f8987c
+    verbose("auth_secure_filename: checking for uid: %u", uid);
f8987c
 
f8987c
-	if (realpath(file, buf) == NULL) {
f8987c
-		snprintf(err, errlen, "realpath %s failed: %s", file,
f8987c
+	/* if (realpath(pw->pw_dir, homedir) != NULL) */
f8987c
+    if (realpath(name, buf) == NULL) {
f8987c
+		snprintf(err, errlen, "realpath %s failed: %s", name,
f8987c
 		    strerror(errno));
f8987c
 		return -1;
f8987c
 	}
f8987c
-	if (realpath(pw->pw_dir, homedir) != NULL)
f8987c
+	if (pw_dir != NULL && realpath(pw_dir, homedir) != NULL)
f8987c
 		comparehome = 1;
f8987c
 
f8987c
 	/* check the open file to avoid races */
f8987c
-	if (fstat(fileno(f), &st) < 0 ||
f8987c
-	    (st.st_uid != 0 && st.st_uid != uid) ||
f8987c
-	    (st.st_mode & 022) != 0) {
f8987c
+	/* 
f8987c
+     * if (fstat(fileno(f), &st) < 0 ||
f8987c
+	 *    (st.st_uid != 0 && st.st_uid != uid) ||
f8987c
+	 *    (st.st_mode & 022) != 0) {
f8987c
+    */
f8987c
+    if (!S_ISREG(stp->st_mode)) {
f8987c
+        snprintf(err, errlen, "%s is not a regular file", buf);
f8987c
+        return -1;
f8987c
+    }
f8987c
+
f8987c
+    if ((stp->st_uid != 0 && stp->st_uid != uid) ||
f8987c
+            (stp->st_mode & 022) != 0) {
f8987c
 		snprintf(err, errlen, "bad ownership or modes for file %s",
f8987c
 		    buf);
f8987c
 		return -1;
f8987c
@@ -132,3 +141,25 @@ secure_filename(FILE *f, const char *file, struct passwd *pw,
f8987c
 	return 0;
f8987c
 }
f8987c
 
f8987c
+/*
f8987c
+ * Version of secure_path() that accepts an open file descriptor to
f8987c
+ * avoid races.
f8987c
+ *
f8987c
+ * Returns 0 on success and -1 on failure
f8987c
+ */
f8987c
+int
f8987c
+secure_filename(FILE *f, const char *file, struct passwd *pw,
f8987c
+    char *err, size_t errlen)
f8987c
+{
f8987c
+   struct stat st;
f8987c
+   char buf[MAXPATHLEN] = { 0 };
f8987c
+
f8987c
+   /* check the open file to avoid races */
f8987c
+   if (fstat(fileno(f), &st) < 0) {
f8987c
+       snprintf(err, errlen, "cannot stat file %s: %s",
f8987c
+           buf, strerror(errno));
f8987c
+       return -1;
f8987c
+   }
f8987c
+   return pamsshagentauth_auth_secure_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen);
f8987c
+}
f8987c
+
f8987c
diff --git a/pam_ssh_agent_auth-0.9.3/secure_filename.h b/pam_ssh_agent_auth-0.9.3/secure_filename.h
f8987c
index 198c13d..4c1a208 100644
f8987c
--- a/pam_ssh_agent_auth-0.9.3/secure_filename.h
f8987c
+++ b/pam_ssh_agent_auth-0.9.3/secure_filename.h
f8987c
@@ -28,5 +28,7 @@
f8987c
 #define _SECURE_FILENAME_H
f8987c
 #include <pwd.h>
f8987c
 #include <stdio.h>
f8987c
+struct stat;
f8987c
 int secure_filename(FILE *, const char *, struct passwd *, char *, size_t);
f8987c
+int pamsshagentauth_auth_secure_path(const char *, struct stat *, const char *, uid_t, char *, size_t);
f8987c
 #endif
f8987c
diff --git a/pam_ssh_agent_auth-0.9.3/userauth_pubkey_from_id.c b/pam_ssh_agent_auth-0.9.3/userauth_pubkey_from_id.c
f8987c
index 163278b..31849f8 100644
f8987c
--- a/pam_ssh_agent_auth-0.9.3/userauth_pubkey_from_id.c
f8987c
+++ b/pam_ssh_agent_auth-0.9.3/userauth_pubkey_from_id.c
f8987c
@@ -48,11 +48,14 @@
f8987c
 #include "identity.h"
f8987c
 #include "pam_user_authorized_keys.h"
f8987c
 
f8987c
-extern u_char  *session_id2;
f8987c
+#define SSH2_MSG_USERAUTH_TRUST_REQUEST          54
f8987c
+
f8987c
+/* extern u_char  *session_id2;
f8987c
 extern uint8_t  session_id_len;
f8987c
+ */
f8987c
 
f8987c
 int
f8987c
-userauth_pubkey_from_id(Identity * id)
f8987c
+userauth_pubkey_from_id(const char *ruser, Identity * id, Buffer * session_id2)
f8987c
 {
f8987c
     Buffer          b = { 0 };
f8987c
     char           *pkalg = NULL;
f8987c
@@ -63,7 +66,7 @@ userauth_pubkey_from_id(Identity * id)
f8987c
     pkalg = (char *) key_ssh_name(id->key);
f8987c
 
f8987c
     /* first test if this key is even allowed */
f8987c
-    if(! pam_user_key_allowed(id->key))
f8987c
+    if(! pam_user_key_allowed(ruser, id->key))
f8987c
         goto user_auth_clean_exit;
f8987c
 
f8987c
     if(key_to_blob(id->key, &pkblob, &blen) == 0)
f8987c
@@ -72,10 +75,10 @@ userauth_pubkey_from_id(Identity * id)
f8987c
     /* construct packet to sign and test */
f8987c
     buffer_init(&b);
f8987c
 
f8987c
-    buffer_put_string(&b, session_id2, session_id_len);
f8987c
-    buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
f8987c
-    buffer_put_cstring(&b, "root");
f8987c
-    buffer_put_cstring(&b, "ssh-userauth");
f8987c
+    buffer_put_string(&b, session_id2->buf + session_id2->offset, session_id2->end - session_id2->offset);
f8987c
+    buffer_put_char(&b, SSH2_MSG_USERAUTH_TRUST_REQUEST); 
f8987c
+    buffer_put_cstring(&b, ruser);
f8987c
+    buffer_put_cstring(&b, "pam_ssh_agent_auth");
f8987c
     buffer_put_cstring(&b, "publickey");
f8987c
     buffer_put_char(&b, 1);
f8987c
     buffer_put_cstring(&b, pkalg);
f8987c
@@ -89,8 +92,7 @@ userauth_pubkey_from_id(Identity * id)
f8987c
         authenticated = 1;
f8987c
 
f8987c
   user_auth_clean_exit:
f8987c
-    if(&b != NULL)
f8987c
-        buffer_free(&b);
f8987c
+    buffer_free(&b);
f8987c
     if(sig != NULL)
f8987c
         free(sig);
f8987c
     if(pkblob != NULL)
f8987c
diff --git a/pam_ssh_agent_auth-0.9.3/userauth_pubkey_from_id.h b/pam_ssh_agent_auth-0.9.3/userauth_pubkey_from_id.h
f8987c
index 1e14231..7758808 100644
f8987c
--- a/pam_ssh_agent_auth-0.9.3/userauth_pubkey_from_id.h
f8987c
+++ b/pam_ssh_agent_auth-0.9.3/userauth_pubkey_from_id.h
f8987c
@@ -32,6 +32,6 @@
f8987c
 #define _USERAUTH_PUBKEY_FROM_ID_H
f8987c
 
f8987c
 #include <identity.h>
f8987c
-int userauth_pubkey_from_id(Identity *);
f8987c
+int userauth_pubkey_from_id(const char *, Identity *, Buffer *);
f8987c
 
f8987c
 #endif
f8987c
-- 
f8987c
2.5.0
f8987c
f8987c
--- openssh-6.6p1/pam_ssh_agent_auth-0.9.3/pam_user_authorized_keys.c.psaa-command	2016-04-20 09:31:32.164686370 +0200
f8987c
+++ openssh-6.6p1/pam_ssh_agent_auth-0.9.3/pam_user_authorized_keys.c	2016-04-20 09:35:49.778344576 +0200
f8987c
@@ -145,8 +145,12 @@
f8987c
 int
f8987c
 pam_user_key_allowed(const char *ruser, Key * key)
f8987c
 {
f8987c
-    return pam_user_key_allowed2(getpwuid(authorized_keys_file_allowed_owner_uid), key, authorized_keys_file)
f8987c
-        || pam_user_key_allowed2(getpwuid(0), key, authorized_keys_file)
f8987c
+    struct passwd *pw;
f8987c
+    return
f8987c
+        ((pw = getpwuid(authorized_keys_file_allowed_owner_uid)) &&
f8987c
+            pam_user_key_allowed2(pw, key, authorized_keys_file))
f8987c
+        || ((pw = getpwuid(0)) &&
f8987c
+            pam_user_key_allowed2(pw, key, authorized_keys_file))
f8987c
         || pam_user_key_command_allowed2(authorized_keys_command,
f8987c
                                          authorized_keys_command_user,
f8987c
                                          getpwnam(ruser), key);