components/openssh/patches/041-pam_ctx_preserve.patch
changeset 6930 31ef2580c45d
parent 5612 ece68a956e2f
child 7649 69d7508f0d66
--- a/components/openssh/patches/041-pam_ctx_preserve.patch	Mon Sep 19 14:01:08 2016 -0700
+++ b/components/openssh/patches/041-pam_ctx_preserve.patch	Tue Sep 20 03:54:40 2016 -0700
@@ -22,11 +22,10 @@
 # Reported upstream:
 # https://bugzilla.mindrot.org/show_bug.cgi?id=2548
 #
-
 diff -pur old/auth-pam.c new/auth-pam.c
 --- old/auth-pam.c
 +++ new/auth-pam.c
-@@ -97,6 +97,7 @@
+@@ -98,6 +98,7 @@
  #include "ssh-gss.h"
  #endif
  #include "monitor_wrap.h"
@@ -34,7 +33,7 @@
  
  extern ServerOptions options;
  extern Buffer loginmsg;
-@@ -109,38 +110,26 @@ extern u_int utmp_len;
+@@ -110,38 +111,26 @@ extern u_int utmp_len;
  #endif
  
  /*
@@ -83,7 +82,7 @@
  static mysig_t sshpam_oldsig;
  
  static void
-@@ -149,78 +138,22 @@ sshpam_sigchld_handler(int sig)
+@@ -150,85 +139,25 @@ sshpam_sigchld_handler(int sig)
  	signal(SIGCHLD, SIG_DFL);
  	if (cleanup_ctxt == NULL)
  		return;	/* handler called after PAM cleanup, shouldn't happen */
@@ -92,12 +91,16 @@
  	    <= 0) {
 -		/* PAM thread has not exitted, privsep slave must have */
 -		kill(cleanup_ctxt->pam_thread, SIGTERM);
--		if (waitpid(cleanup_ctxt->pam_thread, &sshpam_thread_status, 0)
+-		while (waitpid(cleanup_ctxt->pam_thread,
+-		    &sshpam_thread_status, 0) == -1) {
 +		/* callback child has not exited, privsep slave must have */
 +		kill(cleanup_ctxt->pam_child, SIGTERM);
-+		if (waitpid(cleanup_ctxt->pam_child, &sshpam_child_status, 0)
- 		    <= 0)
- 			return; /* could not wait */
++		while (waitpid(cleanup_ctxt->pam_child,
++		    &sshpam_child_status, 0) == -1) {
+ 			if (errno == EINTR)
+ 				continue;
+ 			return;
+ 		}
  	}
 -	if (WIFSIGNALED(sshpam_thread_status) &&
 -	    WTERMSIG(sshpam_thread_status) == SIGTERM)
@@ -158,7 +161,11 @@
 -	if (sshpam_thread_status != -1)
 -		return (sshpam_thread_status);
 -	signal(SIGCHLD, sshpam_oldsig);
--	waitpid(thread, &status, 0);
+-	while (waitpid(thread, &status, 0) == -1) {
+-		if (errno == EINTR)
+-			continue;
+-		fatal("%s: waitpid: %s", __func__, strerror(errno));
+-	}
 -	return (status);
 +	if (WIFSIGNALED(sshpam_child_status) &&
 +	    WTERMSIG(sshpam_child_status) == SIGTERM)
@@ -173,7 +180,7 @@
  
  static pam_handle_t *sshpam_handle = NULL;
  static int sshpam_err = 0;
-@@ -290,55 +223,11 @@ sshpam_password_change_required(int reqd
+@@ -298,55 +227,11 @@ sshpam_password_change_required(int reqd
  	}
  }
  
@@ -231,7 +238,7 @@
      struct pam_response **resp, void *data)
  {
  	Buffer buffer;
-@@ -420,48 +309,84 @@ sshpam_thread_conv(int n, sshpam_const s
+@@ -411,48 +296,85 @@ sshpam_thread_conv(int n, sshpam_const s
  }
  
  /*
@@ -310,15 +317,15 @@
 +	close(ctxt->pam_csock);
 +	ctxt->pam_csock = -1;
 +}
-+
+ 
+-	sshpam_conv.conv = sshpam_thread_conv;
 +int
 +get_pam_done(void *ctxt)
 +{
 +	struct pam_ctxt *pctxt = (struct pam_ctxt *)ctxt;
 +	return (pctxt->pam_done);
 +}
- 
--	sshpam_conv.conv = sshpam_thread_conv;
++
 +/*
 + * Perform PAM authentication.
 + *
@@ -333,6 +340,7 @@
 +	struct pam_conv sshpam_conv;
 +	int flags = (options.permit_empty_passwd == 0 ?
 +	    PAM_DISALLOW_NULL_AUTHTOK : 0);
++	struct ssh *ssh = active_state; /* XXX */
 +
 +	sshpam_conv.conv = sshpam_child_conv;
  	sshpam_conv.appdata_ptr = ctxt;
@@ -346,7 +354,7 @@
  	sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
  	    (const void *)&sshpam_conv);
  	if (sshpam_err != PAM_SUCCESS)
-@@ -484,60 +409,34 @@ sshpam_thread(void *ctxtp)
+@@ -477,63 +399,35 @@ sshpam_thread(void *ctxtp)
  		}
  	}
  
@@ -385,6 +393,8 @@
 -	/* XXX - can't do much about an error here */
 -	if (sshpam_err == PAM_ACCT_EXPIRED)
 -		ssh_msg_send(ctxt->pam_csock, PAM_ACCT_EXPIRED, &buffer);
+-	else if (sshpam_maxtries_reached)
+-		ssh_msg_send(ctxt->pam_csock, PAM_MAXTRIES, &buffer);
 -	else
 -		ssh_msg_send(ctxt->pam_csock, PAM_AUTH_ERR, &buffer);
 -	buffer_free(&buffer);
@@ -396,7 +406,7 @@
 +		    pam_strerror(sshpam_handle, sshpam_err),
 +		    sshpam_authctxt->valid ? "" : "illegal user ",
 +		    sshpam_authctxt->user,
-+		    get_remote_name_or_ip(utmp_len, options.use_dns));
++		    auth_get_canonical_hostname(ssh, options.use_dns));
 +	relieve_from_duty(ctxt);
  }
  
@@ -413,6 +423,7 @@
 -		close(ctxt->pam_psock);
 -		close(ctxt->pam_csock);
 -		memset(ctxt, 0, sizeof(*ctxt));
+-		cleanup_ctxt = NULL;
 +	if (ctxt != NULL && ctxt->pam_child != 0) {
 +		signal(SIGCHLD, sshpam_oldsig);
 +		/* callback child should have had exited by now */
@@ -423,18 +434,19 @@
 +			close(ctxt->pam_csock);
 +		if (sshpam_child_status == -1)
 +			waitpid(ctxt->pam_child, &sshpam_child_status, 0);
- 		cleanup_ctxt = NULL;
++ 		cleanup_ctxt = NULL;
  	}
  }
-@@ -686,7 +585,6 @@ derive_pam_service_name(Authctxt *authct
+ 
+@@ -681,7 +575,6 @@ derive_pam_service_name(Authctxt *authct
  static int
  sshpam_init(Authctxt *authctxt)
  {
 -	extern char *__progname;
  	const char *pam_rhost, *pam_user, *user = authctxt->user;
  	const char **ptr_pam_user = &pam_user;
- 
-@@ -792,6 +690,7 @@ sshpam_init_ctx(Authctxt *authctxt)
+ 	struct ssh *ssh = active_state; /* XXX */
+@@ -788,6 +681,7 @@ sshpam_init_ctx(Authctxt *authctxt)
  {
  	struct pam_ctxt *ctxt;
  	int socks[2];
@@ -442,7 +454,7 @@
  
  	debug3("PAM: %s entering", __func__);
  	/*
-@@ -809,7 +708,7 @@ sshpam_init_ctx(Authctxt *authctxt)
+@@ -805,7 +699,7 @@ sshpam_init_ctx(Authctxt *authctxt)
  
  	ctxt = xcalloc(1, sizeof *ctxt);
  
@@ -451,7 +463,7 @@
  	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, socks) == -1) {
  		error("PAM: failed create sockets: %s", strerror(errno));
  		free(ctxt);
-@@ -817,15 +716,29 @@ sshpam_init_ctx(Authctxt *authctxt)
+@@ -813,15 +707,29 @@ sshpam_init_ctx(Authctxt *authctxt)
  	}
  	ctxt->pam_psock = socks[0];
  	ctxt->pam_csock = socks[1];
@@ -485,11 +497,10 @@
  	return (ctxt);
  }
  
-@@ -839,8 +752,11 @@ sshpam_query(void *ctx, char **name, cha
+@@ -836,8 +744,10 @@ sshpam_query(void *ctx, char **name, cha
  	u_char type;
  	char *msg;
  	size_t len, mlen;
-+	struct ssh *ssh;
 +	int r;
  
  	debug3("PAM: %s entering", __func__);
@@ -497,7 +508,7 @@
  	buffer_init(&buffer);
  	*name = xstrdup("");
  	*info = xstrdup("");
-@@ -848,6 +764,17 @@ sshpam_query(void *ctx, char **name, cha
+@@ -845,6 +755,17 @@ sshpam_query(void *ctx, char **name, cha
  	**prompts = NULL;
  	plen = 0;
  	*echo_on = xmalloc(sizeof(u_int));
@@ -515,7 +526,7 @@
  	while (ssh_msg_recv(ctxt->pam_psock, &buffer) == 0) {
  		type = buffer_get_char(&buffer);
  		msg = buffer_get_string(&buffer, NULL);
-@@ -879,15 +806,6 @@ sshpam_query(void *ctx, char **name, cha
+@@ -880,15 +801,6 @@ sshpam_query(void *ctx, char **name, cha
  			/* FALLTHROUGH */
  		case PAM_AUTH_ERR:
  			debug3("PAM: %s", pam_strerror(sshpam_handle, type));
@@ -531,7 +542,7 @@
  			/* FALLTHROUGH */
  		case PAM_SUCCESS:
  			if (**prompts != NULL) {
-@@ -898,25 +816,21 @@ sshpam_query(void *ctx, char **name, cha
+@@ -899,25 +811,20 @@ sshpam_query(void *ctx, char **name, cha
  				free(**prompts);
  				**prompts = NULL;
  			}
@@ -553,16 +564,15 @@
 +			buffer_put_cstring(&buffer, buffer_ptr(&loginmsg));
 +			if (!use_privsep) {
 +				/* sync packet state with parrent */
-+				ssh = active_state;
 +				r = ssh_packet_get_state(ssh, &buffer);
 +				if (r != 0)
 +					fatal("%s: get_state failed: %s",
-+					   __func__, ssh_err(r));
++					    __func__, ssh_err(r));
  			}
 -			error("PAM: %s for %s%.100s from %.100s", msg,
 -			    sshpam_authctxt->valid ? "" : "illegal user ",
 -			    sshpam_authctxt->user,
--			    get_remote_name_or_ip(utmp_len, options.use_dns));
+-			    auth_get_canonical_hostname(ssh, options.use_dns));
 -			/* FALLTHROUGH */
 +			ssh_msg_send(ctxt->pam_psock, type, &buffer);
 +			/* callback child ends here */
@@ -571,7 +581,7 @@
  		default:
  			*num = 0;
  			**echo_on = 0;
-@@ -970,7 +884,7 @@ sshpam_free_ctx(void *ctxtp)
+@@ -997,7 +904,7 @@ sshpam_free_ctx(void *ctxtp)
  	struct pam_ctxt *ctxt = ctxtp;
  
  	debug3("PAM: %s entering", __func__);
@@ -583,22 +593,20 @@
 diff -pur old/auth-pam.h new/auth-pam.h
 --- old/auth-pam.h
 +++ new/auth-pam.h
-@@ -45,9 +45,10 @@ int do_pam_putenv(char *, char *);
+@@ -45,7 +45,8 @@ int do_pam_putenv(char *, char *);
  char ** fetch_pam_environment(void);
  char ** fetch_pam_child_environment(void);
  void free_pam_environment(char **);
 -void sshpam_thread_cleanup(void);
 +void sshpam_child_cleanup(void);
++int get_pam_done(void *);
  void sshpam_cleanup(void);
  int sshpam_auth_passwd(Authctxt *, const char *);
- int is_pam_session_open(void);
-+int get_pam_done(void *);
- 
- #endif /* USE_PAM */
+ int sshpam_get_maxtries_reached(void);
 diff -pur old/monitor.c new/monitor.c
 --- old/monitor.c
 +++ new/monitor.c
-@@ -1179,12 +1179,38 @@ mm_answer_pam_init_ctx(int sock, Buffer
+@@ -1184,12 +1184,39 @@ mm_answer_pam_init_ctx(int sock, Buffer
  	sshpam_ctxt = (sshpam_device.init_ctx)(authctxt);
  	sshpam_authok = NULL;
  	buffer_clear(m);
@@ -629,6 +637,7 @@
 +			    buffer_len(&loginmsg));
 +			buffer_clear(&loginmsg);
 +		}
++		buffer_put_int(m, sshpam_get_maxtries_reached());
 +		buffer_put_int(m, 0);		/* num */
 +		mm_request_send(sock, MONITOR_ANS_PAM_QUERY, m);
 +		return (0);
@@ -637,7 +646,7 @@
  	mm_request_send(sock, MONITOR_ANS_PAM_INIT_CTX, m);
  	return (0);
  }
-@@ -1938,7 +1964,8 @@ monitor_apply_keystate(struct monitor *p
+@@ -1947,7 +1974,8 @@ monitor_apply_keystate(struct monitor *p
  	int r;
  
  	debug3("%s: packet_set_state", __func__);
@@ -650,7 +659,7 @@
 diff -pur old/packet.c new/packet.c
 --- old/packet.c
 +++ new/packet.c
-@@ -2345,7 +2345,7 @@ ssh_packet_restore_state(struct ssh *ssh
+@@ -2449,7 +2449,7 @@ ssh_packet_get_output(struct ssh *ssh)
  }
  
  /* Reset after_authentication and reset compression in post-auth privsep */
@@ -659,7 +668,7 @@
  ssh_packet_set_postauth(struct ssh *ssh)
  {
  	struct sshcomp *comp;
-@@ -2682,8 +2682,7 @@ ssh_packet_set_state(struct ssh *ssh, st
+@@ -2775,8 +2775,7 @@ ssh_packet_set_state(struct ssh *ssh, st
  	cipher_set_keycontext(&state->send_context, keyout);
  	cipher_set_keycontext(&state->receive_context, keyin);
  
@@ -672,18 +681,18 @@
 diff -pur old/packet.h new/packet.h
 --- old/packet.h
 +++ new/packet.h
-@@ -141,6 +141,7 @@ u_int	 ssh_packet_get_maxsize(struct ssh
+@@ -144,6 +144,7 @@ u_int	 ssh_packet_get_maxsize(struct ssh
  
  int	 ssh_packet_get_state(struct ssh *, struct sshbuf *);
  int	 ssh_packet_set_state(struct ssh *, struct sshbuf *);
 +int	 ssh_packet_set_postauth(struct ssh *ssh);
  
  const char *ssh_remote_ipaddr(struct ssh *);
- 
+ int	 ssh_remote_port(struct ssh *);
 diff -pur old/servconf.c new/servconf.c
 --- old/servconf.c
 +++ new/servconf.c
-@@ -433,6 +433,18 @@ fill_default_server_options(ServerOption
+@@ -435,6 +435,18 @@ fill_default_server_options(ServerOption
  		options->compression = 0;
  	}
  #endif
@@ -705,7 +714,7 @@
 diff -pur old/session.c new/session.c
 --- old/session.c
 +++ new/session.c
-@@ -2850,7 +2850,7 @@ do_cleanup(Authctxt *authctxt)
+@@ -2890,7 +2890,7 @@ do_cleanup(Authctxt *authctxt)
  #ifdef USE_PAM
  	if (options.use_pam) {
  		sshpam_cleanup();