diff options
author | Damien Miller <djm@mindrot.org> | 2000-04-01 11:09:21 +1000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2000-04-01 11:09:21 +1000 |
commit | b38eff8e4ff901df9cf1113a9f14d64c3565a401 (patch) | |
tree | 9a856898f15f7760ed95c5d47789a6f954b4ad2f /channels.c | |
parent | 450a7a1ff40fe7c2d84c93b83cf2df53445d807d (diff) |
- Big OpenBSD CVS update (mainly beginnings of SSH2 infrastructure)
- [auth.c session.c sshd.c auth.h]
split sshd.c -> auth.c session.c sshd.c plus cleanup and goto-removal
- [bufaux.c bufaux.h]
support ssh2 bignums
- [channels.c channels.h clientloop.c sshd.c nchan.c nchan.h packet.c]
[readconf.c ssh.c ssh.h serverloop.c]
replace big switch() with function tables (prepare for ssh2)
- [ssh2.h]
ssh2 message type codes
- [sshd.8]
reorder Xr to avoid cutting
- [serverloop.c]
close(fdin) if fdin != fdout, shutdown otherwise, ok theo@
- [channels.c]
missing close
allow bigger packets
- [cipher.c cipher.h]
support ssh2 ciphers
- [compress.c]
cleanup, less code
- [dispatch.c dispatch.h]
function tables for different message types
- [log-server.c]
do not log() if debuggin to stderr
rename a cpp symbol, to avoid param.h collision
- [mpaux.c]
KNF
- [nchan.c]
sync w/ channels.c
Diffstat (limited to 'channels.c')
-rw-r--r-- | channels.c | 1194 |
1 files changed, 682 insertions, 512 deletions
diff --git a/channels.c b/channels.c index e60ecc614..b87ff9f4f 100644 --- a/channels.c +++ b/channels.c | |||
@@ -16,7 +16,7 @@ | |||
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include "includes.h" | 18 | #include "includes.h" |
19 | RCSID("$Id: channels.c,v 1.19 2000/03/17 12:40:15 damien Exp $"); | 19 | RCSID("$Id: channels.c,v 1.20 2000/04/01 01:09:23 damien Exp $"); |
20 | 20 | ||
21 | #include "ssh.h" | 21 | #include "ssh.h" |
22 | #include "packet.h" | 22 | #include "packet.h" |
@@ -37,6 +37,10 @@ RCSID("$Id: channels.c,v 1.19 2000/03/17 12:40:15 damien Exp $"); | |||
37 | /* Max len of agent socket */ | 37 | /* Max len of agent socket */ |
38 | #define MAX_SOCKET_NAME 100 | 38 | #define MAX_SOCKET_NAME 100 |
39 | 39 | ||
40 | /* default buffer for tcp-fwd-channel */ | ||
41 | #define CHAN_WINDOW_DEFAULT (8*1024) | ||
42 | #define CHAN_PACKET_DEFAULT (CHAN_WINDOW_DEFAULT/2) | ||
43 | |||
40 | /* | 44 | /* |
41 | * Pointer to an array containing all allocated channels. The array is | 45 | * Pointer to an array containing all allocated channels. The array is |
42 | * dynamically extended as needed. | 46 | * dynamically extended as needed. |
@@ -81,8 +85,9 @@ unsigned int x11_fake_data_len; | |||
81 | * network (which might be behind a firewall). | 85 | * network (which might be behind a firewall). |
82 | */ | 86 | */ |
83 | typedef struct { | 87 | typedef struct { |
84 | char *host; /* Host name. */ | 88 | char *host_to_connect; /* Connect to 'host'. */ |
85 | u_short port; /* Port number. */ | 89 | u_short port_to_connect; /* Connect to 'port'. */ |
90 | u_short listen_port; /* Remote side should listen port number. */ | ||
86 | } ForwardPermission; | 91 | } ForwardPermission; |
87 | 92 | ||
88 | /* List of all permitted host/port pairs to connect. */ | 93 | /* List of all permitted host/port pairs to connect. */ |
@@ -119,20 +124,43 @@ channel_permit_all_opens() | |||
119 | all_opens_permitted = 1; | 124 | all_opens_permitted = 1; |
120 | } | 125 | } |
121 | 126 | ||
127 | /* lookup channel by id */ | ||
128 | |||
129 | Channel * | ||
130 | channel_lookup(int id) | ||
131 | { | ||
132 | Channel *c; | ||
133 | if (id < 0 && id > channels_alloc) { | ||
134 | log("channel_lookup: %d: bad id", id); | ||
135 | return NULL; | ||
136 | } | ||
137 | c = &channels[id]; | ||
138 | if (c->type == SSH_CHANNEL_FREE) { | ||
139 | log("channel_lookup: %d: bad id: channel free", id); | ||
140 | return NULL; | ||
141 | } | ||
142 | return c; | ||
143 | } | ||
144 | |||
122 | /* | 145 | /* |
123 | * Allocate a new channel object and set its type and socket. This will cause | 146 | * Allocate a new channel object and set its type and socket. This will cause |
124 | * remote_name to be freed. | 147 | * remote_name to be freed. |
125 | */ | 148 | */ |
126 | 149 | ||
127 | int | 150 | int |
128 | channel_allocate(int type, int sock, char *remote_name) | 151 | channel_new(char *ctype, int type, int rfd, int wfd, int efd, |
152 | int window, int maxpack, int extended_usage, char *remote_name) | ||
129 | { | 153 | { |
130 | int i, found; | 154 | int i, found; |
131 | Channel *c; | 155 | Channel *c; |
132 | 156 | ||
133 | /* Update the maximum file descriptor value. */ | 157 | /* Update the maximum file descriptor value. */ |
134 | if (sock > channel_max_fd_value) | 158 | if (rfd > channel_max_fd_value) |
135 | channel_max_fd_value = sock; | 159 | channel_max_fd_value = rfd; |
160 | if (wfd > channel_max_fd_value) | ||
161 | channel_max_fd_value = wfd; | ||
162 | if (efd > channel_max_fd_value) | ||
163 | channel_max_fd_value = efd; | ||
136 | /* XXX set close-on-exec -markus */ | 164 | /* XXX set close-on-exec -markus */ |
137 | 165 | ||
138 | /* Do initial allocation if this is the first call. */ | 166 | /* Do initial allocation if this is the first call. */ |
@@ -167,388 +195,514 @@ channel_allocate(int type, int sock, char *remote_name) | |||
167 | c = &channels[found]; | 195 | c = &channels[found]; |
168 | buffer_init(&c->input); | 196 | buffer_init(&c->input); |
169 | buffer_init(&c->output); | 197 | buffer_init(&c->output); |
198 | buffer_init(&c->extended); | ||
170 | chan_init_iostates(c); | 199 | chan_init_iostates(c); |
171 | c->self = found; | 200 | c->self = found; |
172 | c->type = type; | 201 | c->type = type; |
173 | c->sock = sock; | 202 | c->ctype = ctype; |
203 | c->local_window = window; | ||
204 | c->local_window_max = window; | ||
205 | c->local_consumed = 0; | ||
206 | c->local_maxpacket = maxpack; | ||
207 | c->remote_window = 0; | ||
208 | c->remote_maxpacket = 0; | ||
209 | c->rfd = rfd; | ||
210 | c->wfd = wfd; | ||
211 | c->sock = (rfd == wfd) ? rfd : -1; | ||
212 | c->efd = efd; | ||
213 | c->extended_usage = extended_usage; | ||
174 | c->remote_id = -1; | 214 | c->remote_id = -1; |
175 | c->remote_name = remote_name; | 215 | c->remote_name = remote_name; |
216 | c->remote_window = 0; | ||
217 | c->remote_maxpacket = 0; | ||
218 | c->cb_fn = NULL; | ||
219 | c->cb_arg = NULL; | ||
220 | c->cb_event = 0; | ||
221 | c->dettach_user = NULL; | ||
176 | debug("channel %d: new [%s]", found, remote_name); | 222 | debug("channel %d: new [%s]", found, remote_name); |
177 | return found; | 223 | return found; |
178 | } | 224 | } |
225 | int | ||
226 | channel_allocate(int type, int sock, char *remote_name) | ||
227 | { | ||
228 | return channel_new("", type, sock, sock, -1, 0, 0, 0, remote_name); | ||
229 | } | ||
179 | 230 | ||
180 | /* Free the channel and close its socket. */ | 231 | /* Free the channel and close its socket. */ |
181 | 232 | ||
182 | void | 233 | void |
183 | channel_free(int channel) | 234 | channel_free(int id) |
184 | { | 235 | { |
185 | if (channel < 0 || channel >= channels_alloc || | 236 | Channel *c = channel_lookup(id); |
186 | channels[channel].type == SSH_CHANNEL_FREE) | 237 | if (c == NULL) |
187 | packet_disconnect("channel free: bad local channel %d", channel); | 238 | packet_disconnect("channel free: bad local channel %d", id); |
188 | 239 | debug("channel_free: channel %d: status: %s", id, channel_open_message()); | |
189 | if (compat13) | 240 | if (c->sock != -1) { |
190 | shutdown(channels[channel].sock, SHUT_RDWR); | 241 | shutdown(c->sock, SHUT_RDWR); |
191 | close(channels[channel].sock); | 242 | close(c->sock); |
192 | buffer_free(&channels[channel].input); | 243 | } |
193 | buffer_free(&channels[channel].output); | 244 | buffer_free(&c->input); |
194 | channels[channel].type = SSH_CHANNEL_FREE; | 245 | buffer_free(&c->output); |
195 | if (channels[channel].remote_name) { | 246 | buffer_free(&c->extended); |
196 | xfree(channels[channel].remote_name); | 247 | c->type = SSH_CHANNEL_FREE; |
197 | channels[channel].remote_name = NULL; | 248 | if (c->remote_name) { |
249 | xfree(c->remote_name); | ||
250 | c->remote_name = NULL; | ||
198 | } | 251 | } |
199 | } | 252 | } |
200 | 253 | ||
201 | /* | 254 | /* |
202 | * This is called just before select() to add any bits relevant to channels | 255 | * 'channel_pre*' are called just before select() to add any bits relevant to |
203 | * in the select bitmasks. | 256 | * channels in the select bitmasks. |
257 | */ | ||
258 | /* | ||
259 | * 'channel_post*': perform any appropriate operations for channels which | ||
260 | * have events pending. | ||
204 | */ | 261 | */ |
262 | typedef void chan_fn(Channel *c, fd_set * readset, fd_set * writeset); | ||
263 | chan_fn *channel_pre[SSH_CHANNEL_MAX_TYPE]; | ||
264 | chan_fn *channel_post[SSH_CHANNEL_MAX_TYPE]; | ||
205 | 265 | ||
206 | void | 266 | void |
207 | channel_prepare_select(fd_set * readset, fd_set * writeset) | 267 | channel_pre_listener(Channel *c, fd_set * readset, fd_set * writeset) |
208 | { | 268 | { |
209 | int i; | 269 | FD_SET(c->sock, readset); |
210 | Channel *ch; | 270 | } |
211 | unsigned char *ucp; | ||
212 | unsigned int proto_len, data_len; | ||
213 | 271 | ||
214 | for (i = 0; i < channels_alloc; i++) { | 272 | void |
215 | ch = &channels[i]; | 273 | channel_pre_open_13(Channel *c, fd_set * readset, fd_set * writeset) |
216 | redo: | 274 | { |
217 | switch (ch->type) { | 275 | if (buffer_len(&c->input) < packet_get_maxsize()) |
218 | case SSH_CHANNEL_X11_LISTENER: | 276 | FD_SET(c->sock, readset); |
219 | case SSH_CHANNEL_PORT_LISTENER: | 277 | if (buffer_len(&c->output) > 0) |
220 | case SSH_CHANNEL_AUTH_SOCKET: | 278 | FD_SET(c->sock, writeset); |
221 | FD_SET(ch->sock, readset); | 279 | } |
222 | break; | ||
223 | 280 | ||
224 | case SSH_CHANNEL_OPEN: | 281 | void |
225 | if (compat13) { | 282 | channel_pre_open_15(Channel *c, fd_set * readset, fd_set * writeset) |
226 | if (buffer_len(&ch->input) < packet_get_maxsize()) | 283 | { |
227 | FD_SET(ch->sock, readset); | 284 | /* test whether sockets are 'alive' for read/write */ |
228 | if (buffer_len(&ch->output) > 0) | 285 | if (c->istate == CHAN_INPUT_OPEN) |
229 | FD_SET(ch->sock, writeset); | 286 | if (buffer_len(&c->input) < packet_get_maxsize()) |
230 | break; | 287 | FD_SET(c->sock, readset); |
231 | } | 288 | if (c->ostate == CHAN_OUTPUT_OPEN || |
232 | /* test whether sockets are 'alive' for read/write */ | 289 | c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { |
233 | if (ch->istate == CHAN_INPUT_OPEN) | 290 | if (buffer_len(&c->output) > 0) { |
234 | if (buffer_len(&ch->input) < packet_get_maxsize()) | 291 | FD_SET(c->sock, writeset); |
235 | FD_SET(ch->sock, readset); | 292 | } else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { |
236 | if (ch->ostate == CHAN_OUTPUT_OPEN || | 293 | chan_obuf_empty(c); |
237 | ch->ostate == CHAN_OUTPUT_WAIT_DRAIN) { | 294 | } |
238 | if (buffer_len(&ch->output) > 0) { | 295 | } |
239 | FD_SET(ch->sock, writeset); | 296 | } |
240 | } else if (ch->ostate == CHAN_OUTPUT_WAIT_DRAIN) { | ||
241 | chan_obuf_empty(ch); | ||
242 | } | ||
243 | } | ||
244 | break; | ||
245 | 297 | ||
246 | case SSH_CHANNEL_INPUT_DRAINING: | 298 | void |
247 | if (!compat13) | 299 | channel_pre_input_draining(Channel *c, fd_set * readset, fd_set * writeset) |
248 | fatal("cannot happen: IN_DRAIN"); | 300 | { |
249 | if (buffer_len(&ch->input) == 0) { | 301 | if (buffer_len(&c->input) == 0) { |
250 | packet_start(SSH_MSG_CHANNEL_CLOSE); | 302 | packet_start(SSH_MSG_CHANNEL_CLOSE); |
251 | packet_put_int(ch->remote_id); | 303 | packet_put_int(c->remote_id); |
252 | packet_send(); | 304 | packet_send(); |
253 | ch->type = SSH_CHANNEL_CLOSED; | 305 | c->type = SSH_CHANNEL_CLOSED; |
254 | debug("Closing channel %d after input drain.", ch->self); | 306 | debug("Closing channel %d after input drain.", c->self); |
255 | break; | 307 | } |
256 | } | 308 | } |
257 | break; | ||
258 | 309 | ||
259 | case SSH_CHANNEL_OUTPUT_DRAINING: | 310 | void |
260 | if (!compat13) | 311 | channel_pre_output_draining(Channel *c, fd_set * readset, fd_set * writeset) |
261 | fatal("cannot happen: OUT_DRAIN"); | 312 | { |
262 | if (buffer_len(&ch->output) == 0) { | 313 | if (buffer_len(&c->output) == 0) |
263 | channel_free(i); | 314 | channel_free(c->self); |
264 | break; | 315 | else |
265 | } | 316 | FD_SET(c->sock, writeset); |
266 | FD_SET(ch->sock, writeset); | 317 | } |
267 | break; | ||
268 | 318 | ||
269 | case SSH_CHANNEL_X11_OPEN: | 319 | /* |
270 | /* | 320 | * This is a special state for X11 authentication spoofing. An opened X11 |
271 | * This is a special state for X11 authentication | 321 | * connection (when authentication spoofing is being done) remains in this |
272 | * spoofing. An opened X11 connection (when | 322 | * state until the first packet has been completely read. The authentication |
273 | * authentication spoofing is being done) remains in | 323 | * data in that packet is then substituted by the real data if it matches the |
274 | * this state until the first packet has been | 324 | * fake data, and the channel is put into normal mode. |
275 | * completely read. The authentication data in that | 325 | */ |
276 | * packet is then substituted by the real data if it | 326 | int |
277 | * matches the fake data, and the channel is put into | 327 | x11_open_helper(Channel *c) |
278 | * normal mode. | 328 | { |
279 | */ | 329 | unsigned char *ucp; |
280 | /* Check if the fixed size part of the packet is in buffer. */ | 330 | unsigned int proto_len, data_len; |
281 | if (buffer_len(&ch->output) < 12) | ||
282 | break; | ||
283 | 331 | ||
284 | /* Parse the lengths of variable-length fields. */ | 332 | /* Check if the fixed size part of the packet is in buffer. */ |
285 | ucp = (unsigned char *) buffer_ptr(&ch->output); | 333 | if (buffer_len(&c->output) < 12) |
286 | if (ucp[0] == 0x42) { /* Byte order MSB first. */ | 334 | return 0; |
287 | proto_len = 256 * ucp[6] + ucp[7]; | 335 | |
288 | data_len = 256 * ucp[8] + ucp[9]; | 336 | /* Parse the lengths of variable-length fields. */ |
289 | } else if (ucp[0] == 0x6c) { /* Byte order LSB first. */ | 337 | ucp = (unsigned char *) buffer_ptr(&c->output); |
290 | proto_len = ucp[6] + 256 * ucp[7]; | 338 | if (ucp[0] == 0x42) { /* Byte order MSB first. */ |
291 | data_len = ucp[8] + 256 * ucp[9]; | 339 | proto_len = 256 * ucp[6] + ucp[7]; |
292 | } else { | 340 | data_len = 256 * ucp[8] + ucp[9]; |
293 | debug("Initial X11 packet contains bad byte order byte: 0x%x", | 341 | } else if (ucp[0] == 0x6c) { /* Byte order LSB first. */ |
294 | ucp[0]); | 342 | proto_len = ucp[6] + 256 * ucp[7]; |
295 | ch->type = SSH_CHANNEL_OPEN; | 343 | data_len = ucp[8] + 256 * ucp[9]; |
296 | goto reject; | 344 | } else { |
297 | } | 345 | debug("Initial X11 packet contains bad byte order byte: 0x%x", |
346 | ucp[0]); | ||
347 | return -1; | ||
348 | } | ||
298 | 349 | ||
299 | /* Check if the whole packet is in buffer. */ | 350 | /* Check if the whole packet is in buffer. */ |
300 | if (buffer_len(&ch->output) < | 351 | if (buffer_len(&c->output) < |
301 | 12 + ((proto_len + 3) & ~3) + ((data_len + 3) & ~3)) | 352 | 12 + ((proto_len + 3) & ~3) + ((data_len + 3) & ~3)) |
302 | break; | 353 | return 0; |
303 | 354 | ||
304 | /* Check if authentication protocol matches. */ | 355 | /* Check if authentication protocol matches. */ |
305 | if (proto_len != strlen(x11_saved_proto) || | 356 | if (proto_len != strlen(x11_saved_proto) || |
306 | memcmp(ucp + 12, x11_saved_proto, proto_len) != 0) { | 357 | memcmp(ucp + 12, x11_saved_proto, proto_len) != 0) { |
307 | debug("X11 connection uses different authentication protocol."); | 358 | debug("X11 connection uses different authentication protocol."); |
308 | ch->type = SSH_CHANNEL_OPEN; | 359 | return -1; |
309 | goto reject; | 360 | } |
310 | } | 361 | /* Check if authentication data matches our fake data. */ |
311 | /* Check if authentication data matches our fake data. */ | 362 | if (data_len != x11_fake_data_len || |
312 | if (data_len != x11_fake_data_len || | 363 | memcmp(ucp + 12 + ((proto_len + 3) & ~3), |
313 | memcmp(ucp + 12 + ((proto_len + 3) & ~3), | 364 | x11_fake_data, x11_fake_data_len) != 0) { |
314 | x11_fake_data, x11_fake_data_len) != 0) { | 365 | debug("X11 auth data does not match fake data."); |
315 | debug("X11 auth data does not match fake data."); | 366 | return -1; |
316 | ch->type = SSH_CHANNEL_OPEN; | 367 | } |
317 | goto reject; | 368 | /* Check fake data length */ |
318 | } | 369 | if (x11_fake_data_len != x11_saved_data_len) { |
319 | /* Check fake data length */ | 370 | error("X11 fake_data_len %d != saved_data_len %d", |
320 | if (x11_fake_data_len != x11_saved_data_len) { | 371 | x11_fake_data_len, x11_saved_data_len); |
321 | error("X11 fake_data_len %d != saved_data_len %d", | 372 | return -1; |
322 | x11_fake_data_len, x11_saved_data_len); | 373 | } |
323 | ch->type = SSH_CHANNEL_OPEN; | 374 | /* |
324 | goto reject; | 375 | * Received authentication protocol and data match |
325 | } | 376 | * our fake data. Substitute the fake data with real |
326 | /* | 377 | * data. |
327 | * Received authentication protocol and data match | 378 | */ |
328 | * our fake data. Substitute the fake data with real | 379 | memcpy(ucp + 12 + ((proto_len + 3) & ~3), |
329 | * data. | 380 | x11_saved_data, x11_saved_data_len); |
330 | */ | 381 | return 1; |
331 | memcpy(ucp + 12 + ((proto_len + 3) & ~3), | 382 | } |
332 | x11_saved_data, x11_saved_data_len); | ||
333 | 383 | ||
334 | /* Start normal processing for the channel. */ | 384 | void |
335 | ch->type = SSH_CHANNEL_OPEN; | 385 | channel_pre_x11_open_13(Channel *c, fd_set * readset, fd_set * writeset) |
336 | goto redo; | 386 | { |
387 | int ret = x11_open_helper(c); | ||
388 | if (ret == 1) { | ||
389 | /* Start normal processing for the channel. */ | ||
390 | c->type = SSH_CHANNEL_OPEN; | ||
391 | } else if (ret == -1) { | ||
392 | /* | ||
393 | * We have received an X11 connection that has bad | ||
394 | * authentication information. | ||
395 | */ | ||
396 | log("X11 connection rejected because of wrong authentication.\r\n"); | ||
397 | buffer_clear(&c->input); | ||
398 | buffer_clear(&c->output); | ||
399 | close(c->sock); | ||
400 | c->sock = -1; | ||
401 | c->type = SSH_CHANNEL_CLOSED; | ||
402 | packet_start(SSH_MSG_CHANNEL_CLOSE); | ||
403 | packet_put_int(c->remote_id); | ||
404 | packet_send(); | ||
405 | } | ||
406 | } | ||
337 | 407 | ||
338 | reject: | 408 | void |
339 | /* | 409 | channel_pre_x11_open_15(Channel *c, fd_set * readset, fd_set * writeset) |
340 | * We have received an X11 connection that has bad | 410 | { |
341 | * authentication information. | 411 | int ret = x11_open_helper(c); |
342 | */ | 412 | if (ret == 1) { |
343 | log("X11 connection rejected because of wrong authentication.\r\n"); | 413 | c->type = SSH_CHANNEL_OPEN; |
344 | buffer_clear(&ch->input); | 414 | } else if (ret == -1) { |
345 | buffer_clear(&ch->output); | 415 | debug("X11 rejected %d i%d/o%d", c->self, c->istate, c->ostate); |
346 | if (compat13) { | 416 | chan_read_failed(c); |
347 | close(ch->sock); | 417 | chan_write_failed(c); |
348 | ch->sock = -1; | 418 | debug("X11 closed %d i%d/o%d", c->self, c->istate, c->ostate); |
349 | ch->type = SSH_CHANNEL_CLOSED; | 419 | } |
350 | packet_start(SSH_MSG_CHANNEL_CLOSE); | 420 | } |
351 | packet_put_int(ch->remote_id); | ||
352 | packet_send(); | ||
353 | } else { | ||
354 | debug("X11 rejected %d i%d/o%d", ch->self, ch->istate, ch->ostate); | ||
355 | chan_read_failed(ch); | ||
356 | chan_write_failed(ch); | ||
357 | debug("X11 rejected %d i%d/o%d", ch->self, ch->istate, ch->ostate); | ||
358 | } | ||
359 | break; | ||
360 | 421 | ||
361 | case SSH_CHANNEL_FREE: | 422 | /* This is our fake X11 server socket. */ |
362 | default: | 423 | void |
363 | continue; | 424 | channel_post_x11_listener(Channel *c, fd_set * readset, fd_set * writeset) |
425 | { | ||
426 | struct sockaddr addr; | ||
427 | int newsock, newch; | ||
428 | socklen_t addrlen; | ||
429 | char buf[16384], *remote_hostname; | ||
430 | |||
431 | if (FD_ISSET(c->sock, readset)) { | ||
432 | debug("X11 connection requested."); | ||
433 | addrlen = sizeof(addr); | ||
434 | newsock = accept(c->sock, &addr, &addrlen); | ||
435 | if (newsock < 0) { | ||
436 | error("accept: %.100s", strerror(errno)); | ||
437 | return; | ||
364 | } | 438 | } |
439 | remote_hostname = get_remote_hostname(newsock); | ||
440 | snprintf(buf, sizeof buf, "X11 connection from %.200s port %d", | ||
441 | remote_hostname, get_peer_port(newsock)); | ||
442 | xfree(remote_hostname); | ||
443 | newch = channel_allocate(SSH_CHANNEL_OPENING, newsock, | ||
444 | xstrdup(buf)); | ||
445 | packet_start(SSH_SMSG_X11_OPEN); | ||
446 | packet_put_int(newch); | ||
447 | if (have_hostname_in_open) | ||
448 | packet_put_string(buf, strlen(buf)); | ||
449 | packet_send(); | ||
365 | } | 450 | } |
366 | } | 451 | } |
367 | 452 | ||
368 | /* | 453 | /* |
369 | * After select, perform any appropriate operations for channels which have | 454 | * This socket is listening for connections to a forwarded TCP/IP port. |
370 | * events pending. | ||
371 | */ | 455 | */ |
456 | void | ||
457 | channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset) | ||
458 | { | ||
459 | struct sockaddr addr; | ||
460 | int newsock, newch; | ||
461 | socklen_t addrlen; | ||
462 | char buf[1024], *remote_hostname; | ||
463 | int remote_port; | ||
464 | |||
465 | if (FD_ISSET(c->sock, readset)) { | ||
466 | debug("Connection to port %d forwarding " | ||
467 | "to %.100s port %d requested.", | ||
468 | c->listening_port, c->path, c->host_port); | ||
469 | addrlen = sizeof(addr); | ||
470 | newsock = accept(c->sock, &addr, &addrlen); | ||
471 | if (newsock < 0) { | ||
472 | error("accept: %.100s", strerror(errno)); | ||
473 | return; | ||
474 | } | ||
475 | remote_hostname = get_remote_hostname(newsock); | ||
476 | remote_port = get_peer_port(newsock); | ||
477 | snprintf(buf, sizeof buf, | ||
478 | "listen port %d for %.100s port %d, " | ||
479 | "connect from %.200s port %d", | ||
480 | c->listening_port, c->path, c->host_port, | ||
481 | remote_hostname, remote_port); | ||
482 | newch = channel_new("direct-tcpip", | ||
483 | SSH_CHANNEL_OPENING, newsock, newsock, -1, | ||
484 | c->local_window_max, c->local_maxpacket, | ||
485 | 0, xstrdup(buf)); | ||
486 | |||
487 | packet_start(SSH_MSG_PORT_OPEN); | ||
488 | packet_put_int(newch); | ||
489 | packet_put_string(c->path, strlen(c->path)); | ||
490 | packet_put_int(c->host_port); | ||
491 | if (have_hostname_in_open) { | ||
492 | packet_put_string(buf, strlen(buf)); | ||
493 | } | ||
494 | packet_send(); | ||
495 | xfree(remote_hostname); | ||
496 | } | ||
497 | } | ||
372 | 498 | ||
373 | void | 499 | /* |
374 | channel_after_select(fd_set * readset, fd_set * writeset) | 500 | * This is the authentication agent socket listening for connections from |
501 | * clients. | ||
502 | */ | ||
503 | void | ||
504 | channel_post_auth_listener(Channel *c, fd_set * readset, fd_set * writeset) | ||
375 | { | 505 | { |
376 | struct sockaddr addr; | 506 | struct sockaddr addr; |
377 | int newsock, i, newch, len; | 507 | int newsock, newch; |
378 | socklen_t addrlen; | 508 | socklen_t addrlen; |
379 | Channel *ch; | ||
380 | char buf[16384], *remote_hostname; | ||
381 | 509 | ||
382 | /* Loop over all channels... */ | 510 | if (FD_ISSET(c->sock, readset)) { |
383 | for (i = 0; i < channels_alloc; i++) { | 511 | addrlen = sizeof(addr); |
384 | ch = &channels[i]; | 512 | newsock = accept(c->sock, &addr, &addrlen); |
385 | switch (ch->type) { | 513 | if (newsock < 0) { |
386 | case SSH_CHANNEL_X11_LISTENER: | 514 | error("accept from auth socket: %.100s", strerror(errno)); |
387 | /* This is our fake X11 server socket. */ | 515 | return; |
388 | if (FD_ISSET(ch->sock, readset)) { | 516 | } |
389 | debug("X11 connection requested."); | 517 | newch = channel_allocate(SSH_CHANNEL_OPENING, newsock, |
390 | addrlen = sizeof(addr); | 518 | xstrdup("accepted auth socket")); |
391 | newsock = accept(ch->sock, &addr, &addrlen); | 519 | packet_start(SSH_SMSG_AGENT_OPEN); |
392 | if (newsock < 0) { | 520 | packet_put_int(newch); |
393 | error("accept: %.100s", strerror(errno)); | 521 | packet_send(); |
394 | break; | 522 | } |
395 | } | 523 | } |
396 | remote_hostname = get_remote_hostname(newsock); | ||
397 | snprintf(buf, sizeof buf, "X11 connection from %.200s port %d", | ||
398 | remote_hostname, get_peer_port(newsock)); | ||
399 | xfree(remote_hostname); | ||
400 | newch = channel_allocate(SSH_CHANNEL_OPENING, newsock, | ||
401 | xstrdup(buf)); | ||
402 | packet_start(SSH_SMSG_X11_OPEN); | ||
403 | packet_put_int(newch); | ||
404 | if (have_hostname_in_open) | ||
405 | packet_put_string(buf, strlen(buf)); | ||
406 | packet_send(); | ||
407 | } | ||
408 | break; | ||
409 | 524 | ||
410 | case SSH_CHANNEL_PORT_LISTENER: | 525 | int |
411 | /* | 526 | channel_handle_rfd(Channel *c, fd_set * readset, fd_set * writeset) |
412 | * This socket is listening for connections to a | 527 | { |
413 | * forwarded TCP/IP port. | 528 | char buf[16*1024]; |
414 | */ | 529 | int len; |
415 | if (FD_ISSET(ch->sock, readset)) { | 530 | |
416 | debug("Connection to port %d forwarding to %.100s port %d requested.", | 531 | if (c->rfd != -1 && |
417 | ch->listening_port, ch->path, ch->host_port); | 532 | FD_ISSET(c->rfd, readset)) { |
418 | addrlen = sizeof(addr); | 533 | len = read(c->rfd, buf, sizeof(buf)); |
419 | newsock = accept(ch->sock, &addr, &addrlen); | 534 | if (len <= 0) { |
420 | if (newsock < 0) { | 535 | debug("channel %d: read<0 rfd %d len %d", |
421 | error("accept: %.100s", strerror(errno)); | 536 | c->self, c->rfd, len); |
422 | break; | 537 | if (compat13) { |
423 | } | 538 | buffer_consume(&c->output, buffer_len(&c->output)); |
424 | remote_hostname = get_remote_hostname(newsock); | 539 | c->type = SSH_CHANNEL_INPUT_DRAINING; |
425 | snprintf(buf, sizeof buf, "listen port %d for %.100s port %d, connect from %.200s port %d", | 540 | debug("Channel %d status set to input draining.", c->self); |
426 | ch->listening_port, ch->path, ch->host_port, | 541 | } else { |
427 | remote_hostname, get_peer_port(newsock)); | 542 | chan_read_failed(c); |
428 | xfree(remote_hostname); | ||
429 | newch = channel_allocate(SSH_CHANNEL_OPENING, newsock, | ||
430 | xstrdup(buf)); | ||
431 | packet_start(SSH_MSG_PORT_OPEN); | ||
432 | packet_put_int(newch); | ||
433 | packet_put_string(ch->path, strlen(ch->path)); | ||
434 | packet_put_int(ch->host_port); | ||
435 | if (have_hostname_in_open) | ||
436 | packet_put_string(buf, strlen(buf)); | ||
437 | packet_send(); | ||
438 | } | 543 | } |
439 | break; | 544 | return -1; |
440 | 545 | } | |
441 | case SSH_CHANNEL_AUTH_SOCKET: | 546 | buffer_append(&c->input, buf, len); |
442 | /* | 547 | } |
443 | * This is the authentication agent socket listening | 548 | return 1; |
444 | * for connections from clients. | 549 | } |
445 | */ | 550 | int |
446 | if (FD_ISSET(ch->sock, readset)) { | 551 | channel_handle_wfd(Channel *c, fd_set * readset, fd_set * writeset) |
447 | addrlen = sizeof(addr); | 552 | { |
448 | newsock = accept(ch->sock, &addr, &addrlen); | 553 | int len; |
449 | if (newsock < 0) { | 554 | |
450 | error("accept from auth socket: %.100s", strerror(errno)); | 555 | /* Send buffered output data to the socket. */ |
451 | break; | 556 | if (c->wfd != -1 && |
452 | } | 557 | FD_ISSET(c->wfd, writeset) && |
453 | newch = channel_allocate(SSH_CHANNEL_OPENING, newsock, | 558 | buffer_len(&c->output) > 0) { |
454 | xstrdup("accepted auth socket")); | 559 | len = write(c->wfd, buffer_ptr(&c->output), |
455 | packet_start(SSH_SMSG_AGENT_OPEN); | 560 | buffer_len(&c->output)); |
456 | packet_put_int(newch); | 561 | if (len <= 0) { |
457 | packet_send(); | 562 | if (compat13) { |
563 | buffer_consume(&c->output, buffer_len(&c->output)); | ||
564 | debug("Channel %d status set to input draining.", c->self); | ||
565 | c->type = SSH_CHANNEL_INPUT_DRAINING; | ||
566 | } else { | ||
567 | chan_write_failed(c); | ||
458 | } | 568 | } |
459 | break; | 569 | return -1; |
570 | } | ||
571 | buffer_consume(&c->output, len); | ||
572 | } | ||
573 | return 1; | ||
574 | } | ||
460 | 575 | ||
461 | case SSH_CHANNEL_OPEN: | 576 | void |
462 | /* | 577 | channel_post_open_1(Channel *c, fd_set * readset, fd_set * writeset) |
463 | * This is an open two-way communication channel. It | 578 | { |
464 | * is not of interest to us at this point what kind | 579 | channel_handle_rfd(c, readset, writeset); |
465 | * of data is being transmitted. | 580 | channel_handle_wfd(c, readset, writeset); |
466 | */ | 581 | } |
467 | 582 | ||
468 | /* | 583 | void |
469 | * Read available incoming data and append it to | 584 | channel_post_output_drain_13(Channel *c, fd_set * readset, fd_set * writeset) |
470 | * buffer; shutdown socket, if read or write failes | 585 | { |
471 | */ | 586 | int len; |
472 | if (FD_ISSET(ch->sock, readset)) { | 587 | /* Send buffered output data to the socket. */ |
473 | len = read(ch->sock, buf, sizeof(buf)); | 588 | if (FD_ISSET(c->sock, writeset) && buffer_len(&c->output) > 0) { |
474 | if (len <= 0) { | 589 | len = write(c->sock, buffer_ptr(&c->output), |
475 | if (compat13) { | 590 | buffer_len(&c->output)); |
476 | buffer_consume(&ch->output, buffer_len(&ch->output)); | 591 | if (len <= 0) |
477 | ch->type = SSH_CHANNEL_INPUT_DRAINING; | 592 | buffer_consume(&c->output, buffer_len(&c->output)); |
478 | debug("Channel %d status set to input draining.", i); | 593 | else |
479 | } else { | 594 | buffer_consume(&c->output, len); |
480 | chan_read_failed(ch); | 595 | } |
481 | } | 596 | } |
482 | break; | ||
483 | } | ||
484 | buffer_append(&ch->input, buf, len); | ||
485 | } | ||
486 | /* Send buffered output data to the socket. */ | ||
487 | if (FD_ISSET(ch->sock, writeset) && buffer_len(&ch->output) > 0) { | ||
488 | len = write(ch->sock, buffer_ptr(&ch->output), | ||
489 | buffer_len(&ch->output)); | ||
490 | if (len <= 0) { | ||
491 | if (compat13) { | ||
492 | buffer_consume(&ch->output, buffer_len(&ch->output)); | ||
493 | debug("Channel %d status set to input draining.", i); | ||
494 | ch->type = SSH_CHANNEL_INPUT_DRAINING; | ||
495 | } else { | ||
496 | chan_write_failed(ch); | ||
497 | } | ||
498 | break; | ||
499 | } | ||
500 | buffer_consume(&ch->output, len); | ||
501 | } | ||
502 | break; | ||
503 | 597 | ||
504 | case SSH_CHANNEL_OUTPUT_DRAINING: | 598 | void |
505 | if (!compat13) | 599 | channel_handler_init_13(void) |
506 | fatal("cannot happen: OUT_DRAIN"); | 600 | { |
507 | /* Send buffered output data to the socket. */ | 601 | channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open_13; |
508 | if (FD_ISSET(ch->sock, writeset) && buffer_len(&ch->output) > 0) { | 602 | channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open_13; |
509 | len = write(ch->sock, buffer_ptr(&ch->output), | 603 | channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener; |
510 | buffer_len(&ch->output)); | 604 | channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; |
511 | if (len <= 0) | 605 | channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; |
512 | buffer_consume(&ch->output, buffer_len(&ch->output)); | 606 | channel_pre[SSH_CHANNEL_INPUT_DRAINING] = &channel_pre_input_draining; |
513 | else | 607 | channel_pre[SSH_CHANNEL_OUTPUT_DRAINING] = &channel_pre_output_draining; |
514 | buffer_consume(&ch->output, len); | 608 | |
515 | } | 609 | channel_post[SSH_CHANNEL_OPEN] = &channel_post_open_1; |
516 | break; | 610 | channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; |
611 | channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; | ||
612 | channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; | ||
613 | channel_post[SSH_CHANNEL_OUTPUT_DRAINING] = &channel_post_output_drain_13; | ||
614 | } | ||
517 | 615 | ||
518 | case SSH_CHANNEL_X11_OPEN: | 616 | void |
519 | case SSH_CHANNEL_FREE: | 617 | channel_handler_init_15(void) |
520 | default: | 618 | { |
619 | channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open_15; | ||
620 | channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open_15; | ||
621 | channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener; | ||
622 | channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; | ||
623 | channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; | ||
624 | |||
625 | channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; | ||
626 | channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; | ||
627 | channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; | ||
628 | channel_post[SSH_CHANNEL_OPEN] = &channel_post_open_1; | ||
629 | } | ||
630 | |||
631 | void | ||
632 | channel_handler_init(void) | ||
633 | { | ||
634 | int i; | ||
635 | for(i = 0; i < SSH_CHANNEL_MAX_TYPE; i++) { | ||
636 | channel_pre[i] = NULL; | ||
637 | channel_post[i] = NULL; | ||
638 | } | ||
639 | if (compat13) | ||
640 | channel_handler_init_13(); | ||
641 | else | ||
642 | channel_handler_init_15(); | ||
643 | } | ||
644 | |||
645 | void | ||
646 | channel_handler(chan_fn *ftab[], fd_set * readset, fd_set * writeset) | ||
647 | { | ||
648 | static int did_init = 0; | ||
649 | int i; | ||
650 | Channel *c; | ||
651 | |||
652 | if (!did_init) { | ||
653 | channel_handler_init(); | ||
654 | did_init = 1; | ||
655 | } | ||
656 | for (i = 0; i < channels_alloc; i++) { | ||
657 | c = &channels[i]; | ||
658 | if (c->type == SSH_CHANNEL_FREE) | ||
521 | continue; | 659 | continue; |
522 | } | 660 | if (ftab[c->type] == NULL) |
661 | continue; | ||
662 | (*ftab[c->type])(c, readset, writeset); | ||
663 | if (!compat13) | ||
664 | chan_delete_if_full_closed(c); | ||
523 | } | 665 | } |
524 | } | 666 | } |
525 | 667 | ||
668 | void | ||
669 | channel_prepare_select(fd_set * readset, fd_set * writeset) | ||
670 | { | ||
671 | channel_handler(channel_pre, readset, writeset); | ||
672 | } | ||
673 | |||
674 | void | ||
675 | channel_after_select(fd_set * readset, fd_set * writeset) | ||
676 | { | ||
677 | channel_handler(channel_post, readset, writeset); | ||
678 | } | ||
679 | |||
526 | /* If there is data to send to the connection, send some of it now. */ | 680 | /* If there is data to send to the connection, send some of it now. */ |
527 | 681 | ||
528 | void | 682 | void |
529 | channel_output_poll() | 683 | channel_output_poll() |
530 | { | 684 | { |
531 | int len, i; | 685 | int len, i; |
532 | Channel *ch; | 686 | Channel *c; |
533 | 687 | ||
534 | for (i = 0; i < channels_alloc; i++) { | 688 | for (i = 0; i < channels_alloc; i++) { |
535 | ch = &channels[i]; | 689 | c = &channels[i]; |
536 | 690 | ||
537 | /* We are only interested in channels that can have buffered incoming data. */ | 691 | /* We are only interested in channels that can have buffered incoming data. */ |
538 | if (compat13) { | 692 | if (compat13) { |
539 | if (ch->type != SSH_CHANNEL_OPEN && | 693 | if (c->type != SSH_CHANNEL_OPEN && |
540 | ch->type != SSH_CHANNEL_INPUT_DRAINING) | 694 | c->type != SSH_CHANNEL_INPUT_DRAINING) |
541 | continue; | 695 | continue; |
542 | } else { | 696 | } else { |
543 | if (ch->type != SSH_CHANNEL_OPEN) | 697 | if (c->type != SSH_CHANNEL_OPEN) |
544 | continue; | 698 | continue; |
545 | if (ch->istate != CHAN_INPUT_OPEN && | 699 | if (c->istate != CHAN_INPUT_OPEN && |
546 | ch->istate != CHAN_INPUT_WAIT_DRAIN) | 700 | c->istate != CHAN_INPUT_WAIT_DRAIN) |
547 | continue; | 701 | continue; |
548 | } | 702 | } |
549 | 703 | ||
550 | /* Get the amount of buffered data for this channel. */ | 704 | /* Get the amount of buffered data for this channel. */ |
551 | len = buffer_len(&ch->input); | 705 | len = buffer_len(&c->input); |
552 | if (len > 0) { | 706 | if (len > 0) { |
553 | /* Send some data for the other side over the secure connection. */ | 707 | /* Send some data for the other side over the secure connection. */ |
554 | if (packet_is_interactive()) { | 708 | if (packet_is_interactive()) { |
@@ -556,22 +710,26 @@ channel_output_poll() | |||
556 | len = 512; | 710 | len = 512; |
557 | } else { | 711 | } else { |
558 | /* Keep the packets at reasonable size. */ | 712 | /* Keep the packets at reasonable size. */ |
559 | if (len > packet_get_maxsize()/2) | 713 | if (len > packet_get_maxsize()) |
560 | len = packet_get_maxsize()/2; | 714 | len = packet_get_maxsize()/2; |
561 | } | 715 | } |
562 | packet_start(SSH_MSG_CHANNEL_DATA); | 716 | if (len > 0) { |
563 | packet_put_int(ch->remote_id); | 717 | packet_start(SSH_MSG_CHANNEL_DATA); |
564 | packet_put_string(buffer_ptr(&ch->input), len); | 718 | packet_put_int(c->remote_id); |
565 | packet_send(); | 719 | packet_put_string(buffer_ptr(&c->input), len); |
566 | buffer_consume(&ch->input, len); | 720 | packet_send(); |
567 | } else if (ch->istate == CHAN_INPUT_WAIT_DRAIN) { | 721 | buffer_consume(&c->input, len); |
722 | c->remote_window -= len; | ||
723 | debug("channel %d: send data len %d", c->self, len); | ||
724 | } | ||
725 | } else if (c->istate == CHAN_INPUT_WAIT_DRAIN) { | ||
568 | if (compat13) | 726 | if (compat13) |
569 | fatal("cannot happen: istate == INPUT_WAIT_DRAIN for proto 1.3"); | 727 | fatal("cannot happen: istate == INPUT_WAIT_DRAIN for proto 1.3"); |
570 | /* | 728 | /* |
571 | * input-buffer is empty and read-socket shutdown: | 729 | * input-buffer is empty and read-socket shutdown: |
572 | * tell peer, that we will not send more data: send IEOF | 730 | * tell peer, that we will not send more data: send IEOF |
573 | */ | 731 | */ |
574 | chan_ibuf_empty(ch); | 732 | chan_ibuf_empty(c); |
575 | } | 733 | } |
576 | } | 734 | } |
577 | } | 735 | } |
@@ -583,35 +741,33 @@ channel_output_poll() | |||
583 | */ | 741 | */ |
584 | 742 | ||
585 | void | 743 | void |
586 | channel_input_data(int payload_len) | 744 | channel_input_data(int type, int plen) |
587 | { | 745 | { |
588 | int id; | 746 | int id; |
589 | char *data; | 747 | char *data; |
590 | unsigned int data_len; | 748 | unsigned int data_len; |
591 | Channel *ch; | 749 | Channel *c; |
592 | 750 | ||
593 | /* Get the channel number and verify it. */ | 751 | /* Get the channel number and verify it. */ |
594 | id = packet_get_int(); | 752 | id = packet_get_int(); |
595 | if (id < 0 || id >= channels_alloc) | 753 | c = channel_lookup(id); |
754 | if (c == NULL) | ||
596 | packet_disconnect("Received data for nonexistent channel %d.", id); | 755 | packet_disconnect("Received data for nonexistent channel %d.", id); |
597 | ch = &channels[id]; | ||
598 | |||
599 | if (ch->type == SSH_CHANNEL_FREE) | ||
600 | packet_disconnect("Received data for free channel %d.", ch->self); | ||
601 | 756 | ||
602 | /* Ignore any data for non-open channels (might happen on close) */ | 757 | /* Ignore any data for non-open channels (might happen on close) */ |
603 | if (ch->type != SSH_CHANNEL_OPEN && | 758 | if (c->type != SSH_CHANNEL_OPEN && |
604 | ch->type != SSH_CHANNEL_X11_OPEN) | 759 | c->type != SSH_CHANNEL_X11_OPEN) |
605 | return; | 760 | return; |
606 | 761 | ||
607 | /* same for protocol 1.5 if output end is no longer open */ | 762 | /* same for protocol 1.5 if output end is no longer open */ |
608 | if (!compat13 && ch->ostate != CHAN_OUTPUT_OPEN) | 763 | if (!compat13 && c->ostate != CHAN_OUTPUT_OPEN) |
609 | return; | 764 | return; |
610 | 765 | ||
611 | /* Get the data. */ | 766 | /* Get the data. */ |
612 | data = packet_get_string(&data_len); | 767 | data = packet_get_string(&data_len); |
613 | packet_integrity_check(payload_len, 4 + 4 + data_len, SSH_MSG_CHANNEL_DATA); | 768 | |
614 | buffer_append(&ch->output, data, data_len); | 769 | packet_integrity_check(plen, 4 + 4 + data_len, SSH_MSG_CHANNEL_DATA); |
770 | buffer_append(&c->output, data, data_len); | ||
615 | xfree(data); | 771 | xfree(data); |
616 | } | 772 | } |
617 | 773 | ||
@@ -624,45 +780,60 @@ int | |||
624 | channel_not_very_much_buffered_data() | 780 | channel_not_very_much_buffered_data() |
625 | { | 781 | { |
626 | unsigned int i; | 782 | unsigned int i; |
627 | Channel *ch; | 783 | Channel *c; |
628 | 784 | ||
629 | for (i = 0; i < channels_alloc; i++) { | 785 | for (i = 0; i < channels_alloc; i++) { |
630 | ch = &channels[i]; | 786 | c = &channels[i]; |
631 | if (ch->type == SSH_CHANNEL_OPEN) { | 787 | if (c->type == SSH_CHANNEL_OPEN) { |
632 | if (buffer_len(&ch->input) > packet_get_maxsize()) | 788 | if (buffer_len(&c->input) > packet_get_maxsize()) { |
789 | debug("channel %d: big input buffer %d", | ||
790 | c->self, buffer_len(&c->input)); | ||
633 | return 0; | 791 | return 0; |
634 | if (buffer_len(&ch->output) > packet_get_maxsize()) | 792 | } |
793 | if (buffer_len(&c->output) > packet_get_maxsize()) { | ||
794 | debug("channel %d: big output buffer %d", | ||
795 | c->self, buffer_len(&c->output)); | ||
635 | return 0; | 796 | return 0; |
797 | } | ||
636 | } | 798 | } |
637 | } | 799 | } |
638 | return 1; | 800 | return 1; |
639 | } | 801 | } |
640 | 802 | ||
641 | /* This is called after receiving CHANNEL_CLOSE/IEOF. */ | 803 | void |
804 | channel_input_ieof(int type, int plen) | ||
805 | { | ||
806 | int id; | ||
807 | Channel *c; | ||
808 | |||
809 | packet_integrity_check(plen, 4, type); | ||
810 | |||
811 | id = packet_get_int(); | ||
812 | c = channel_lookup(id); | ||
813 | if (c == NULL) | ||
814 | packet_disconnect("Received ieof for nonexistent channel %d.", id); | ||
815 | chan_rcvd_ieof(c); | ||
816 | } | ||
642 | 817 | ||
643 | void | 818 | void |
644 | channel_input_close() | 819 | channel_input_close(int type, int plen) |
645 | { | 820 | { |
646 | int channel; | 821 | int id; |
822 | Channel *c; | ||
647 | 823 | ||
648 | /* Get the channel number and verify it. */ | 824 | packet_integrity_check(plen, 4, type); |
649 | channel = packet_get_int(); | 825 | |
650 | if (channel < 0 || channel >= channels_alloc || | 826 | id = packet_get_int(); |
651 | channels[channel].type == SSH_CHANNEL_FREE) | 827 | c = channel_lookup(id); |
652 | packet_disconnect("Received data for nonexistent channel %d.", channel); | 828 | if (c == NULL) |
653 | 829 | packet_disconnect("Received close for nonexistent channel %d.", id); | |
654 | if (!compat13) { | ||
655 | /* proto version 1.5 overloads CLOSE with IEOF */ | ||
656 | chan_rcvd_ieof(&channels[channel]); | ||
657 | return; | ||
658 | } | ||
659 | 830 | ||
660 | /* | 831 | /* |
661 | * Send a confirmation that we have closed the channel and no more | 832 | * Send a confirmation that we have closed the channel and no more |
662 | * data is coming for it. | 833 | * data is coming for it. |
663 | */ | 834 | */ |
664 | packet_start(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION); | 835 | packet_start(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION); |
665 | packet_put_int(channels[channel].remote_id); | 836 | packet_put_int(c->remote_id); |
666 | packet_send(); | 837 | packet_send(); |
667 | 838 | ||
668 | /* | 839 | /* |
@@ -672,81 +843,80 @@ channel_input_close() | |||
672 | * no-one to receive the confirmation. The channel gets freed when | 843 | * no-one to receive the confirmation. The channel gets freed when |
673 | * the confirmation arrives. | 844 | * the confirmation arrives. |
674 | */ | 845 | */ |
675 | if (channels[channel].type != SSH_CHANNEL_CLOSED) { | 846 | if (c->type != SSH_CHANNEL_CLOSED) { |
676 | /* | 847 | /* |
677 | * Not a closed channel - mark it as draining, which will | 848 | * Not a closed channel - mark it as draining, which will |
678 | * cause it to be freed later. | 849 | * cause it to be freed later. |
679 | */ | 850 | */ |
680 | buffer_consume(&channels[channel].input, | 851 | buffer_consume(&c->input, buffer_len(&c->input)); |
681 | buffer_len(&channels[channel].input)); | 852 | c->type = SSH_CHANNEL_OUTPUT_DRAINING; |
682 | channels[channel].type = SSH_CHANNEL_OUTPUT_DRAINING; | ||
683 | } | 853 | } |
684 | } | 854 | } |
685 | 855 | ||
686 | /* This is called after receiving CHANNEL_CLOSE_CONFIRMATION/OCLOSE. */ | 856 | /* proto version 1.5 overloads CLOSE_CONFIRMATION with OCLOSE */ |
687 | |||
688 | void | 857 | void |
689 | channel_input_close_confirmation() | 858 | channel_input_oclose(int type, int plen) |
690 | { | 859 | { |
691 | int channel; | 860 | int id = packet_get_int(); |
692 | 861 | Channel *c = channel_lookup(id); | |
693 | /* Get the channel number and verify it. */ | 862 | packet_integrity_check(plen, 4, type); |
694 | channel = packet_get_int(); | 863 | if (c == NULL) |
695 | if (channel < 0 || channel >= channels_alloc) | 864 | packet_disconnect("Received oclose for nonexistent channel %d.", id); |
696 | packet_disconnect("Received close confirmation for out-of-range channel %d.", | 865 | chan_rcvd_oclose(c); |
697 | channel); | ||
698 | |||
699 | if (!compat13) { | ||
700 | /* proto version 1.5 overloads CLOSE_CONFIRMATION with OCLOSE */ | ||
701 | chan_rcvd_oclose(&channels[channel]); | ||
702 | return; | ||
703 | } | ||
704 | if (channels[channel].type != SSH_CHANNEL_CLOSED) | ||
705 | packet_disconnect("Received close confirmation for non-closed channel %d (type %d).", | ||
706 | channel, channels[channel].type); | ||
707 | |||
708 | /* Free the channel. */ | ||
709 | channel_free(channel); | ||
710 | } | 866 | } |
711 | 867 | ||
712 | /* This is called after receiving CHANNEL_OPEN_CONFIRMATION. */ | 868 | void |
869 | channel_input_close_confirmation(int type, int plen) | ||
870 | { | ||
871 | int id = packet_get_int(); | ||
872 | Channel *c = channel_lookup(id); | ||
873 | |||
874 | if (c == NULL) | ||
875 | packet_disconnect("Received close confirmation for " | ||
876 | "out-of-range channel %d.", id); | ||
877 | if (c->type != SSH_CHANNEL_CLOSED) | ||
878 | packet_disconnect("Received close confirmation for " | ||
879 | "non-closed channel %d (type %d).", id, c->type); | ||
880 | channel_free(c->self); | ||
881 | } | ||
713 | 882 | ||
714 | void | 883 | void |
715 | channel_input_open_confirmation() | 884 | channel_input_open_confirmation(int type, int plen) |
716 | { | 885 | { |
717 | int channel, remote_channel; | 886 | int id, remote_id; |
887 | Channel *c; | ||
718 | 888 | ||
719 | /* Get the channel number and verify it. */ | 889 | packet_integrity_check(plen, 4 + 4, type); |
720 | channel = packet_get_int(); | ||
721 | if (channel < 0 || channel >= channels_alloc || | ||
722 | channels[channel].type != SSH_CHANNEL_OPENING) | ||
723 | packet_disconnect("Received open confirmation for non-opening channel %d.", | ||
724 | channel); | ||
725 | 890 | ||
726 | /* Get remote side's id for this channel. */ | 891 | id = packet_get_int(); |
727 | remote_channel = packet_get_int(); | 892 | c = channel_lookup(id); |
728 | 893 | ||
894 | if (c==NULL || c->type != SSH_CHANNEL_OPENING) | ||
895 | packet_disconnect("Received open confirmation for " | ||
896 | "non-opening channel %d.", id); | ||
897 | remote_id = packet_get_int(); | ||
729 | /* Record the remote channel number and mark that the channel is now open. */ | 898 | /* Record the remote channel number and mark that the channel is now open. */ |
730 | channels[channel].remote_id = remote_channel; | 899 | c->remote_id = remote_id; |
731 | channels[channel].type = SSH_CHANNEL_OPEN; | 900 | c->type = SSH_CHANNEL_OPEN; |
732 | } | 901 | } |
733 | 902 | ||
734 | /* This is called after receiving CHANNEL_OPEN_FAILURE from the other side. */ | ||
735 | |||
736 | void | 903 | void |
737 | channel_input_open_failure() | 904 | channel_input_open_failure(int type, int plen) |
738 | { | 905 | { |
739 | int channel; | 906 | int id; |
907 | Channel *c; | ||
740 | 908 | ||
741 | /* Get the channel number and verify it. */ | 909 | packet_integrity_check(plen, 4, type); |
742 | channel = packet_get_int(); | 910 | |
743 | if (channel < 0 || channel >= channels_alloc || | 911 | id = packet_get_int(); |
744 | channels[channel].type != SSH_CHANNEL_OPENING) | 912 | c = channel_lookup(id); |
745 | packet_disconnect("Received open failure for non-opening channel %d.", | 913 | |
746 | channel); | 914 | if (c==NULL || c->type != SSH_CHANNEL_OPENING) |
915 | packet_disconnect("Received open failure for " | ||
916 | "non-opening channel %d.", id); | ||
747 | 917 | ||
748 | /* Free the channel. This will also close the socket. */ | 918 | /* Free the channel. This will also close the socket. */ |
749 | channel_free(channel); | 919 | channel_free(id); |
750 | } | 920 | } |
751 | 921 | ||
752 | /* | 922 | /* |
@@ -859,15 +1029,16 @@ channel_open_message() | |||
859 | case SSH_CHANNEL_X11_OPEN: | 1029 | case SSH_CHANNEL_X11_OPEN: |
860 | case SSH_CHANNEL_INPUT_DRAINING: | 1030 | case SSH_CHANNEL_INPUT_DRAINING: |
861 | case SSH_CHANNEL_OUTPUT_DRAINING: | 1031 | case SSH_CHANNEL_OUTPUT_DRAINING: |
862 | snprintf(buf, sizeof buf, " #%d %.300s (t%d r%d i%d/%d o%d/%d)\r\n", | 1032 | snprintf(buf, sizeof buf, " #%d %.300s (t%d r%d i%d/%d o%d/%d fd %d/%d)\r\n", |
863 | c->self, c->remote_name, | 1033 | c->self, c->remote_name, |
864 | c->type, c->remote_id, | 1034 | c->type, c->remote_id, |
865 | c->istate, buffer_len(&c->input), | 1035 | c->istate, buffer_len(&c->input), |
866 | c->ostate, buffer_len(&c->output)); | 1036 | c->ostate, buffer_len(&c->output), |
1037 | c->rfd, c->wfd); | ||
867 | buffer_append(&buffer, buf, strlen(buf)); | 1038 | buffer_append(&buffer, buf, strlen(buf)); |
868 | continue; | 1039 | continue; |
869 | default: | 1040 | default: |
870 | fatal("channel_still_open: bad channel type %d", c->type); | 1041 | fatal("channel_open_message: bad channel type %d", c->type); |
871 | /* NOTREACHED */ | 1042 | /* NOTREACHED */ |
872 | } | 1043 | } |
873 | } | 1044 | } |
@@ -950,8 +1121,11 @@ channel_request_local_forwarding(u_short port, const char *host, | |||
950 | continue; | 1121 | continue; |
951 | } | 1122 | } |
952 | /* Allocate a channel number for the socket. */ | 1123 | /* Allocate a channel number for the socket. */ |
953 | ch = channel_allocate(SSH_CHANNEL_PORT_LISTENER, sock, | 1124 | ch = channel_new( |
954 | xstrdup("port listener")); | 1125 | "port listener", SSH_CHANNEL_PORT_LISTENER, |
1126 | sock, sock, -1, | ||
1127 | CHAN_WINDOW_DEFAULT, CHAN_PACKET_DEFAULT, | ||
1128 | 0, xstrdup("port listener")); | ||
955 | strlcpy(channels[ch].path, host, sizeof(channels[ch].path)); | 1129 | strlcpy(channels[ch].path, host, sizeof(channels[ch].path)); |
956 | channels[ch].host_port = host_port; | 1130 | channels[ch].host_port = host_port; |
957 | channels[ch].listening_port = port; | 1131 | channels[ch].listening_port = port; |
@@ -968,26 +1142,26 @@ channel_request_local_forwarding(u_short port, const char *host, | |||
968 | */ | 1142 | */ |
969 | 1143 | ||
970 | void | 1144 | void |
971 | channel_request_remote_forwarding(u_short port, const char *host, | 1145 | channel_request_remote_forwarding(u_short listen_port, const char *host_to_connect, |
972 | u_short remote_port) | 1146 | u_short port_to_connect) |
973 | { | 1147 | { |
974 | int payload_len; | 1148 | int payload_len; |
975 | /* Record locally that connection to this host/port is permitted. */ | 1149 | /* Record locally that connection to this host/port is permitted. */ |
976 | if (num_permitted_opens >= SSH_MAX_FORWARDS_PER_DIRECTION) | 1150 | if (num_permitted_opens >= SSH_MAX_FORWARDS_PER_DIRECTION) |
977 | fatal("channel_request_remote_forwarding: too many forwards"); | 1151 | fatal("channel_request_remote_forwarding: too many forwards"); |
978 | 1152 | ||
979 | permitted_opens[num_permitted_opens].host = xstrdup(host); | 1153 | permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host_to_connect); |
980 | permitted_opens[num_permitted_opens].port = remote_port; | 1154 | permitted_opens[num_permitted_opens].port_to_connect = port_to_connect; |
1155 | permitted_opens[num_permitted_opens].listen_port = listen_port; | ||
981 | num_permitted_opens++; | 1156 | num_permitted_opens++; |
982 | 1157 | ||
983 | /* Send the forward request to the remote side. */ | 1158 | /* Send the forward request to the remote side. */ |
984 | packet_start(SSH_CMSG_PORT_FORWARD_REQUEST); | 1159 | packet_start(SSH_CMSG_PORT_FORWARD_REQUEST); |
985 | packet_put_int(port); | 1160 | packet_put_int(port_to_connect); |
986 | packet_put_string(host, strlen(host)); | 1161 | packet_put_string(host_to_connect, strlen(host_to_connect)); |
987 | packet_put_int(remote_port); | 1162 | packet_put_int(listen_port); |
988 | packet_send(); | 1163 | packet_send(); |
989 | packet_write_wait(); | 1164 | packet_write_wait(); |
990 | |||
991 | /* | 1165 | /* |
992 | * Wait for response from the remote side. It will send a disconnect | 1166 | * Wait for response from the remote side. It will send a disconnect |
993 | * message on failure, and we will never see it here. | 1167 | * message on failure, and we will never see it here. |
@@ -1029,63 +1203,14 @@ channel_input_port_forward_request(int is_root) | |||
1029 | xfree(hostname); | 1203 | xfree(hostname); |
1030 | } | 1204 | } |
1031 | 1205 | ||
1032 | /* | 1206 | /* XXX move to aux.c */ |
1033 | * This is called after receiving PORT_OPEN message. This attempts to | 1207 | int |
1034 | * connect to the given host:port, and sends back CHANNEL_OPEN_CONFIRMATION | 1208 | channel_connect_to(const char *host, u_short host_port) |
1035 | * or CHANNEL_OPEN_FAILURE. | ||
1036 | */ | ||
1037 | |||
1038 | void | ||
1039 | channel_input_port_open(int payload_len) | ||
1040 | { | 1209 | { |
1041 | int remote_channel, sock = 0, newch, i; | ||
1042 | u_short host_port; | ||
1043 | char *host, *originator_string; | ||
1044 | unsigned int host_len, originator_len; | ||
1045 | struct addrinfo hints, *ai, *aitop; | 1210 | struct addrinfo hints, *ai, *aitop; |
1046 | char ntop[NI_MAXHOST], strport[NI_MAXSERV]; | 1211 | char ntop[NI_MAXHOST], strport[NI_MAXSERV]; |
1047 | int gaierr; | 1212 | int gaierr; |
1048 | 1213 | int sock = -1; | |
1049 | /* Get remote channel number. */ | ||
1050 | remote_channel = packet_get_int(); | ||
1051 | |||
1052 | /* Get host name to connect to. */ | ||
1053 | host = packet_get_string(&host_len); | ||
1054 | |||
1055 | /* Get port to connect to. */ | ||
1056 | host_port = packet_get_int(); | ||
1057 | |||
1058 | /* Get remote originator name. */ | ||
1059 | if (have_hostname_in_open) { | ||
1060 | originator_string = packet_get_string(&originator_len); | ||
1061 | originator_len += 4; /* size of packet_int */ | ||
1062 | } else { | ||
1063 | originator_string = xstrdup("unknown (remote did not supply name)"); | ||
1064 | originator_len = 0; /* no originator supplied */ | ||
1065 | } | ||
1066 | |||
1067 | packet_integrity_check(payload_len, | ||
1068 | 4 + 4 + host_len + 4 + originator_len, | ||
1069 | SSH_MSG_PORT_OPEN); | ||
1070 | |||
1071 | /* Check if opening that port is permitted. */ | ||
1072 | if (!all_opens_permitted) { | ||
1073 | /* Go trough all permitted ports. */ | ||
1074 | for (i = 0; i < num_permitted_opens; i++) | ||
1075 | if (permitted_opens[i].port == host_port && | ||
1076 | strcmp(permitted_opens[i].host, host) == 0) | ||
1077 | break; | ||
1078 | |||
1079 | /* Check if we found the requested port among those permitted. */ | ||
1080 | if (i >= num_permitted_opens) { | ||
1081 | /* The port is not permitted. */ | ||
1082 | log("Received request to connect to %.100s:%d, but the request was denied.", | ||
1083 | host, host_port); | ||
1084 | packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); | ||
1085 | packet_put_int(remote_channel); | ||
1086 | packet_send(); | ||
1087 | } | ||
1088 | } | ||
1089 | 1214 | ||
1090 | memset(&hints, 0, sizeof(hints)); | 1215 | memset(&hints, 0, sizeof(hints)); |
1091 | hints.ai_family = IPv4or6; | 1216 | hints.ai_family = IPv4or6; |
@@ -1093,15 +1218,14 @@ channel_input_port_open(int payload_len) | |||
1093 | snprintf(strport, sizeof strport, "%d", host_port); | 1218 | snprintf(strport, sizeof strport, "%d", host_port); |
1094 | if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) { | 1219 | if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) { |
1095 | error("%.100s: unknown host (%s)", host, gai_strerror(gaierr)); | 1220 | error("%.100s: unknown host (%s)", host, gai_strerror(gaierr)); |
1096 | goto fail; | 1221 | return -1; |
1097 | } | 1222 | } |
1098 | |||
1099 | for (ai = aitop; ai; ai = ai->ai_next) { | 1223 | for (ai = aitop; ai; ai = ai->ai_next) { |
1100 | if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) | 1224 | if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) |
1101 | continue; | 1225 | continue; |
1102 | if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), | 1226 | if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), |
1103 | strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { | 1227 | strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { |
1104 | error("channel_input_port_open: getnameinfo failed"); | 1228 | error("channel_connect_to: getnameinfo failed"); |
1105 | continue; | 1229 | continue; |
1106 | } | 1230 | } |
1107 | /* Create the socket. */ | 1231 | /* Create the socket. */ |
@@ -1121,37 +1245,82 @@ channel_input_port_open(int payload_len) | |||
1121 | 1245 | ||
1122 | } | 1246 | } |
1123 | freeaddrinfo(aitop); | 1247 | freeaddrinfo(aitop); |
1124 | |||
1125 | if (!ai) { | 1248 | if (!ai) { |
1126 | error("connect %.100s port %d: failed.", host, host_port); | 1249 | error("connect %.100s port %d: failed.", host, host_port); |
1127 | goto fail; | 1250 | return -1; |
1128 | } | 1251 | } |
1252 | /* success */ | ||
1253 | return sock; | ||
1254 | } | ||
1129 | 1255 | ||
1130 | /* Successful connection. */ | 1256 | /* |
1257 | * This is called after receiving PORT_OPEN message. This attempts to | ||
1258 | * connect to the given host:port, and sends back CHANNEL_OPEN_CONFIRMATION | ||
1259 | * or CHANNEL_OPEN_FAILURE. | ||
1260 | */ | ||
1131 | 1261 | ||
1132 | /* Allocate a channel for this connection. */ | 1262 | void |
1133 | newch = channel_allocate(SSH_CHANNEL_OPEN, sock, originator_string); | 1263 | channel_input_port_open(int type, int plen) |
1134 | channels[newch].remote_id = remote_channel; | 1264 | { |
1265 | u_short host_port; | ||
1266 | char *host, *originator_string; | ||
1267 | int remote_channel, sock = -1, newch, i, denied; | ||
1268 | unsigned int host_len, originator_len; | ||
1135 | 1269 | ||
1136 | /* Send a confirmation to the remote host. */ | 1270 | /* Get remote channel number. */ |
1137 | packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION); | 1271 | remote_channel = packet_get_int(); |
1138 | packet_put_int(remote_channel); | ||
1139 | packet_put_int(newch); | ||
1140 | packet_send(); | ||
1141 | 1272 | ||
1142 | /* Free the argument string. */ | 1273 | /* Get host name to connect to. */ |
1143 | xfree(host); | 1274 | host = packet_get_string(&host_len); |
1144 | 1275 | ||
1145 | return; | 1276 | /* Get port to connect to. */ |
1277 | host_port = packet_get_int(); | ||
1146 | 1278 | ||
1147 | fail: | 1279 | /* Get remote originator name. */ |
1148 | /* Free the argument string. */ | 1280 | if (have_hostname_in_open) { |
1149 | xfree(host); | 1281 | originator_string = packet_get_string(&originator_len); |
1282 | originator_len += 4; /* size of packet_int */ | ||
1283 | } else { | ||
1284 | originator_string = xstrdup("unknown (remote did not supply name)"); | ||
1285 | originator_len = 0; /* no originator supplied */ | ||
1286 | } | ||
1150 | 1287 | ||
1151 | /* Send refusal to the remote host. */ | 1288 | packet_integrity_check(plen, |
1152 | packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); | 1289 | 4 + 4 + host_len + 4 + originator_len, SSH_MSG_PORT_OPEN); |
1153 | packet_put_int(remote_channel); | 1290 | |
1154 | packet_send(); | 1291 | /* Check if opening that port is permitted. */ |
1292 | denied = 0; | ||
1293 | if (!all_opens_permitted) { | ||
1294 | /* Go trough all permitted ports. */ | ||
1295 | for (i = 0; i < num_permitted_opens; i++) | ||
1296 | if (permitted_opens[i].port_to_connect == host_port && | ||
1297 | strcmp(permitted_opens[i].host_to_connect, host) == 0) | ||
1298 | break; | ||
1299 | |||
1300 | /* Check if we found the requested port among those permitted. */ | ||
1301 | if (i >= num_permitted_opens) { | ||
1302 | /* The port is not permitted. */ | ||
1303 | log("Received request to connect to %.100s:%d, but the request was denied.", | ||
1304 | host, host_port); | ||
1305 | denied = 1; | ||
1306 | } | ||
1307 | } | ||
1308 | sock = denied ? -1 : channel_connect_to(host, host_port); | ||
1309 | if (sock > 0) { | ||
1310 | /* Allocate a channel for this connection. */ | ||
1311 | newch = channel_allocate(SSH_CHANNEL_OPEN, sock, originator_string); | ||
1312 | channels[newch].remote_id = remote_channel; | ||
1313 | |||
1314 | packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION); | ||
1315 | packet_put_int(remote_channel); | ||
1316 | packet_put_int(newch); | ||
1317 | packet_send(); | ||
1318 | } else { | ||
1319 | packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); | ||
1320 | packet_put_int(remote_channel); | ||
1321 | packet_send(); | ||
1322 | } | ||
1323 | xfree(host); | ||
1155 | } | 1324 | } |
1156 | 1325 | ||
1157 | /* | 1326 | /* |
@@ -1336,7 +1505,7 @@ connect_local_xsocket(unsigned int dnr) | |||
1336 | */ | 1505 | */ |
1337 | 1506 | ||
1338 | void | 1507 | void |
1339 | x11_input_open(int payload_len) | 1508 | x11_input_open(int type, int plen) |
1340 | { | 1509 | { |
1341 | int remote_channel, display_number, sock = 0, newch; | 1510 | int remote_channel, display_number, sock = 0, newch; |
1342 | const char *display; | 1511 | const char *display; |
@@ -1359,7 +1528,7 @@ x11_input_open(int payload_len) | |||
1359 | } | 1528 | } |
1360 | 1529 | ||
1361 | debug("Received X11 open request."); | 1530 | debug("Received X11 open request."); |
1362 | packet_integrity_check(payload_len, 4 + remote_len, SSH_SMSG_X11_OPEN); | 1531 | packet_integrity_check(plen, 4 + remote_len, SSH_SMSG_X11_OPEN); |
1363 | 1532 | ||
1364 | /* Try to open a socket for the local X server. */ | 1533 | /* Try to open a socket for the local X server. */ |
1365 | display = getenv("DISPLAY"); | 1534 | display = getenv("DISPLAY"); |
@@ -1425,19 +1594,18 @@ x11_input_open(int payload_len) | |||
1425 | sock = socket(ai->ai_family, SOCK_STREAM, 0); | 1594 | sock = socket(ai->ai_family, SOCK_STREAM, 0); |
1426 | if (sock < 0) { | 1595 | if (sock < 0) { |
1427 | debug("socket: %.100s", strerror(errno)); | 1596 | debug("socket: %.100s", strerror(errno)); |
1428 | continue; | 1597 | continue; |
1429 | } | 1598 | } |
1430 | /* Connect it to the display. */ | 1599 | /* Connect it to the display. */ |
1431 | if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0) { | 1600 | if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0) { |
1432 | debug("connect %.100s port %d: %.100s", buf, 6000 + display_number, | 1601 | debug("connect %.100s port %d: %.100s", buf, |
1433 | strerror(errno)); | 1602 | 6000 + display_number, strerror(errno)); |
1434 | close(sock); | 1603 | close(sock); |
1435 | continue; | 1604 | continue; |
1605 | } | ||
1606 | /* Success */ | ||
1607 | break; | ||
1436 | } | 1608 | } |
1437 | /* Success */ | ||
1438 | break; | ||
1439 | |||
1440 | } /* (ai = aitop, ai; ai = ai->ai_next) */ | ||
1441 | freeaddrinfo(aitop); | 1609 | freeaddrinfo(aitop); |
1442 | if (!ai) { | 1610 | if (!ai) { |
1443 | error("connect %.100s port %d: %.100s", buf, 6000 + display_number, | 1611 | error("connect %.100s port %d: %.100s", buf, 6000 + display_number, |
@@ -1625,11 +1793,13 @@ auth_input_request_forwarding(struct passwd * pw) | |||
1625 | /* This is called to process an SSH_SMSG_AGENT_OPEN message. */ | 1793 | /* This is called to process an SSH_SMSG_AGENT_OPEN message. */ |
1626 | 1794 | ||
1627 | void | 1795 | void |
1628 | auth_input_open_request() | 1796 | auth_input_open_request(int type, int plen) |
1629 | { | 1797 | { |
1630 | int remch, sock, newch; | 1798 | int remch, sock, newch; |
1631 | char *dummyname; | 1799 | char *dummyname; |
1632 | 1800 | ||
1801 | packet_integrity_check(plen, 4, type); | ||
1802 | |||
1633 | /* Read the remote channel number from the message. */ | 1803 | /* Read the remote channel number from the message. */ |
1634 | remch = packet_get_int(); | 1804 | remch = packet_get_int(); |
1635 | 1805 | ||