Petr Šabata 81d24c
diff -up openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-build openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c
Petr Šabata 81d24c
--- openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-build	2016-11-13 04:24:32.000000000 +0100
Petr Šabata 81d24c
+++ openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c	2017-02-07 14:29:41.626116675 +0100
Petr Šabata 81d24c
@@ -43,12 +43,31 @@
Petr Šabata 81d24c
 #include <openssl/evp.h>
Petr Šabata 81d24c
 #include "ssh2.h"
Petr Šabata 81d24c
 #include "misc.h"
Petr Šabata 81d24c
+#include "ssh.h"
Petr Šabata 81d24c
+#include <sys/types.h>
Petr Šabata 81d24c
+#include <sys/stat.h>
Petr Šabata 81d24c
+#include <sys/socket.h>
Petr Šabata 81d24c
+#include <sys/un.h>
Petr Šabata 81d24c
+#include <unistd.h>
Petr Šabata 81d24c
+#include <stdlib.h>
Petr Šabata 81d24c
+#include <errno.h>
Petr Šabata 81d24c
+#include <fcntl.h>
Petr Šabata 81d24c
 
Petr Šabata 81d24c
 #include "userauth_pubkey_from_id.h"
Petr Šabata 81d24c
 #include "identity.h"
Petr Šabata 81d24c
 #include "get_command_line.h"
Petr Šabata 81d24c
 extern char **environ;
Petr Šabata 81d24c
 
Petr Šabata 81d24c
+/* 
Petr Šabata 81d24c
+ * Added by Jamie Beverly, ensure socket fd points to a socket owned by the user 
Petr Šabata 81d24c
+ * A cursory check is done, but to avoid race conditions, it is necessary 
Petr Šabata 81d24c
+ * to drop effective UID when connecting to the socket. 
Petr Šabata 81d24c
+ *
Petr Šabata 81d24c
+ * If the cause of error is EACCES, because we verified we would not have that 
Petr Šabata 81d24c
+ * problem initially, we can safely assume that somebody is attempting to find a 
Petr Šabata 81d24c
+ * race condition; so a more "direct" log message is generated.
Petr Šabata 81d24c
+ */
Petr Šabata 81d24c
+
Petr Šabata 81d24c
 static char *
Petr Šabata 81d24c
 log_action(char ** action, size_t count)
Petr Šabata 81d24c
 {
Petr Šabata 81d24c
@@ -85,7 +104,7 @@ void
Petr Šabata 81d24c
 pamsshagentauth_session_id2_gen(Buffer * session_id2, const char * user,
Petr Šabata 81d24c
                                 const char * ruser, const char * servicename)
Petr Šabata 81d24c
 {
Petr Šabata 81d24c
-    char *cookie = NULL;
Petr Šabata 81d24c
+    u_char *cookie = NULL;
Petr Šabata 81d24c
     uint8_t i = 0;
Petr Šabata 81d24c
     uint32_t rnd = 0;
Petr Šabata 81d24c
     uint8_t cookie_len;
Petr Šabata 81d24c
@@ -112,7 +131,7 @@ pamsshagentauth_session_id2_gen(Buffer *
Petr Šabata 81d24c
         if (i % 4 == 0) {
Petr Šabata 81d24c
             rnd = pamsshagentauth_arc4random();
Petr Šabata 81d24c
         }
Petr Šabata 81d24c
-        cookie[i] = (char) rnd;
Petr Šabata 81d24c
+        cookie[i] = (u_char) rnd;
Petr Šabata 81d24c
         rnd >>= 8;
Petr Šabata 81d24c
     }
Petr Šabata 81d24c
 
Petr Šabata 81d24c
@@ -177,6 +196,86 @@ pamsshagentauth_session_id2_gen(Buffer *
Petr Šabata 81d24c
 }
Petr Šabata 81d24c
 
Petr Šabata 81d24c
 int
Petr Šabata 81d24c
+ssh_get_authentication_socket_for_uid(uid_t uid)
Petr Šabata 81d24c
+{
Petr Šabata 81d24c
+	const char *authsocket;
Petr Šabata 81d24c
+	int sock;
Petr Šabata 81d24c
+	struct sockaddr_un sunaddr;
Petr Šabata 81d24c
+	struct stat sock_st;
Petr Šabata 81d24c
+
Petr Šabata 81d24c
+	authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);
Petr Šabata 81d24c
+	if (!authsocket)
Petr Šabata 81d24c
+		return -1;
Petr Šabata 81d24c
+
Petr Šabata 81d24c
+	/* Advisory only; seteuid ensures no race condition; but will only log if we see EACCES */
Petr Šabata 81d24c
+	if( stat(authsocket,&sock_st) == 0) {
Petr Šabata 81d24c
+		if(uid != 0 && sock_st.st_uid != uid) {
Petr Šabata 81d24c
+			fatal("uid %lu attempted to open an agent socket owned by uid %lu", (unsigned long) uid, (unsigned long) sock_st.st_uid);
Petr Šabata 81d24c
+			return -1;
Petr Šabata 81d24c
+		}
Petr Šabata 81d24c
+	}
Petr Šabata 81d24c
+
Petr Šabata 81d24c
+	/* 
Petr Šabata 81d24c
+	 * Ensures that the EACCES tested for below can _only_ happen if somebody 
Petr Šabata 81d24c
+	 * is attempting to race the stat above to bypass authentication.
Petr Šabata 81d24c
+	 */
Petr Šabata 81d24c
+	if( (sock_st.st_mode & S_IWUSR) != S_IWUSR || (sock_st.st_mode & S_IRUSR) != S_IRUSR) {
Petr Šabata 81d24c
+		error("ssh-agent socket has incorrect permissions for owner");
Petr Šabata 81d24c
+		return -1;
Petr Šabata 81d24c
+	}
Petr Šabata 81d24c
+
Petr Šabata 81d24c
+	sunaddr.sun_family = AF_UNIX;
Petr Šabata 81d24c
+	strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));
Petr Šabata 81d24c
+
Petr Šabata 81d24c
+	sock = socket(AF_UNIX, SOCK_STREAM, 0);
Petr Šabata 81d24c
+	if (sock < 0)
Petr Šabata 81d24c
+		return -1;
Petr Šabata 81d24c
+
Petr Šabata 81d24c
+	/* close on exec */
Petr Šabata 81d24c
+	if (fcntl(sock, F_SETFD, 1) == -1) {
Petr Šabata 81d24c
+		close(sock);
Petr Šabata 81d24c
+		return -1;
Petr Šabata 81d24c
+	}
Petr Šabata 81d24c
+
Petr Šabata 81d24c
+	errno = 0; 
Petr Šabata 81d24c
+	seteuid(uid); /* To ensure a race condition is not used to circumvent the stat
Petr Šabata 81d24c
+	             above, we will temporarily drop UID to the caller */
Petr Šabata 81d24c
+	if (connect(sock, (struct sockaddr *)&sunaddr, sizeof sunaddr) < 0) {
Petr Šabata 81d24c
+		close(sock);
Petr Šabata 81d24c
+        if(errno == EACCES)
Petr Šabata 81d24c
+		fatal("MAJOR SECURITY WARNING: uid %lu made a deliberate and malicious attempt to open an agent socket owned by another user", (unsigned long) uid);
Petr Šabata 81d24c
+		return -1;
Petr Šabata 81d24c
+	}
Petr Šabata 81d24c
+
Petr Šabata 81d24c
+	seteuid(0); /* we now continue the regularly scheduled programming */
Petr Šabata 81d24c
+
Petr Šabata 81d24c
+	return sock;
Petr Šabata 81d24c
+}
Petr Šabata 81d24c
+
Petr Šabata 81d24c
+AuthenticationConnection *
Petr Šabata 81d24c
+ssh_get_authentication_connection_for_uid(uid_t uid)
Petr Šabata 81d24c
+{
Petr Šabata 81d24c
+	AuthenticationConnection *auth;
Petr Šabata 81d24c
+	int sock;
Petr Šabata 81d24c
+
Petr Šabata 81d24c
+	sock = ssh_get_authentication_socket_for_uid(uid);
Petr Šabata 81d24c
+
Petr Šabata 81d24c
+	/*
Petr Šabata 81d24c
+	 * Fail if we couldn't obtain a connection.  This happens if we
Petr Šabata 81d24c
+	 * exited due to a timeout.
Petr Šabata 81d24c
+	 */
Petr Šabata 81d24c
+	if (sock < 0)
Petr Šabata 81d24c
+		return NULL;
Petr Šabata 81d24c
+
Petr Šabata 81d24c
+	auth = xmalloc(sizeof(*auth));
Petr Šabata 81d24c
+	auth->fd = sock;
Petr Šabata 81d24c
+	buffer_init(&auth->identities);
Petr Šabata 81d24c
+	auth->howmany = 0;
Petr Šabata 81d24c
+
Petr Šabata 81d24c
+	return auth;
Petr Šabata 81d24c
+}
Petr Šabata 81d24c
+
Petr Šabata 81d24c
+int
Petr Šabata 81d24c
 pamsshagentauth_find_authorized_keys(const char * user, const char * ruser, const char * servicename)
Petr Šabata 81d24c
 {
Petr Šabata 81d24c
     Buffer session_id2 = { 0 };
Petr Šabata 81d24c
@@ -190,7 +289,7 @@ pamsshagentauth_find_authorized_keys(con
Petr Šabata 81d24c
     OpenSSL_add_all_digests();
Petr Šabata 81d24c
     pamsshagentauth_session_id2_gen(&session_id2, user, ruser, servicename);
Petr Šabata 81d24c
 
Petr Šabata 81d24c
-    if ((ac = ssh_get_authentication_connection(uid))) {
Petr Šabata 81d24c
+    if ((ac = ssh_get_authentication_connection_for_uid(uid))) {
Petr Šabata 81d24c
         pamsshagentauth_verbose("Contacted ssh-agent of user %s (%u)", ruser, uid);
Petr Šabata 81d24c
         for (key = ssh_get_first_identity(ac, &comment, 2); key != NULL; key = ssh_get_next_identity(ac, &comment, 2)) 
Petr Šabata 81d24c
         {
Petr Šabata 81d24c
diff -up openssh-7.4p1/pam_ssh_agent_auth-0.10.3/Makefile.in.psaa-build openssh-7.4p1/pam_ssh_agent_auth-0.10.3/Makefile.in
Petr Šabata 81d24c
--- openssh-7.4p1/pam_ssh_agent_auth-0.10.3/Makefile.in.psaa-build	2016-11-13 04:24:32.000000000 +0100
Petr Šabata 81d24c
+++ openssh-7.4p1/pam_ssh_agent_auth-0.10.3/Makefile.in	2017-02-07 14:40:14.407566921 +0100
Petr Šabata 81d24c
@@ -52,7 +52,7 @@ PATHS=
Petr Šabata 81d24c
 CC=@CC@
Petr Šabata 81d24c
 LD=@LD@
Petr Šabata 81d24c
 CFLAGS=@CFLAGS@
Petr Šabata 81d24c
-CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@
Petr Šabata 81d24c
+CPPFLAGS=-I.. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@
Petr Šabata 81d24c
 LIBS=@LIBS@
Petr Šabata 81d24c
 AR=@AR@
Petr Šabata 81d24c
 AWK=@AWK@
Petr Šabata 81d24c
@@ -61,8 +61,8 @@ INSTALL=@INSTALL@
Petr Šabata 81d24c
 PERL=@PERL@
Petr Šabata 81d24c
 SED=@SED@
Petr Šabata 81d24c
 ENT=@ENT@
Petr Šabata 81d24c
-LDFLAGS=-L. -Lopenbsd-compat/ @LDFLAGS@
Petr Šabata 81d24c
-LDFLAGS_SHARED = @LDFLAGS_SHARED@
Petr Šabata 81d24c
+LDFLAGS=-L.. -L../openbsd-compat/ @LDFLAGS@
Petr Šabata 81d24c
+LDFLAGS_SHARED =-Wl,-z,defs @LDFLAGS_SHARED@
Petr Šabata 81d24c
 EXEEXT=@EXEEXT@
Petr Šabata 81d24c
 
Petr Šabata 81d24c
 INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@
Petr Šabata 81d24c
@@ -74,7 +74,7 @@ SSHOBJS=xmalloc.o atomicio.o authfd.o bu
Petr Šabata 81d24c
 
Petr Šabata 81d24c
 ED25519OBJS=ed25519-donna/ed25519.o
Petr Šabata 81d24c
 
Petr Šabata 81d24c
-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 get_command_line.o userauth_pubkey_from_pam.o
Petr Šabata 81d24c
+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 get_command_line.o userauth_pubkey_from_pam.o secure_filename.o
Petr Šabata 81d24c
 
Petr Šabata 81d24c
 
Petr Šabata 81d24c
 MANPAGES_IN	= pam_ssh_agent_auth.pod
Petr Šabata 81d24c
@@ -94,13 +94,13 @@ $(PAM_MODULES): Makefile.in config.h
Petr Šabata 81d24c
 .c.o:
Petr Šabata 81d24c
 	$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
Petr Šabata 81d24c
 
Petr Šabata 81d24c
-LIBCOMPAT=openbsd-compat/libopenbsd-compat.a
Petr Šabata 81d24c
+LIBCOMPAT=../openbsd-compat/libopenbsd-compat.a
Petr Šabata 81d24c
 $(LIBCOMPAT): always
Petr Šabata 81d24c
 	(cd openbsd-compat && $(MAKE))
Petr Šabata 81d24c
 always:
Petr Šabata 81d24c
 
Petr Šabata 81d24c
-pam_ssh_agent_auth.so: $(LIBCOMPAT) $(SSHOBJS) $(ED25519OBJS) $(PAM_SSH_AGENT_AUTH_OBJS)  pam_ssh_agent_auth.o
Petr Šabata 81d24c
-	$(LD) $(LDFLAGS_SHARED) -o $@ $(SSHOBJS) $(ED25519OBJS) $(PAM_SSH_AGENT_AUTH_OBJS) $(LDFLAGS) -lopenbsd-compat pam_ssh_agent_auth.o $(LIBS) -lpam
Petr Šabata 81d24c
+pam_ssh_agent_auth.so: $(PAM_SSH_AGENT_AUTH_OBJS)  pam_ssh_agent_auth.o ../uidswap.o ../ssh-sk-client.o
Petr Šabata 81d24c
+	$(LD) $(LDFLAGS_SHARED) -o $@ $(PAM_SSH_AGENT_AUTH_OBJS) ../ssh-sk-client.o $(LDFLAGS) -lssh -lopenbsd-compat pam_ssh_agent_auth.o ../uidswap.o $(LIBS) -lpam
Petr Šabata 81d24c
 
Petr Šabata 81d24c
 $(MANPAGES): $(MANPAGES_IN)
Petr Šabata 81d24c
 	pod2man --section=8 --release=v0.10.3 --name=pam_ssh_agent_auth --official --center "PAM" pam_ssh_agent_auth.pod > pam_ssh_agent_auth.8