Mercurial > dropbear
comparison cli-tcpfwd.c @ 641:2b1bb792cd4d dropbear-tfm
- Update tfm changes to current default tip
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Mon, 21 Nov 2011 19:52:28 +0800 |
parents | af304deacb4c |
children | c19acba28590 |
comparison
equal
deleted
inserted
replaced
640:76097ec1a29a | 641:2b1bb792cd4d |
---|---|
43 NULL | 43 NULL |
44 }; | 44 }; |
45 #endif | 45 #endif |
46 | 46 |
47 #ifdef ENABLE_CLI_LOCALTCPFWD | 47 #ifdef ENABLE_CLI_LOCALTCPFWD |
48 static int cli_localtcp(unsigned int listenport, const char* remoteaddr, | 48 static int cli_localtcp(const char* listenaddr, |
49 unsigned int listenport, | |
50 const char* remoteaddr, | |
49 unsigned int remoteport); | 51 unsigned int remoteport); |
50 static const struct ChanType cli_chan_tcplocal = { | 52 static const struct ChanType cli_chan_tcplocal = { |
51 1, /* sepfds */ | 53 1, /* sepfds */ |
52 "direct-tcpip", | 54 "direct-tcpip", |
53 NULL, | 55 NULL, |
57 }; | 59 }; |
58 #endif | 60 #endif |
59 | 61 |
60 #ifdef ENABLE_CLI_LOCALTCPFWD | 62 #ifdef ENABLE_CLI_LOCALTCPFWD |
61 void setup_localtcp() { | 63 void setup_localtcp() { |
62 | 64 m_list_elem *iter; |
63 int ret; | 65 int ret; |
64 | 66 |
65 TRACE(("enter setup_localtcp")) | 67 TRACE(("enter setup_localtcp")) |
66 | 68 |
67 if (cli_opts.localfwds == NULL) { | 69 for (iter = cli_opts.localfwds->first; iter; iter = iter->next) { |
68 TRACE(("cli_opts.localfwds == NULL")) | 70 struct TCPFwdEntry * fwd = (struct TCPFwdEntry*)iter->item; |
69 } | 71 ret = cli_localtcp( |
70 | 72 fwd->listenaddr, |
71 while (cli_opts.localfwds != NULL) { | 73 fwd->listenport, |
72 ret = cli_localtcp(cli_opts.localfwds->listenport, | 74 fwd->connectaddr, |
73 cli_opts.localfwds->connectaddr, | 75 fwd->connectport); |
74 cli_opts.localfwds->connectport); | |
75 if (ret == DROPBEAR_FAILURE) { | 76 if (ret == DROPBEAR_FAILURE) { |
76 dropbear_log(LOG_WARNING, "Failed local port forward %d:%s:%d", | 77 dropbear_log(LOG_WARNING, "Failed local port forward %s:%d:%s:%d", |
77 cli_opts.localfwds->listenport, | 78 fwd->listenaddr, |
78 cli_opts.localfwds->connectaddr, | 79 fwd->listenport, |
79 cli_opts.localfwds->connectport); | 80 fwd->connectaddr, |
80 } | 81 fwd->connectport); |
81 | 82 } |
82 cli_opts.localfwds = cli_opts.localfwds->next; | |
83 } | 83 } |
84 TRACE(("leave setup_localtcp")) | 84 TRACE(("leave setup_localtcp")) |
85 | 85 |
86 } | 86 } |
87 | 87 |
88 static int cli_localtcp(unsigned int listenport, const char* remoteaddr, | 88 static int cli_localtcp(const char* listenaddr, |
89 unsigned int listenport, | |
90 const char* remoteaddr, | |
89 unsigned int remoteport) { | 91 unsigned int remoteport) { |
90 | 92 |
91 struct TCPListener* tcpinfo = NULL; | 93 struct TCPListener* tcpinfo = NULL; |
92 int ret; | 94 int ret; |
93 | 95 |
97 tcpinfo = (struct TCPListener*)m_malloc(sizeof(struct TCPListener)); | 99 tcpinfo = (struct TCPListener*)m_malloc(sizeof(struct TCPListener)); |
98 | 100 |
99 tcpinfo->sendaddr = m_strdup(remoteaddr); | 101 tcpinfo->sendaddr = m_strdup(remoteaddr); |
100 tcpinfo->sendport = remoteport; | 102 tcpinfo->sendport = remoteport; |
101 | 103 |
102 if (opts.listen_fwd_all) { | 104 if (listenaddr) |
103 tcpinfo->listenaddr = m_strdup(""); | 105 { |
104 } else { | 106 tcpinfo->listenaddr = m_strdup(listenaddr); |
105 tcpinfo->listenaddr = m_strdup("localhost"); | 107 } |
108 else | |
109 { | |
110 if (opts.listen_fwd_all) { | |
111 tcpinfo->listenaddr = m_strdup(""); | |
112 } else { | |
113 tcpinfo->listenaddr = m_strdup("localhost"); | |
114 } | |
106 } | 115 } |
107 tcpinfo->listenport = listenport; | 116 tcpinfo->listenport = listenport; |
108 | 117 |
109 tcpinfo->chantype = &cli_chan_tcplocal; | 118 tcpinfo->chantype = &cli_chan_tcplocal; |
110 tcpinfo->tcp_type = direct; | 119 tcpinfo->tcp_type = direct; |
118 return ret; | 127 return ret; |
119 } | 128 } |
120 #endif /* ENABLE_CLI_LOCALTCPFWD */ | 129 #endif /* ENABLE_CLI_LOCALTCPFWD */ |
121 | 130 |
122 #ifdef ENABLE_CLI_REMOTETCPFWD | 131 #ifdef ENABLE_CLI_REMOTETCPFWD |
123 static void send_msg_global_request_remotetcp(int port) { | 132 static void send_msg_global_request_remotetcp(const char *addr, int port) { |
124 | 133 |
125 char* listenspec = NULL; | |
126 TRACE(("enter send_msg_global_request_remotetcp")) | 134 TRACE(("enter send_msg_global_request_remotetcp")) |
127 | 135 |
128 CHECKCLEARTOWRITE(); | 136 CHECKCLEARTOWRITE(); |
129 buf_putbyte(ses.writepayload, SSH_MSG_GLOBAL_REQUEST); | 137 buf_putbyte(ses.writepayload, SSH_MSG_GLOBAL_REQUEST); |
130 buf_putstring(ses.writepayload, "tcpip-forward", 13); | 138 buf_putstring(ses.writepayload, "tcpip-forward", 13); |
131 buf_putbyte(ses.writepayload, 1); /* want_reply */ | 139 buf_putbyte(ses.writepayload, 1); /* want_reply */ |
132 if (opts.listen_fwd_all) { | 140 buf_putstring(ses.writepayload, addr, strlen(addr)); |
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); | 141 buf_putint(ses.writepayload, port); |
140 | 142 |
141 encrypt_packet(); | 143 encrypt_packet(); |
142 | 144 |
143 TRACE(("leave send_msg_global_request_remotetcp")) | 145 TRACE(("leave send_msg_global_request_remotetcp")) |
144 } | 146 } |
145 | 147 |
146 /* The only global success/failure messages are for remotetcp. | 148 /* The only global success/failure messages are for remotetcp. |
147 * Since there isn't any identifier in these messages, we have to rely on them | 149 * Since there isn't any identifier in these messages, we have to rely on them |
148 * being in the same order as we sent the requests. This is the ordering | 150 * being in the same order as we sent the requests. This is the ordering |
149 * of the cli_opts.remotefwds list */ | 151 * of the cli_opts.remotefwds list. |
152 * If the requested remote port is 0 the listen port will be | |
153 * dynamically allocated by the server and the port number will be returned | |
154 * to client and the port number reported to the user. */ | |
150 void cli_recv_msg_request_success() { | 155 void cli_recv_msg_request_success() { |
151 | 156 /* We just mark off that we have received the reply, |
152 /* Nothing in the packet. We just mark off that we have received the reply, | |
153 * so that we can report failure for later ones. */ | 157 * so that we can report failure for later ones. */ |
154 struct TCPFwdList * iter = NULL; | 158 m_list_elem * iter = NULL; |
155 | 159 for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) { |
156 iter = cli_opts.remotefwds; | 160 struct TCPFwdEntry *fwd = (struct TCPFwdEntry*)iter->item; |
157 while (iter != NULL) { | 161 if (!fwd->have_reply) { |
158 if (!iter->have_reply) | 162 fwd->have_reply = 1; |
163 if (fwd->listenport == 0) { | |
164 /* The server should let us know which port was allocated if we requestd port 0 */ | |
165 int allocport = buf_getint(ses.payload); | |
166 if (allocport > 0) { | |
167 dropbear_log(LOG_INFO, "Allocated port %d for remote forward to %s:%d", | |
168 allocport, fwd->connectaddr, fwd->connectport); | |
169 } | |
170 } | |
171 return; | |
172 } | |
173 } | |
174 } | |
175 | |
176 void cli_recv_msg_request_failure() { | |
177 m_list_elem *iter; | |
178 for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) { | |
179 struct TCPFwdEntry *fwd = (struct TCPFwdEntry*)iter->item; | |
180 if (!fwd->have_reply) { | |
181 fwd->have_reply = 1; | |
182 dropbear_log(LOG_WARNING, "Remote TCP forward request failed (port %d -> %s:%d)", fwd->listenport, fwd->connectaddr, fwd->connectport); | |
183 return; | |
184 } | |
185 } | |
186 } | |
187 | |
188 void setup_remotetcp() { | |
189 m_list_elem *iter; | |
190 TRACE(("enter setup_remotetcp")) | |
191 | |
192 for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) { | |
193 struct TCPFwdEntry *fwd = (struct TCPFwdEntry*)iter->item; | |
194 if (!fwd->listenaddr) | |
159 { | 195 { |
160 iter->have_reply = 1; | 196 // we store the addresses so that we can compare them |
161 return; | 197 // when the server sends them back |
162 } | 198 if (opts.listen_fwd_all) { |
163 iter = iter->next; | 199 fwd->listenaddr = m_strdup(""); |
164 } | 200 } else { |
165 } | 201 fwd->listenaddr = m_strdup("localhost"); |
166 | 202 } |
167 void cli_recv_msg_request_failure() { | 203 } |
168 struct TCPFwdList * iter = NULL; | 204 send_msg_global_request_remotetcp(fwd->listenaddr, fwd->listenport); |
169 | 205 } |
170 iter = cli_opts.remotefwds; | 206 |
171 while (iter != NULL) { | |
172 if (!iter->have_reply) | |
173 { | |
174 iter->have_reply = 1; | |
175 dropbear_log(LOG_WARNING, "Remote TCP forward request failed (port %d -> %s:%d)", iter->listenport, iter->connectaddr, iter->connectport); | |
176 return; | |
177 } | |
178 iter = iter->next; | |
179 } | |
180 } | |
181 | |
182 void setup_remotetcp() { | |
183 | |
184 struct TCPFwdList * iter = NULL; | |
185 | |
186 TRACE(("enter setup_remotetcp")) | |
187 | |
188 if (cli_opts.remotefwds == NULL) { | |
189 TRACE(("cli_opts.remotefwds == NULL")) | |
190 } | |
191 | |
192 iter = cli_opts.remotefwds; | |
193 | |
194 while (iter != NULL) { | |
195 send_msg_global_request_remotetcp(iter->listenport); | |
196 iter = iter->next; | |
197 } | |
198 TRACE(("leave setup_remotetcp")) | 207 TRACE(("leave setup_remotetcp")) |
199 } | 208 } |
200 | 209 |
201 static int newtcpforwarded(struct Channel * channel) { | 210 static int newtcpforwarded(struct Channel * channel) { |
202 | 211 |
212 char *origaddr = NULL; | |
203 unsigned int origport; | 213 unsigned int origport; |
204 struct TCPFwdList * iter = NULL; | 214 m_list_elem * iter = NULL; |
215 struct TCPFwdEntry *fwd; | |
205 char portstring[NI_MAXSERV]; | 216 char portstring[NI_MAXSERV]; |
206 int sock; | 217 int sock; |
207 int err = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED; | 218 int err = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED; |
208 | 219 |
209 /* We don't care what address they connected to */ | 220 origaddr = buf_getstring(ses.payload, NULL); |
210 buf_eatstring(ses.payload); | |
211 | |
212 origport = buf_getint(ses.payload); | 221 origport = buf_getint(ses.payload); |
213 | 222 |
214 /* Find which port corresponds */ | 223 /* Find which port corresponds */ |
215 iter = cli_opts.remotefwds; | 224 for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) { |
216 | 225 fwd = (struct TCPFwdEntry*)iter->item; |
217 while (iter != NULL) { | 226 if (origport == fwd->listenport |
218 if (origport == iter->listenport) { | 227 && (strcmp(origaddr, fwd->listenaddr) == 0)) { |
219 break; | 228 break; |
220 } | 229 } |
221 iter = iter->next; | |
222 } | 230 } |
223 | 231 |
224 if (iter == NULL) { | 232 if (iter == NULL) { |
225 /* We didn't request forwarding on that port */ | 233 /* We didn't request forwarding on that port */ |
226 dropbear_log(LOG_INFO, "Server send unrequested port, from port %d", | 234 cleantext(origaddr); |
227 origport); | 235 dropbear_log(LOG_INFO, "Server sent unrequested forward from \"%s:%d\"", |
236 origaddr, origport); | |
228 goto out; | 237 goto out; |
229 } | 238 } |
230 | 239 |
231 snprintf(portstring, sizeof(portstring), "%d", iter->connectport); | 240 snprintf(portstring, sizeof(portstring), "%d", fwd->connectport); |
232 sock = connect_remote(iter->connectaddr, portstring, 1, NULL); | 241 sock = connect_remote(fwd->connectaddr, portstring, 1, NULL); |
233 if (sock < 0) { | 242 if (sock < 0) { |
234 TRACE(("leave newtcpdirect: sock failed")) | 243 TRACE(("leave newtcpdirect: sock failed")) |
235 err = SSH_OPEN_CONNECT_FAILED; | 244 err = SSH_OPEN_CONNECT_FAILED; |
236 goto out; | 245 goto out; |
237 } | 246 } |
244 channel->initconn = 1; | 253 channel->initconn = 1; |
245 | 254 |
246 err = SSH_OPEN_IN_PROGRESS; | 255 err = SSH_OPEN_IN_PROGRESS; |
247 | 256 |
248 out: | 257 out: |
258 m_free(origaddr); | |
249 TRACE(("leave newtcpdirect: err %d", err)) | 259 TRACE(("leave newtcpdirect: err %d", err)) |
250 return err; | 260 return err; |
251 } | 261 } |
252 #endif /* ENABLE_CLI_REMOTETCPFWD */ | 262 #endif /* ENABLE_CLI_REMOTETCPFWD */ |