Mercurial > dropbear
comparison cli-tcpfwd.c @ 389:5ff8218bcee9
propagate from branch 'au.asn.ucc.matt.ltm.dropbear' (head 2af95f00ebd5bb7a28b3817db1218442c935388e)
to branch 'au.asn.ucc.matt.dropbear' (head ecd779509ef23a8cdf64888904fc9b31d78aa933)
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Thu, 11 Jan 2007 03:14:55 +0000 |
parents | c049490e43fe |
children | 805e557fdff7 |
comparison
equal
deleted
inserted
replaced
388:fb54020f78e1 | 389:5ff8218bcee9 |
---|---|
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 | |
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 | |
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 | |
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 | |
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 | |
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 */ |