1 /*
2 * Dropbear SSH
3 *
4 * Copyright (c) 2002,2003 Matt Johnston
5 * All rights reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE. */
24
25 #include "includes.h"
26 #include "options.h"
27 #include "dbutil.h"
28 #include "tcpfwd.h"
29 #include "channel.h"
30 #include "runopts.h"
31 #include "session.h"
32 #include "ssh.h"
33
34 #ifdef ENABLE_CLI_REMOTETCPFWD
35 static int newtcpforwarded(struct Channel * channel);
36
37 const struct ChanType cli_chan_tcpremote = {
38 1, /* sepfds */
39 "forwarded-tcpip",
40 newtcpforwarded,
41 NULL,
42 NULL,
43 NULL
44 };
45 #endif
46
47 #ifdef ENABLE_CLI_LOCALTCPFWD
48 static int cli_localtcp(unsigned int listenport, const char* remoteaddr,
49 unsigned int remoteport);
50 static const struct ChanType cli_chan_tcplocal = {
51 1, /* sepfds */
52 "direct-tcpip",
53 NULL,
54 NULL,
55 NULL,
56 NULL
57 };
58 #endif
59
60 #ifdef ENABLE_CLI_LOCALTCPFWD
setup_localtcp()61 void setup_localtcp() {
62
63 int ret;
64
65 TRACE(("enter setup_localtcp"))
66
67 if (cli_opts.localfwds == NULL) {
68 TRACE(("cli_opts.localfwds == NULL"))
69 }
70
71 while (cli_opts.localfwds != NULL) {
72 ret = cli_localtcp(cli_opts.localfwds->listenport,
73 cli_opts.localfwds->connectaddr,
74 cli_opts.localfwds->connectport);
75 if (ret == DROPBEAR_FAILURE) {
76 dropbear_log(LOG_WARNING, "Failed local port forward %d:%s:%d",
77 cli_opts.localfwds->listenport,
78 cli_opts.localfwds->connectaddr,
79 cli_opts.localfwds->connectport);
80 }
81
82 cli_opts.localfwds = cli_opts.localfwds->next;
83 }
84 TRACE(("leave setup_localtcp"))
85
86 }
87
cli_localtcp(unsigned int listenport,const char * remoteaddr,unsigned int remoteport)88 static int cli_localtcp(unsigned int listenport, const char* remoteaddr,
89 unsigned int remoteport) {
90
91 struct TCPListener* tcpinfo = NULL;
92 int ret;
93
94 TRACE(("enter cli_localtcp: %d %s %d", listenport, remoteaddr,
95 remoteport));
96
97 tcpinfo = (struct TCPListener*)m_malloc(sizeof(struct TCPListener));
98
99 tcpinfo->sendaddr = m_strdup(remoteaddr);
100 tcpinfo->sendport = remoteport;
101
102 if (opts.listen_fwd_all) {
103 tcpinfo->listenaddr = m_strdup("");
104 } else {
105 tcpinfo->listenaddr = m_strdup("localhost");
106 }
107 tcpinfo->listenport = listenport;
108
109 tcpinfo->chantype = &cli_chan_tcplocal;
110 tcpinfo->tcp_type = direct;
111
112 ret = listen_tcpfwd(tcpinfo);
113
114 if (ret == DROPBEAR_FAILURE) {
115 m_free(tcpinfo);
116 }
117 TRACE(("leave cli_localtcp: %d", ret))
118 return ret;
119 }
120 #endif /* ENABLE_CLI_LOCALTCPFWD */
121
122 #ifdef ENABLE_CLI_REMOTETCPFWD
send_msg_global_request_remotetcp(int port)123 static void send_msg_global_request_remotetcp(int port) {
124
125 char* listenspec = NULL;
126 TRACE(("enter send_msg_global_request_remotetcp"))
127
128 CHECKCLEARTOWRITE();
129 buf_putbyte(ses.writepayload, SSH_MSG_GLOBAL_REQUEST);
130 buf_putstring(ses.writepayload, "tcpip-forward", 13);
131 buf_putbyte(ses.writepayload, 0);
132 if (opts.listen_fwd_all) {
133 listenspec = "";
134 } else {
135 listenspec = "localhost";
136 }
137 /* TODO: IPv6? */;
138 buf_putstring(ses.writepayload, listenspec, strlen(listenspec));
139 buf_putint(ses.writepayload, port);
140
141 encrypt_packet();
142
143 TRACE(("leave send_msg_global_request_remotetcp"))
144 }
145
setup_remotetcp()146 void setup_remotetcp() {
147
148 struct TCPFwdList * iter = NULL;
149
150 TRACE(("enter setup_remotetcp"))
151
152 if (cli_opts.remotefwds == NULL) {
153 TRACE(("cli_opts.remotefwds == NULL"))
154 }
155
156 iter = cli_opts.remotefwds;
157
158 while (iter != NULL) {
159 send_msg_global_request_remotetcp(iter->listenport);
160 iter = iter->next;
161 }
162 TRACE(("leave setup_remotetcp"))
163 }
164
newtcpforwarded(struct Channel * channel)165 static int newtcpforwarded(struct Channel * channel) {
166
167 unsigned int origport;
168 struct TCPFwdList * iter = NULL;
169 char portstring[NI_MAXSERV];
170 int sock;
171 int err = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED;
172
173 /* We don't care what address they connected to */
174 buf_eatstring(ses.payload);
175
176 origport = buf_getint(ses.payload);
177
178 /* Find which port corresponds */
179 iter = cli_opts.remotefwds;
180
181 while (iter != NULL) {
182 if (origport == iter->listenport) {
183 break;
184 }
185 iter = iter->next;
186 }
187
188 if (iter == NULL) {
189 /* We didn't request forwarding on that port */
190 dropbear_log(LOG_INFO, "Server send unrequested port, from port %d",
191 origport);
192 goto out;
193 }
194
195 snprintf(portstring, sizeof(portstring), "%d", iter->connectport);
196 sock = connect_remote(iter->connectaddr, portstring, 1, NULL);
197 if (sock < 0) {
198 TRACE(("leave newtcpdirect: sock failed"))
199 err = SSH_OPEN_CONNECT_FAILED;
200 goto out;
201 }
202
203 ses.maxfd = MAX(ses.maxfd, sock);
204
205 /* We don't set readfd, that will get set after the connection's
206 * progress succeeds */
207 channel->writefd = sock;
208 channel->initconn = 1;
209
210 err = SSH_OPEN_IN_PROGRESS;
211
212 out:
213 TRACE(("leave newtcpdirect: err %d", err))
214 return err;
215 }
216 #endif /* ENABLE_CLI_REMOTETCPFWD */
217