Mercurial > dropbear
comparison cli-tcpfwd.c @ 118:5312ca05ed48 private-rez
propagate of 717950f4061f1123659ee87c7c168805af920ab7 and 839f98f136788cc1466e4641bf796f96040a085d from branch 'matt.dbclient.authpam' to 'matt.dbclient.rez'
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Sun, 12 Sep 2004 04:56:50 +0000 |
parents | 10f4d3319780 |
children | 8c2b3506f112 |
comparison
equal
deleted
inserted
replaced
57:3b2a5a1c4347 | 118:5312ca05ed48 |
---|---|
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 static int cli_localtcp(unsigned int listenport, const char* remoteaddr, | |
35 unsigned int remoteport); | |
36 static int newtcpforwarded(struct Channel * channel); | |
37 | |
38 const struct ChanType cli_chan_tcpremote = { | |
39 1, /* sepfds */ | |
40 "forwarded-tcpip", | |
41 newtcpforwarded, | |
42 NULL, | |
43 NULL, | |
44 NULL | |
45 }; | |
46 static const struct ChanType cli_chan_tcplocal = { | |
47 1, /* sepfds */ | |
48 "direct-tcpip", | |
49 NULL, | |
50 NULL, | |
51 NULL, | |
52 NULL | |
53 }; | |
54 | |
55 void setup_localtcp() { | |
56 | |
57 int ret; | |
58 | |
59 TRACE(("enter setup_localtcp")); | |
60 | |
61 if (cli_opts.localfwds == NULL) { | |
62 TRACE(("cli_opts.localfwds == NULL")); | |
63 } | |
64 | |
65 while (cli_opts.localfwds != NULL) { | |
66 ret = cli_localtcp(cli_opts.localfwds->listenport, | |
67 cli_opts.localfwds->connectaddr, | |
68 cli_opts.localfwds->connectport); | |
69 if (ret == DROPBEAR_FAILURE) { | |
70 dropbear_log(LOG_WARNING, "Failed local port forward %d:%s:%d", | |
71 cli_opts.localfwds->listenport, | |
72 cli_opts.localfwds->connectaddr, | |
73 cli_opts.localfwds->connectport); | |
74 } | |
75 | |
76 cli_opts.localfwds = cli_opts.localfwds->next; | |
77 } | |
78 TRACE(("leave setup_localtcp")); | |
79 | |
80 } | |
81 | |
82 static int cli_localtcp(unsigned int listenport, const char* remoteaddr, | |
83 unsigned int remoteport) { | |
84 | |
85 struct TCPListener* tcpinfo = NULL; | |
86 int ret; | |
87 | |
88 TRACE(("enter cli_localtcp: %d %s %d", listenport, remoteaddr, | |
89 remoteport)); | |
90 | |
91 tcpinfo = (struct TCPListener*)m_malloc(sizeof(struct TCPListener*)); | |
92 tcpinfo->sendaddr = m_strdup(remoteaddr); | |
93 tcpinfo->sendport = remoteport; | |
94 tcpinfo->listenport = listenport; | |
95 tcpinfo->chantype = &cli_chan_tcplocal; | |
96 | |
97 ret = listen_tcpfwd(tcpinfo); | |
98 | |
99 if (ret == DROPBEAR_FAILURE) { | |
100 m_free(tcpinfo); | |
101 } | |
102 TRACE(("leave cli_localtcp: %d", ret)); | |
103 return ret; | |
104 } | |
105 | |
106 static void send_msg_global_request_remotetcp(int port) { | |
107 | |
108 TRACE(("enter send_msg_global_request_remotetcp")); | |
109 | |
110 CHECKCLEARTOWRITE(); | |
111 buf_putbyte(ses.writepayload, SSH_MSG_GLOBAL_REQUEST); | |
112 buf_putstring(ses.writepayload, "tcpip-forward", 13); | |
113 buf_putbyte(ses.writepayload, 0); | |
114 buf_putstring(ses.writepayload, "0.0.0.0", 7); /* TODO: IPv6? */ | |
115 buf_putint(ses.writepayload, port); | |
116 | |
117 encrypt_packet(); | |
118 | |
119 TRACE(("leave send_msg_global_request_remotetcp")); | |
120 } | |
121 | |
122 void setup_remotetcp() { | |
123 | |
124 struct TCPFwdList * iter = NULL; | |
125 | |
126 TRACE(("enter setup_remotetcp")); | |
127 | |
128 if (cli_opts.remotefwds == NULL) { | |
129 TRACE(("cli_opts.remotefwds == NULL")); | |
130 } | |
131 | |
132 iter = cli_opts.remotefwds; | |
133 | |
134 while (iter != NULL) { | |
135 send_msg_global_request_remotetcp(iter->listenport); | |
136 iter = iter->next; | |
137 } | |
138 TRACE(("leave setup_remotetcp")); | |
139 } | |
140 | |
141 static int newtcpforwarded(struct Channel * channel) { | |
142 | |
143 unsigned int origport; | |
144 struct TCPFwdList * iter = NULL; | |
145 char portstring[NI_MAXSERV]; | |
146 int sock; | |
147 int err = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED; | |
148 | |
149 /* We don't care what address they connected to */ | |
150 buf_eatstring(ses.payload); | |
151 | |
152 origport = buf_getint(ses.payload); | |
153 | |
154 /* Find which port corresponds */ | |
155 iter = cli_opts.remotefwds; | |
156 | |
157 while (iter != NULL) { | |
158 if (origport == iter->listenport) { | |
159 break; | |
160 } | |
161 iter = iter->next; | |
162 } | |
163 | |
164 if (iter == NULL) { | |
165 /* We didn't request forwarding on that port */ | |
166 dropbear_log(LOG_INFO, "Server send unrequested port, from port %d", | |
167 origport); | |
168 goto out; | |
169 } | |
170 | |
171 snprintf(portstring, sizeof(portstring), "%d", iter->connectport); | |
172 sock = connect_remote(iter->connectaddr, portstring, 1, NULL); | |
173 if (sock < 0) { | |
174 TRACE(("leave newtcpdirect: sock failed")); | |
175 err = SSH_OPEN_CONNECT_FAILED; | |
176 goto out; | |
177 } | |
178 | |
179 ses.maxfd = MAX(ses.maxfd, sock); | |
180 | |
181 /* Note that infd is actually the "outgoing" direction on the | |
182 * tcp connection, vice versa for outfd. | |
183 * We don't set outfd, that will get set after the connection's | |
184 * progress succeeds */ | |
185 channel->infd = sock; | |
186 channel->initconn = 1; | |
187 | |
188 err = SSH_OPEN_IN_PROGRESS; | |
189 | |
190 out: | |
191 TRACE(("leave newtcpdirect: err %d", err)); | |
192 return err; | |
193 } |