diff svr-tcpfwd.c @ 1478:3a933956437e coverity

update coverity
author Matt Johnston <matt@ucc.asn.au>
date Fri, 09 Feb 2018 23:49:22 +0800
parents f787f60f8e45
children 2d450c1056e3
line wrap: on
line diff
--- a/svr-tcpfwd.c	Sat Jun 24 23:33:16 2017 +0800
+++ b/svr-tcpfwd.c	Fri Feb 09 23:49:22 2018 +0800
@@ -47,7 +47,7 @@
 #endif /* !DROPBEAR_SVR_REMOTETCPFWD */
 
 static int svr_cancelremotetcp(void);
-static int svr_remotetcpreq(void);
+static int svr_remotetcpreq(int *allocated_listen_port);
 static int newtcpdirect(struct Channel * channel);
 
 #if DROPBEAR_SVR_REMOTETCPFWD
@@ -86,7 +86,16 @@
 	}
 
 	if (strcmp("tcpip-forward", reqname) == 0) {
-		ret = svr_remotetcpreq();
+		int allocated_listen_port;
+		ret = svr_remotetcpreq(&allocated_listen_port);
+		/* client expects-port-number-to-make-use-of-server-allocated-ports */
+		if (DROPBEAR_SUCCESS == ret) {
+			CHECKCLEARTOWRITE();
+			buf_putbyte(ses.writepayload, SSH_MSG_REQUEST_SUCCESS);
+			buf_putint(ses.writepayload, allocated_listen_port);
+			encrypt_packet();
+			wantreply = 0; //so out does not do so
+	  }
 	} else if (strcmp("cancel-tcpip-forward", reqname) == 0) {
 		ret = svr_cancelremotetcp();
 	} else {
@@ -107,7 +116,7 @@
 	TRACE(("leave recv_msg_global_request"))
 }
 
-static int matchtcp(void* typedata1, void* typedata2) {
+static int matchtcp(const void* typedata1, const void* typedata2) {
 
 	const struct TCPListener *info1 = (struct TCPListener*)typedata1;
 	const struct TCPListener *info2 = (struct TCPListener*)typedata2;
@@ -152,7 +161,7 @@
 	return ret;
 }
 
-static int svr_remotetcpreq() {
+static int svr_remotetcpreq(int *allocated_listen_port) {
 
 	int ret = DROPBEAR_FAILURE;
 	char * request_addr = NULL;
@@ -170,19 +179,16 @@
 
 	port = buf_getint(ses.payload);
 
-	if (port == 0) {
-		dropbear_log(LOG_INFO, "Server chosen tcpfwd ports are unsupported");
-		goto out;
-	}
+	if (port != 0) {
+		if (port < 1 || port > 65535) {
+			TRACE(("invalid port: %d", port))
+			goto out;
+		}
 
-	if (port < 1 || port > 65535) {
-		TRACE(("invalid port: %d", port))
-		goto out;
-	}
-
-	if (!ses.allowprivport && port < IPPORT_RESERVED) {
-		TRACE(("can't assign port < 1024 for non-root"))
-		goto out;
+		if (!ses.allowprivport && port < IPPORT_RESERVED) {
+			TRACE(("can't assign port < 1024 for non-root"))
+			goto out;
+		}
 	}
 
 	tcpinfo = (struct TCPListener*)m_malloc(sizeof(struct TCPListener));
@@ -203,6 +209,13 @@
 	}
 
 	ret = listen_tcpfwd(tcpinfo);
+	if (DROPBEAR_SUCCESS == ret) {
+		tcpinfo->listenport = get_sock_port(ses.listeners[0]->socks[0]);
+		*allocated_listen_port = tcpinfo->listenport;
+		dropbear_log(LOG_INFO, "tcpip-forward %s:%d '%s'", 
+			((NULL == tcpinfo->listenaddr)?"localhost":tcpinfo->listenaddr), 
+			tcpinfo->listenport, ses.authstate.pw_name);
+	}
 
 out:
 	if (ret == DROPBEAR_FAILURE) {
@@ -211,7 +224,9 @@
 		m_free(request_addr);
 		m_free(tcpinfo);
 	}
+
 	TRACE(("leave remotetcpreq"))
+
 	return ret;
 }
 
@@ -270,7 +285,7 @@
 	}
 
 	snprintf(portstring, sizeof(portstring), "%u", destport);
-	channel->conn_pending = connect_remote(desthost, portstring, channel_connect_done, channel);
+	channel->conn_pending = connect_remote(desthost, portstring, channel_connect_done, channel, NULL, NULL);
 
 	channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE;