changeset 1830:c32976db772f

Merge
author Matt Johnston <matt@ucc.asn.au>
date Mon, 11 Oct 2021 15:46:49 +0800
parents a7cc3332d8ab (diff) 1edf4f143e12 (current diff)
children 0a3d02c66bf6
files cli-session.c svr-chansession.c
diffstat 11 files changed, 30 insertions(+), 64 deletions(-) [+]
line wrap: on
line diff
--- a/channel.h	Thu Aug 19 18:49:52 2021 +0300
+++ b/channel.h	Mon Oct 11 15:46:49 2021 +0800
@@ -60,6 +60,9 @@
 	int readfd; /* read from insecure side, written to wire */
 	int errfd; /* used like writefd or readfd, depending if it's client or server.
 				  Doesn't exactly belong here, but is cleaner here */
+	int bidir_fd; /* a boolean indicating that writefd/readfd are the same
+			file descriptor (bidirectional), such as a network socket or PTY.
+			That is handled differently when closing FDs */
 	circbuffer *writebuf; /* data from the wire, for local consumption. Can be
 							 initially NULL */
 	circbuffer *extrabuf; /* extended-data for the program - used like writebuf
@@ -77,8 +80,6 @@
 					   for this channel (and are awaiting a confirmation
 					   or failure). */
 
-	int flushing;
-
 	/* Used by client chansession to handle ~ escaping, NULL ignored otherwise */
 	void (*read_mangler)(const struct Channel*, const unsigned char* bytes, int *len);
 
@@ -89,7 +90,6 @@
 
 struct ChanType {
 
-	int sepfds; /* Whether this channel has separate pipes for in/out or not */
 	const char *name;
 	/* Sets up the channel */
 	int (*inithandler)(struct Channel*);
--- a/cli-agentfwd.c	Thu Aug 19 18:49:52 2021 +0300
+++ b/cli-agentfwd.c	Mon Oct 11 15:46:49 2021 +0800
@@ -47,7 +47,6 @@
 static int new_agent_chan(struct Channel * channel);
 
 const struct ChanType cli_chan_agent = {
-	0, /* sepfds */
 	"[email protected]",
 	new_agent_chan,
 	NULL,
@@ -94,6 +93,7 @@
 
 	channel->readfd = fd;
 	channel->writefd = fd;
+	channel->bidir_fd = 1;
 
 	return 0;
 }
--- a/cli-chansession.c	Thu Aug 19 18:49:52 2021 +0300
+++ b/cli-chansession.c	Mon Oct 11 15:46:49 2021 +0800
@@ -46,7 +46,6 @@
 static void cli_tty_setup(void);
 
 const struct ChanType clichansess = {
-	0, /* sepfds */
 	"session", /* name */
 	cli_initchansess, /* inithandler */
 	NULL, /* checkclosehandler */
@@ -344,6 +343,7 @@
 	setnonblocking(STDERR_FILENO);
 
 	channel->extrabuf = cbuf_new(opts.recv_window);
+	channel->bidir_fd = 0;
 	return 0;
 }
 
@@ -383,7 +383,6 @@
 #if DROPBEAR_CLI_NETCAT
 
 static const struct ChanType cli_chan_netcat = {
-	0, /* sepfds */
 	"direct-tcpip",
 	cli_init_netcat, /* inithandler */
 	NULL,
--- a/cli-session.c	Thu Aug 19 18:49:52 2021 +0300
+++ b/cli-session.c	Mon Oct 11 15:46:49 2021 +0800
@@ -246,6 +246,9 @@
 			/* We've got the transport layer sorted, we now need to request
 			 * userauth */
 			send_msg_service_request(SSH_SERVICE_USERAUTH);
+			/* We aren't using any "implicit server authentication" methods,
+			so don't need to wait for a response for SSH_SERVICE_USERAUTH
+			before sending the auth messages (rfc4253 10) */
 			cli_auth_getmethods();
 			cli_ses.state = USERAUTH_REQ_SENT;
 			TRACE(("leave cli_sessionloop: sent userauth methods req"))
--- a/cli-tcpfwd.c	Thu Aug 19 18:49:52 2021 +0300
+++ b/cli-tcpfwd.c	Mon Oct 11 15:46:49 2021 +0800
@@ -35,7 +35,6 @@
 static int newtcpforwarded(struct Channel * channel);
 
 const struct ChanType cli_chan_tcpremote = {
-	1, /* sepfds */
 	"forwarded-tcpip",
 	newtcpforwarded,
 	NULL,
@@ -51,7 +50,6 @@
 		const char* remoteaddr,
 		unsigned int remoteport);
 static const struct ChanType cli_chan_tcplocal = {
-	1, /* sepfds */
 	"direct-tcpip",
 	tcp_prio_inithandler,
 	NULL,
@@ -275,10 +273,10 @@
 	}
 
 	channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE;
-	
+
 	snprintf(portstring, sizeof(portstring), "%u", fwd->connectport);
 	channel->conn_pending = connect_remote(fwd->connectaddr, portstring, channel_connect_done, channel, NULL, NULL);
-	
+
 	err = SSH_OPEN_IN_PROGRESS;
 
 out:
--- a/common-channel.c	Thu Aug 19 18:49:52 2021 +0300
+++ b/common-channel.c	Mon Oct 11 15:46:49 2021 +0800
@@ -154,7 +154,6 @@
 	newchan->readfd = FD_UNINIT;
 	newchan->errfd = FD_CLOSED; /* this isn't always set to start with */
 	newchan->await_open = 0;
-	newchan->flushing = 0;
 
 	newchan->writebuf = cbuf_new(opts.recv_window);
 	newchan->recvwindow = opts.recv_window;
@@ -284,14 +283,6 @@
 				channel->writebuf ? cbuf_getused(channel->writebuf) : 0,
 				channel->extrabuf ? cbuf_getused(channel->extrabuf) : 0))
 
-	if (!channel->flushing 
-		&& !channel->sent_close
-		&& channel->type->check_close
-		&& channel->type->check_close(channel))
-	{
-		channel->flushing = 1;
-	}
-	
 	/* if a type-specific check_close is defined we will only exit
 	   once that has been triggered. this is only used for a server "session"
 	   channel, to ensure that the shell has exited (and the exit status 
@@ -317,22 +308,6 @@
 		close_chan_fd(channel, channel->writefd, SHUT_WR);
 	}
 
-	/* Special handling for flushing read data after an exit. We
-	   read regardless of whether the select FD was set,
-	   and if there isn't data available, the channel will get closed. */
-	if (channel->flushing) {
-		TRACE(("might send data, flushing"))
-		if (channel->readfd >= 0 && channel->transwindow > 0) {
-			TRACE(("send data readfd"))
-			send_msg_channel_data(channel, 0);
-		}
-		if (ERRFD_IS_READ(channel) && channel->errfd >= 0 
-			&& channel->transwindow > 0) {
-			TRACE(("send data errfd"))
-			send_msg_channel_data(channel, 1);
-		}
-	}
-
 	/* If we're not going to send any more data, send EOF */
 	if (!channel->sent_eof
 			&& channel->readfd == FD_CLOSED 
@@ -364,6 +339,7 @@
 	if (result == DROPBEAR_SUCCESS)
 	{
 		channel->readfd = channel->writefd = sock;
+		channel->bidir_fd = 1;
 		channel->conn_pending = NULL;
 		send_msg_channel_open_confirmation(channel, channel->recvwindow,
 				channel->recvmaxpacket);
@@ -779,14 +755,6 @@
 	channel->transwindow -= len;
 
 	encrypt_packet();
-	
-	/* If we receive less data than we requested when flushing, we've
-	   reached the equivalent of EOF */
-	if (channel->flushing && len < (ssize_t)maxlen)
-	{
-		TRACE(("closing from channel, flushing out."))
-		close_chan_fd(channel, fd, SHUT_RD);
-	}
 	TRACE(("leave send_msg_channel_data"))
 }
 
@@ -1072,7 +1040,7 @@
 
 	int closein = 0, closeout = 0;
 
-	if (channel->type->sepfds) {
+	if (channel->bidir_fd) {
 		TRACE(("SHUTDOWN(%d, %d)", fd, how))
 		shutdown(fd, how);
 		if (how == 0) {
@@ -1102,7 +1070,7 @@
 
 	/* if we called shutdown on it and all references are gone, then we 
 	 * need to close() it to stop it lingering */
-	if (channel->type->sepfds && channel->readfd == FD_CLOSED 
+	if (channel->bidir_fd && channel->readfd == FD_CLOSED 
 		&& channel->writefd == FD_CLOSED && channel->errfd == FD_CLOSED) {
 		TRACE(("CLOSE (finally) of %d", fd))
 		m_close(fd);
@@ -1135,6 +1103,7 @@
 
 	chan->writefd = chan->readfd = fd;
 	ses.maxfd = MAX(ses.maxfd, fd);
+	chan->bidir_fd = 1;
 
 	chan->await_open = 1;
 
@@ -1151,7 +1120,7 @@
 	return DROPBEAR_SUCCESS;
 }
 
-/* Confirmation that our channel open request (for forwardings) was 
+/* Confirmation that our channel open request was 
  * successful*/
 void recv_msg_channel_open_confirmation() {
 
--- a/svr-agentfwd.c	Thu Aug 19 18:49:52 2021 +0300
+++ b/svr-agentfwd.c	Mon Oct 11 15:46:49 2021 +0800
@@ -186,7 +186,6 @@
 }
 
 static const struct ChanType chan_svr_agent = {
-	0, /* sepfds */
 	"[email protected]",
 	NULL,
 	NULL,
--- a/svr-chansession.c	Thu Aug 19 18:49:52 2021 +0300
+++ b/svr-chansession.c	Mon Oct 11 15:46:49 2021 +0800
@@ -64,7 +64,6 @@
 static void get_termmodes(const struct ChanSess *chansess);
 
 const struct ChanType svrchansess = {
-	0, /* sepfds */
 	"session", /* name */
 	newchansess, /* inithandler */
 	sesscheckclose, /* checkclosehandler */
@@ -76,12 +75,22 @@
 /* required to clear environment */
 extern char** environ;
 
+/* Returns whether the channel is ready to close. The child process
+   must not be running (has never started, or has exited) */
 static int sesscheckclose(const struct Channel *channel) {
 	struct ChanSess *chansess = (struct ChanSess*)channel->typedata;
-	TRACE(("sesscheckclose, pid is %d", chansess->exit.exitpid))
-	return chansess->exit.exitpid != -1;
+	TRACE(("sesscheckclose, pid %d, exitpid %d", chansess->pid, chansess->exit.exitpid))
+	return chansess->pid == 0 || chansess->exit.exitpid != -1;
 }
 
+/* Handler for childs exiting, store the state for return to the client */
+
+/* There's a particular race we have to watch out for: if the forked child
+ * executes, exits, and this signal-handler is called, all before the parent
+ * gets to run, then the childpids[] array won't have the pid in it. Hence we
+ * use the svr_ses.lastexit struct to hold the exit, which is then compared by
+ * the parent when it runs. This work correctly at least in the case of a
+ * single shell spawned (ie the usual case) */
 void svr_chansess_checksignal(void) {
 	int status;
 	pid_t pid;
@@ -127,18 +136,9 @@
 			/* we use this to determine how pid exited */
 			ex->exitsignal = -1;
 		}
-		
 	}
 }
 
-/* Handler for childs exiting, store the state for return to the client */
-
-/* There's a particular race we have to watch out for: if the forked child
- * executes, exits, and this signal-handler is called, all before the parent
- * gets to run, then the childpids[] array won't have the pid in it. Hence we
- * use the svr_ses.lastexit struct to hold the exit, which is then compared by
- * the parent when it runs. This work correctly at least in the case of a
- * single shell spawned (ie the usual case) */
 static void sesssigchild_handler(int UNUSED(dummy)) {
 	struct sigaction sa_chld;
 
@@ -768,6 +768,7 @@
 	ses.maxfd = MAX(ses.maxfd, channel->writefd);
 	ses.maxfd = MAX(ses.maxfd, channel->readfd);
 	ses.maxfd = MAX(ses.maxfd, channel->errfd);
+	channel->bidir_fd = 0;
 
 	addchildpid(chansess, chansess->pid);
 
@@ -894,6 +895,7 @@
 		channel->readfd = chansess->master;
 		/* don't need to set stderr here */
 		ses.maxfd = MAX(ses.maxfd, chansess->master);
+		channel->bidir_fd = 1;
 
 		setnonblocking(chansess->master);
 
--- a/svr-session.c	Thu Aug 19 18:49:52 2021 +0300
+++ b/svr-session.c	Mon Oct 11 15:46:49 2021 +0800
@@ -201,8 +201,7 @@
     }
 #endif
 
-	/* Run the main for loop. NULL is for the dispatcher - only the client
-	 * code makes use of it */
+	/* Run the main for-loop. */
 	session_loop(svr_chansess_checksignal);
 
 	/* Not reached */
--- a/svr-tcpfwd.c	Thu Aug 19 18:49:52 2021 +0300
+++ b/svr-tcpfwd.c	Mon Oct 11 15:46:49 2021 +0800
@@ -59,7 +59,6 @@
 
 #if DROPBEAR_SVR_REMOTETCPFWD
 static const struct ChanType svr_chan_tcpremote = {
-	1, /* sepfds */
 	"forwarded-tcpip",
 	tcp_prio_inithandler,
 	NULL,
@@ -241,7 +240,6 @@
 #if DROPBEAR_SVR_LOCALTCPFWD
 
 const struct ChanType svr_chan_tcpdirect = {
-	1, /* sepfds */
 	"direct-tcpip",
 	newtcpdirect, /* init */
 	NULL, /* checkclose */
--- a/svr-x11fwd.c	Thu Aug 19 18:49:52 2021 +0300
+++ b/svr-x11fwd.c	Mon Oct 11 15:46:49 2021 +0800
@@ -211,7 +211,6 @@
 }
 
 static const struct ChanType chan_x11 = {
-	0, /* sepfds */
 	"x11",
 	x11_inithandler, /* inithandler */
 	NULL, /* checkclose */