1f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/*
2f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Dropbear SSH
3f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
4f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Copyright (c) 2002,2003 Matt Johnston
5f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Copyright (c) 2004 by Mihnea Stoenescu
6f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * All rights reserved.
7f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
8f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Permission is hereby granted, free of charge, to any person obtaining a copy
9f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * of this software and associated documentation files (the "Software"), to deal
10f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * in the Software without restriction, including without limitation the rights
11f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * copies of the Software, and to permit persons to whom the Software is
13f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * furnished to do so, subject to the following conditions:
14f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
15f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * The above copyright notice and this permission notice shall be included in
16f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * all copies or substantial portions of the Software.
17f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
18f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * SOFTWARE. */
25f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
26f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "includes.h"
27f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "ssh.h"
28f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "tcpfwd.h"
29f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "dbutil.h"
30f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "session.h"
31f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "buffer.h"
32f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "packet.h"
33f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "listener.h"
34f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "runopts.h"
35f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
36f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef ENABLE_SVR_REMOTETCPFWD
37f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
38f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void send_msg_request_success();
39f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void send_msg_request_failure();
40f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int svr_cancelremotetcp();
41f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int svr_remotetcpreq();
42f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int newtcpdirect(struct Channel * channel);
43f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
44f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
45f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectconst struct ChanType svr_chan_tcpdirect = {
46f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	1, /* sepfds */
47f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	"direct-tcpip",
48f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	newtcpdirect, /* init */
49f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	NULL, /* checkclose */
50f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	NULL, /* reqhandler */
51f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	NULL /* closehandler */
52f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project};
53f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
54f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic const struct ChanType svr_chan_tcpremote = {
55f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	1, /* sepfds */
56f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	"forwarded-tcpip",
57f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	NULL,
58f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	NULL,
59f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	NULL,
60f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	NULL
61f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project};
62f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
63f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* At the moment this is completely used for tcp code (with the name reflecting
64f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * that). If new request types are added, this should be replaced with code
65f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * similar to the request-switching in chansession.c */
66f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid recv_msg_global_request_remotetcp() {
67f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
68f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned char* reqname = NULL;
69f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned int namelen;
70f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned int wantreply = 0;
71f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	int ret = DROPBEAR_FAILURE;
72f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
73f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("enter recv_msg_global_request_remotetcp"))
74f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
75f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (svr_opts.noremotetcp) {
76f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("leave recv_msg_global_request_remotetcp: remote tcp forwarding disabled"))
77f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		goto out;
78f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
79f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
80f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	reqname = buf_getstring(ses.payload, &namelen);
81f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	wantreply = buf_getbool(ses.payload);
82f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
83f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (namelen > MAX_NAME_LEN) {
84f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("name len is wrong: %d", namelen))
85f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		goto out;
86f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
87f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
88f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (strcmp("tcpip-forward", reqname) == 0) {
89f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		ret = svr_remotetcpreq();
90f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	} else if (strcmp("cancel-tcpip-forward", reqname) == 0) {
91f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		ret = svr_cancelremotetcp();
92f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	} else {
93f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("reqname isn't tcpip-forward: '%s'", reqname))
94f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
95f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
96f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectout:
97f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (wantreply) {
98f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (ret == DROPBEAR_SUCCESS) {
99f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			send_msg_request_success();
100f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		} else {
101f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			send_msg_request_failure();
102f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
103f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
104f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
105f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	m_free(reqname);
106f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
107f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("leave recv_msg_global_request"))
108f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
109f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
110f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
111f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void send_msg_request_success() {
112f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
113f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	CHECKCLEARTOWRITE();
114f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putbyte(ses.writepayload, SSH_MSG_REQUEST_SUCCESS);
115f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	encrypt_packet();
116f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
117f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
118f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
119f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void send_msg_request_failure() {
120f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
121f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	CHECKCLEARTOWRITE();
122f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putbyte(ses.writepayload, SSH_MSG_REQUEST_FAILURE);
123f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	encrypt_packet();
124f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
125f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
126f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
127f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int matchtcp(void* typedata1, void* typedata2) {
128f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
129f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	const struct TCPListener *info1 = (struct TCPListener*)typedata1;
130f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	const struct TCPListener *info2 = (struct TCPListener*)typedata2;
131f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
132f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	return (info1->listenport == info2->listenport)
133f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			&& (info1->chantype == info2->chantype)
134f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			&& (strcmp(info1->listenaddr, info2->listenaddr) == 0);
135f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
136f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
137f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int svr_cancelremotetcp() {
138f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
139f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	int ret = DROPBEAR_FAILURE;
140f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned char * bindaddr = NULL;
141f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned int addrlen;
142f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned int port;
143f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	struct Listener * listener = NULL;
144f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	struct TCPListener tcpinfo;
145f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
146f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("enter cancelremotetcp"))
147f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
148f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	bindaddr = buf_getstring(ses.payload, &addrlen);
149f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (addrlen > MAX_IP_LEN) {
150f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("addr len too long: %d", addrlen))
151f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		goto out;
152f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
153f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
154f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	port = buf_getint(ses.payload);
155f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
156f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	tcpinfo.sendaddr = NULL;
157f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	tcpinfo.sendport = 0;
158f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	tcpinfo.listenaddr = bindaddr;
159f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	tcpinfo.listenport = port;
160f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	listener = get_listener(CHANNEL_ID_TCPFORWARDED, &tcpinfo, matchtcp);
161f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (listener) {
162f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		remove_listener( listener );
163f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		ret = DROPBEAR_SUCCESS;
164f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
165f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
166f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectout:
167f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	m_free(bindaddr);
168f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("leave cancelremotetcp"))
169f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	return ret;
170f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
171f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
172f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int svr_remotetcpreq() {
173f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
174f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	int ret = DROPBEAR_FAILURE;
175f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned char * bindaddr = NULL;
176f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned int addrlen;
177f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	struct TCPListener *tcpinfo = NULL;
178f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned int port;
179f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
180f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("enter remotetcpreq"))
181f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
182f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	bindaddr = buf_getstring(ses.payload, &addrlen);
183f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (addrlen > MAX_IP_LEN) {
184f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("addr len too long: %d", addrlen))
185f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		goto out;
186f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
187f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
188f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	port = buf_getint(ses.payload);
189f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
190f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (port == 0) {
191f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		dropbear_log(LOG_INFO, "Server chosen tcpfwd ports are unsupported");
192f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		goto out;
193f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
194f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
195f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (port < 1 || port > 65535) {
196f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("invalid port: %d", port))
197f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		goto out;
198f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
199f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
200f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (!ses.allowprivport && port < IPPORT_RESERVED) {
201f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("can't assign port < 1024 for non-root"))
202f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		goto out;
203f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
204f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
205f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	tcpinfo = (struct TCPListener*)m_malloc(sizeof(struct TCPListener));
206f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	tcpinfo->sendaddr = NULL;
207f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	tcpinfo->sendport = 0;
208f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	tcpinfo->listenaddr = bindaddr;
209f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	tcpinfo->listenport = port;
210f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	tcpinfo->chantype = &svr_chan_tcpremote;
211f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	tcpinfo->tcp_type = forwarded;
212f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
213f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ret = listen_tcpfwd(tcpinfo);
214f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
215f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectout:
216f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (ret == DROPBEAR_FAILURE) {
217f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		/* we only free it if a listener wasn't created, since the listener
218f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		 * has to remember it if it's to be cancelled */
219f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		m_free(bindaddr);
220f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		m_free(tcpinfo);
221f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
222f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("leave remotetcpreq"))
223f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	return ret;
224f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
225f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
226f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Called upon creating a new direct tcp channel (ie we connect out to an
227f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * address */
228f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int newtcpdirect(struct Channel * channel) {
229f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
230f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned char* desthost = NULL;
231f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned int destport;
232f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned char* orighost = NULL;
233f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned int origport;
234f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	char portstring[NI_MAXSERV];
235f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	int sock;
236f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	int len;
237f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	int err = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED;
238f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
239f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (svr_opts.nolocaltcp) {
240f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("leave newtcpdirect: local tcp forwarding disabled"))
241f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		goto out;
242f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
243f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
244f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	desthost = buf_getstring(ses.payload, &len);
245f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (len > MAX_HOST_LEN) {
246f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("leave newtcpdirect: desthost too long"))
247f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		goto out;
248f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
249f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
250f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	destport = buf_getint(ses.payload);
251f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
252f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	orighost = buf_getstring(ses.payload, &len);
253f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (len > MAX_HOST_LEN) {
254f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("leave newtcpdirect: orighost too long"))
255f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		goto out;
256f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
257f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
258f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	origport = buf_getint(ses.payload);
259f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
260f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* best be sure */
261f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (origport > 65535 || destport > 65535) {
262f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("leave newtcpdirect: port > 65535"))
263f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		goto out;
264f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
265f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
266f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	snprintf(portstring, sizeof(portstring), "%d", destport);
267f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	sock = connect_remote(desthost, portstring, 1, NULL);
268f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (sock < 0) {
269f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		err = SSH_OPEN_CONNECT_FAILED;
270f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("leave newtcpdirect: sock failed"))
271f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		goto out;
272f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
273f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
274f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.maxfd = MAX(ses.maxfd, sock);
275f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
276f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	 /* We don't set readfd, that will get set after the connection's
277f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	 * progress succeeds */
278f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	channel->writefd = sock;
279f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	channel->initconn = 1;
280f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
281f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	err = SSH_OPEN_IN_PROGRESS;
282f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
283f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectout:
284f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	m_free(desthost);
285f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	m_free(orighost);
286f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("leave newtcpdirect: err %d", err))
287f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	return err;
288f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
289f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
290f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
291