diff options
Diffstat (limited to 'channels.c')
-rw-r--r-- | channels.c | 198 |
1 files changed, 159 insertions, 39 deletions
diff --git a/channels.c b/channels.c index e663c2159..1f6984aa7 100644 --- a/channels.c +++ b/channels.c | |||
@@ -39,7 +39,7 @@ | |||
39 | */ | 39 | */ |
40 | 40 | ||
41 | #include "includes.h" | 41 | #include "includes.h" |
42 | RCSID("$OpenBSD: channels.c,v 1.200 2004/01/19 09:24:21 markus Exp $"); | 42 | RCSID("$OpenBSD: channels.c,v 1.209 2004/08/11 21:43:04 avsm Exp $"); |
43 | 43 | ||
44 | #include "ssh.h" | 44 | #include "ssh.h" |
45 | #include "ssh1.h" | 45 | #include "ssh1.h" |
@@ -68,7 +68,7 @@ static Channel **channels = NULL; | |||
68 | * Size of the channel array. All slots of the array must always be | 68 | * Size of the channel array. All slots of the array must always be |
69 | * initialized (at least the type field); unused slots set to NULL | 69 | * initialized (at least the type field); unused slots set to NULL |
70 | */ | 70 | */ |
71 | static int channels_alloc = 0; | 71 | static u_int channels_alloc = 0; |
72 | 72 | ||
73 | /* | 73 | /* |
74 | * Maximum file descriptor value used in any of the channels. This is | 74 | * Maximum file descriptor value used in any of the channels. This is |
@@ -141,7 +141,7 @@ channel_lookup(int id) | |||
141 | { | 141 | { |
142 | Channel *c; | 142 | Channel *c; |
143 | 143 | ||
144 | if (id < 0 || id >= channels_alloc) { | 144 | if (id < 0 || (u_int)id >= channels_alloc) { |
145 | logit("channel_lookup: %d: bad id", id); | 145 | logit("channel_lookup: %d: bad id", id); |
146 | return NULL; | 146 | return NULL; |
147 | } | 147 | } |
@@ -172,6 +172,7 @@ channel_register_fds(Channel *c, int rfd, int wfd, int efd, | |||
172 | c->rfd = rfd; | 172 | c->rfd = rfd; |
173 | c->wfd = wfd; | 173 | c->wfd = wfd; |
174 | c->sock = (rfd == wfd) ? rfd : -1; | 174 | c->sock = (rfd == wfd) ? rfd : -1; |
175 | c->ctl_fd = -1; /* XXX: set elsewhere */ | ||
175 | c->efd = efd; | 176 | c->efd = efd; |
176 | c->extended_usage = extusage; | 177 | c->extended_usage = extusage; |
177 | 178 | ||
@@ -208,7 +209,8 @@ Channel * | |||
208 | channel_new(char *ctype, int type, int rfd, int wfd, int efd, | 209 | channel_new(char *ctype, int type, int rfd, int wfd, int efd, |
209 | u_int window, u_int maxpack, int extusage, char *remote_name, int nonblock) | 210 | u_int window, u_int maxpack, int extusage, char *remote_name, int nonblock) |
210 | { | 211 | { |
211 | int i, found; | 212 | int found; |
213 | u_int i; | ||
212 | Channel *c; | 214 | Channel *c; |
213 | 215 | ||
214 | /* Do initial allocation if this is the first call. */ | 216 | /* Do initial allocation if this is the first call. */ |
@@ -222,10 +224,10 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd, | |||
222 | for (found = -1, i = 0; i < channels_alloc; i++) | 224 | for (found = -1, i = 0; i < channels_alloc; i++) |
223 | if (channels[i] == NULL) { | 225 | if (channels[i] == NULL) { |
224 | /* Found a free slot. */ | 226 | /* Found a free slot. */ |
225 | found = i; | 227 | found = (int)i; |
226 | break; | 228 | break; |
227 | } | 229 | } |
228 | if (found == -1) { | 230 | if (found < 0) { |
229 | /* There are no free slots. Take last+1 slot and expand the array. */ | 231 | /* There are no free slots. Take last+1 slot and expand the array. */ |
230 | found = channels_alloc; | 232 | found = channels_alloc; |
231 | if (channels_alloc > 10000) | 233 | if (channels_alloc > 10000) |
@@ -263,6 +265,7 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd, | |||
263 | c->single_connection = 0; | 265 | c->single_connection = 0; |
264 | c->detach_user = NULL; | 266 | c->detach_user = NULL; |
265 | c->confirm = NULL; | 267 | c->confirm = NULL; |
268 | c->confirm_ctx = NULL; | ||
266 | c->input_filter = NULL; | 269 | c->input_filter = NULL; |
267 | debug("channel %d: new [%s]", found, remote_name); | 270 | debug("channel %d: new [%s]", found, remote_name); |
268 | return c; | 271 | return c; |
@@ -271,7 +274,8 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd, | |||
271 | static int | 274 | static int |
272 | channel_find_maxfd(void) | 275 | channel_find_maxfd(void) |
273 | { | 276 | { |
274 | int i, max = 0; | 277 | u_int i; |
278 | int max = 0; | ||
275 | Channel *c; | 279 | Channel *c; |
276 | 280 | ||
277 | for (i = 0; i < channels_alloc; i++) { | 281 | for (i = 0; i < channels_alloc; i++) { |
@@ -304,10 +308,11 @@ channel_close_fd(int *fdp) | |||
304 | static void | 308 | static void |
305 | channel_close_fds(Channel *c) | 309 | channel_close_fds(Channel *c) |
306 | { | 310 | { |
307 | debug3("channel %d: close_fds r %d w %d e %d", | 311 | debug3("channel %d: close_fds r %d w %d e %d c %d", |
308 | c->self, c->rfd, c->wfd, c->efd); | 312 | c->self, c->rfd, c->wfd, c->efd, c->ctl_fd); |
309 | 313 | ||
310 | channel_close_fd(&c->sock); | 314 | channel_close_fd(&c->sock); |
315 | channel_close_fd(&c->ctl_fd); | ||
311 | channel_close_fd(&c->rfd); | 316 | channel_close_fd(&c->rfd); |
312 | channel_close_fd(&c->wfd); | 317 | channel_close_fd(&c->wfd); |
313 | channel_close_fd(&c->efd); | 318 | channel_close_fd(&c->efd); |
@@ -319,12 +324,12 @@ void | |||
319 | channel_free(Channel *c) | 324 | channel_free(Channel *c) |
320 | { | 325 | { |
321 | char *s; | 326 | char *s; |
322 | int i, n; | 327 | u_int i, n; |
323 | 328 | ||
324 | for (n = 0, i = 0; i < channels_alloc; i++) | 329 | for (n = 0, i = 0; i < channels_alloc; i++) |
325 | if (channels[i]) | 330 | if (channels[i]) |
326 | n++; | 331 | n++; |
327 | debug("channel %d: free: %s, nchannels %d", c->self, | 332 | debug("channel %d: free: %s, nchannels %u", c->self, |
328 | c->remote_name ? c->remote_name : "???", n); | 333 | c->remote_name ? c->remote_name : "???", n); |
329 | 334 | ||
330 | s = channel_open_message(); | 335 | s = channel_open_message(); |
@@ -333,6 +338,8 @@ channel_free(Channel *c) | |||
333 | 338 | ||
334 | if (c->sock != -1) | 339 | if (c->sock != -1) |
335 | shutdown(c->sock, SHUT_RDWR); | 340 | shutdown(c->sock, SHUT_RDWR); |
341 | if (c->ctl_fd != -1) | ||
342 | shutdown(c->ctl_fd, SHUT_RDWR); | ||
336 | channel_close_fds(c); | 343 | channel_close_fds(c); |
337 | buffer_free(&c->input); | 344 | buffer_free(&c->input); |
338 | buffer_free(&c->output); | 345 | buffer_free(&c->output); |
@@ -348,7 +355,7 @@ channel_free(Channel *c) | |||
348 | void | 355 | void |
349 | channel_free_all(void) | 356 | channel_free_all(void) |
350 | { | 357 | { |
351 | int i; | 358 | u_int i; |
352 | 359 | ||
353 | for (i = 0; i < channels_alloc; i++) | 360 | for (i = 0; i < channels_alloc; i++) |
354 | if (channels[i] != NULL) | 361 | if (channels[i] != NULL) |
@@ -363,7 +370,7 @@ channel_free_all(void) | |||
363 | void | 370 | void |
364 | channel_close_all(void) | 371 | channel_close_all(void) |
365 | { | 372 | { |
366 | int i; | 373 | u_int i; |
367 | 374 | ||
368 | for (i = 0; i < channels_alloc; i++) | 375 | for (i = 0; i < channels_alloc; i++) |
369 | if (channels[i] != NULL) | 376 | if (channels[i] != NULL) |
@@ -377,7 +384,7 @@ channel_close_all(void) | |||
377 | void | 384 | void |
378 | channel_stop_listening(void) | 385 | channel_stop_listening(void) |
379 | { | 386 | { |
380 | int i; | 387 | u_int i; |
381 | Channel *c; | 388 | Channel *c; |
382 | 389 | ||
383 | for (i = 0; i < channels_alloc; i++) { | 390 | for (i = 0; i < channels_alloc; i++) { |
@@ -434,7 +441,7 @@ channel_not_very_much_buffered_data(void) | |||
434 | int | 441 | int |
435 | channel_still_open(void) | 442 | channel_still_open(void) |
436 | { | 443 | { |
437 | int i; | 444 | u_int i; |
438 | Channel *c; | 445 | Channel *c; |
439 | 446 | ||
440 | for (i = 0; i < channels_alloc; i++) { | 447 | for (i = 0; i < channels_alloc; i++) { |
@@ -477,12 +484,12 @@ channel_still_open(void) | |||
477 | int | 484 | int |
478 | channel_find_open(void) | 485 | channel_find_open(void) |
479 | { | 486 | { |
480 | int i; | 487 | u_int i; |
481 | Channel *c; | 488 | Channel *c; |
482 | 489 | ||
483 | for (i = 0; i < channels_alloc; i++) { | 490 | for (i = 0; i < channels_alloc; i++) { |
484 | c = channels[i]; | 491 | c = channels[i]; |
485 | if (c == NULL) | 492 | if (c == NULL || c->remote_id < 0) |
486 | continue; | 493 | continue; |
487 | switch (c->type) { | 494 | switch (c->type) { |
488 | case SSH_CHANNEL_CLOSED: | 495 | case SSH_CHANNEL_CLOSED: |
@@ -525,7 +532,7 @@ channel_open_message(void) | |||
525 | Buffer buffer; | 532 | Buffer buffer; |
526 | Channel *c; | 533 | Channel *c; |
527 | char buf[1024], *cp; | 534 | char buf[1024], *cp; |
528 | int i; | 535 | u_int i; |
529 | 536 | ||
530 | buffer_init(&buffer); | 537 | buffer_init(&buffer); |
531 | snprintf(buf, sizeof buf, "The following connections are open:\r\n"); | 538 | snprintf(buf, sizeof buf, "The following connections are open:\r\n"); |
@@ -550,12 +557,13 @@ channel_open_message(void) | |||
550 | case SSH_CHANNEL_X11_OPEN: | 557 | case SSH_CHANNEL_X11_OPEN: |
551 | case SSH_CHANNEL_INPUT_DRAINING: | 558 | case SSH_CHANNEL_INPUT_DRAINING: |
552 | case SSH_CHANNEL_OUTPUT_DRAINING: | 559 | case SSH_CHANNEL_OUTPUT_DRAINING: |
553 | snprintf(buf, sizeof buf, " #%d %.300s (t%d r%d i%d/%d o%d/%d fd %d/%d)\r\n", | 560 | snprintf(buf, sizeof buf, |
561 | " #%d %.300s (t%d r%d i%d/%d o%d/%d fd %d/%d cfd %d)\r\n", | ||
554 | c->self, c->remote_name, | 562 | c->self, c->remote_name, |
555 | c->type, c->remote_id, | 563 | c->type, c->remote_id, |
556 | c->istate, buffer_len(&c->input), | 564 | c->istate, buffer_len(&c->input), |
557 | c->ostate, buffer_len(&c->output), | 565 | c->ostate, buffer_len(&c->output), |
558 | c->rfd, c->wfd); | 566 | c->rfd, c->wfd, c->ctl_fd); |
559 | buffer_append(&buffer, buf, strlen(buf)); | 567 | buffer_append(&buffer, buf, strlen(buf)); |
560 | continue; | 568 | continue; |
561 | default: | 569 | default: |
@@ -596,14 +604,14 @@ channel_request_start(int id, char *service, int wantconfirm) | |||
596 | logit("channel_request_start: %d: unknown channel id", id); | 604 | logit("channel_request_start: %d: unknown channel id", id); |
597 | return; | 605 | return; |
598 | } | 606 | } |
599 | debug2("channel %d: request %s", id, service) ; | 607 | debug2("channel %d: request %s confirm %d", id, service, wantconfirm); |
600 | packet_start(SSH2_MSG_CHANNEL_REQUEST); | 608 | packet_start(SSH2_MSG_CHANNEL_REQUEST); |
601 | packet_put_int(c->remote_id); | 609 | packet_put_int(c->remote_id); |
602 | packet_put_cstring(service); | 610 | packet_put_cstring(service); |
603 | packet_put_char(wantconfirm); | 611 | packet_put_char(wantconfirm); |
604 | } | 612 | } |
605 | void | 613 | void |
606 | channel_register_confirm(int id, channel_callback_fn *fn) | 614 | channel_register_confirm(int id, channel_callback_fn *fn, void *ctx) |
607 | { | 615 | { |
608 | Channel *c = channel_lookup(id); | 616 | Channel *c = channel_lookup(id); |
609 | 617 | ||
@@ -612,6 +620,7 @@ channel_register_confirm(int id, channel_callback_fn *fn) | |||
612 | return; | 620 | return; |
613 | } | 621 | } |
614 | c->confirm = fn; | 622 | c->confirm = fn; |
623 | c->confirm_ctx = ctx; | ||
615 | } | 624 | } |
616 | void | 625 | void |
617 | channel_register_cleanup(int id, channel_callback_fn *fn) | 626 | channel_register_cleanup(int id, channel_callback_fn *fn) |
@@ -729,6 +738,10 @@ channel_pre_open(Channel *c, fd_set * readset, fd_set * writeset) | |||
729 | buffer_len(&c->extended) < c->remote_window) | 738 | buffer_len(&c->extended) < c->remote_window) |
730 | FD_SET(c->efd, readset); | 739 | FD_SET(c->efd, readset); |
731 | } | 740 | } |
741 | /* XXX: What about efd? races? */ | ||
742 | if (compat20 && c->ctl_fd != -1 && | ||
743 | c->istate == CHAN_INPUT_OPEN && c->ostate == CHAN_OUTPUT_OPEN) | ||
744 | FD_SET(c->ctl_fd, readset); | ||
732 | } | 745 | } |
733 | 746 | ||
734 | static void | 747 | static void |
@@ -1031,7 +1044,7 @@ channel_decode_socks5(Channel *c, fd_set * readset, fd_set * writeset) | |||
1031 | buffer_get(&c->input, (char *)&dest_port, 2); | 1044 | buffer_get(&c->input, (char *)&dest_port, 2); |
1032 | dest_addr[addrlen] = '\0'; | 1045 | dest_addr[addrlen] = '\0'; |
1033 | if (s5_req.atyp == SSH_SOCKS5_DOMAIN) | 1046 | if (s5_req.atyp == SSH_SOCKS5_DOMAIN) |
1034 | strlcpy(c->path, dest_addr, sizeof(c->path)); | 1047 | strlcpy(c->path, (char *)dest_addr, sizeof(c->path)); |
1035 | else if (inet_ntop(af, dest_addr, c->path, sizeof(c->path)) == NULL) | 1048 | else if (inet_ntop(af, dest_addr, c->path, sizeof(c->path)) == NULL) |
1036 | return -1; | 1049 | return -1; |
1037 | c->host_port = ntohs(dest_port); | 1050 | c->host_port = ntohs(dest_port); |
@@ -1482,6 +1495,33 @@ channel_handle_efd(Channel *c, fd_set * readset, fd_set * writeset) | |||
1482 | return 1; | 1495 | return 1; |
1483 | } | 1496 | } |
1484 | static int | 1497 | static int |
1498 | channel_handle_ctl(Channel *c, fd_set * readset, fd_set * writeset) | ||
1499 | { | ||
1500 | char buf[16]; | ||
1501 | int len; | ||
1502 | |||
1503 | /* Monitor control fd to detect if the slave client exits */ | ||
1504 | if (c->ctl_fd != -1 && FD_ISSET(c->ctl_fd, readset)) { | ||
1505 | len = read(c->ctl_fd, buf, sizeof(buf)); | ||
1506 | if (len < 0 && (errno == EINTR || errno == EAGAIN)) | ||
1507 | return 1; | ||
1508 | if (len <= 0) { | ||
1509 | debug2("channel %d: ctl read<=0", c->self); | ||
1510 | if (c->type != SSH_CHANNEL_OPEN) { | ||
1511 | debug2("channel %d: not open", c->self); | ||
1512 | chan_mark_dead(c); | ||
1513 | return -1; | ||
1514 | } else { | ||
1515 | chan_read_failed(c); | ||
1516 | chan_write_failed(c); | ||
1517 | } | ||
1518 | return -1; | ||
1519 | } else | ||
1520 | fatal("%s: unexpected data on ctl fd", __func__); | ||
1521 | } | ||
1522 | return 1; | ||
1523 | } | ||
1524 | static int | ||
1485 | channel_check_window(Channel *c) | 1525 | channel_check_window(Channel *c) |
1486 | { | 1526 | { |
1487 | if (c->type == SSH_CHANNEL_OPEN && | 1527 | if (c->type == SSH_CHANNEL_OPEN && |
@@ -1511,6 +1551,7 @@ channel_post_open(Channel *c, fd_set * readset, fd_set * writeset) | |||
1511 | if (!compat20) | 1551 | if (!compat20) |
1512 | return; | 1552 | return; |
1513 | channel_handle_efd(c, readset, writeset); | 1553 | channel_handle_efd(c, readset, writeset); |
1554 | channel_handle_ctl(c, readset, writeset); | ||
1514 | channel_check_window(c); | 1555 | channel_check_window(c); |
1515 | } | 1556 | } |
1516 | 1557 | ||
@@ -1635,7 +1676,7 @@ static void | |||
1635 | channel_handler(chan_fn *ftab[], fd_set * readset, fd_set * writeset) | 1676 | channel_handler(chan_fn *ftab[], fd_set * readset, fd_set * writeset) |
1636 | { | 1677 | { |
1637 | static int did_init = 0; | 1678 | static int did_init = 0; |
1638 | int i; | 1679 | u_int i; |
1639 | Channel *c; | 1680 | Channel *c; |
1640 | 1681 | ||
1641 | if (!did_init) { | 1682 | if (!did_init) { |
@@ -1658,10 +1699,9 @@ channel_handler(chan_fn *ftab[], fd_set * readset, fd_set * writeset) | |||
1658 | */ | 1699 | */ |
1659 | void | 1700 | void |
1660 | channel_prepare_select(fd_set **readsetp, fd_set **writesetp, int *maxfdp, | 1701 | channel_prepare_select(fd_set **readsetp, fd_set **writesetp, int *maxfdp, |
1661 | int *nallocp, int rekeying) | 1702 | u_int *nallocp, int rekeying) |
1662 | { | 1703 | { |
1663 | int n; | 1704 | u_int n, sz; |
1664 | u_int sz; | ||
1665 | 1705 | ||
1666 | n = MAX(*maxfdp, channel_max_fd); | 1706 | n = MAX(*maxfdp, channel_max_fd); |
1667 | 1707 | ||
@@ -1697,8 +1737,7 @@ void | |||
1697 | channel_output_poll(void) | 1737 | channel_output_poll(void) |
1698 | { | 1738 | { |
1699 | Channel *c; | 1739 | Channel *c; |
1700 | int i; | 1740 | u_int i, len; |
1701 | u_int len; | ||
1702 | 1741 | ||
1703 | for (i = 0; i < channels_alloc; i++) { | 1742 | for (i = 0; i < channels_alloc; i++) { |
1704 | c = channels[i]; | 1743 | c = channels[i]; |
@@ -2011,7 +2050,7 @@ channel_input_open_confirmation(int type, u_int32_t seq, void *ctxt) | |||
2011 | c->remote_maxpacket = packet_get_int(); | 2050 | c->remote_maxpacket = packet_get_int(); |
2012 | if (c->confirm) { | 2051 | if (c->confirm) { |
2013 | debug2("callback start"); | 2052 | debug2("callback start"); |
2014 | c->confirm(c->self, NULL); | 2053 | c->confirm(c->self, c->confirm_ctx); |
2015 | debug2("callback done"); | 2054 | debug2("callback done"); |
2016 | } | 2055 | } |
2017 | debug2("channel %d: open confirm rwindow %u rmax %u", c->self, | 2056 | debug2("channel %d: open confirm rwindow %u rmax %u", c->self, |
@@ -2228,6 +2267,27 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por | |||
2228 | return success; | 2267 | return success; |
2229 | } | 2268 | } |
2230 | 2269 | ||
2270 | int | ||
2271 | channel_cancel_rport_listener(const char *host, u_short port) | ||
2272 | { | ||
2273 | u_int i; | ||
2274 | int found = 0; | ||
2275 | |||
2276 | for(i = 0; i < channels_alloc; i++) { | ||
2277 | Channel *c = channels[i]; | ||
2278 | |||
2279 | if (c != NULL && c->type == SSH_CHANNEL_RPORT_LISTENER && | ||
2280 | strncmp(c->path, host, sizeof(c->path)) == 0 && | ||
2281 | c->listening_port == port) { | ||
2282 | debug2("%s: close clannel %d", __func__, i); | ||
2283 | channel_free(c); | ||
2284 | found = 1; | ||
2285 | } | ||
2286 | } | ||
2287 | |||
2288 | return (found); | ||
2289 | } | ||
2290 | |||
2231 | /* protocol local port fwd, used by ssh (and sshd in v1) */ | 2291 | /* protocol local port fwd, used by ssh (and sshd in v1) */ |
2232 | int | 2292 | int |
2233 | channel_setup_local_fwd_listener(u_short listen_port, | 2293 | channel_setup_local_fwd_listener(u_short listen_port, |
@@ -2305,6 +2365,41 @@ channel_request_remote_forwarding(u_short listen_port, | |||
2305 | } | 2365 | } |
2306 | 2366 | ||
2307 | /* | 2367 | /* |
2368 | * Request cancellation of remote forwarding of connection host:port from | ||
2369 | * local side. | ||
2370 | */ | ||
2371 | void | ||
2372 | channel_request_rforward_cancel(u_short port) | ||
2373 | { | ||
2374 | int i; | ||
2375 | const char *address_to_bind = "0.0.0.0"; | ||
2376 | |||
2377 | if (!compat20) | ||
2378 | return; | ||
2379 | |||
2380 | for (i = 0; i < num_permitted_opens; i++) { | ||
2381 | if (permitted_opens[i].host_to_connect != NULL && | ||
2382 | permitted_opens[i].listen_port == port) | ||
2383 | break; | ||
2384 | } | ||
2385 | if (i >= num_permitted_opens) { | ||
2386 | debug("%s: requested forward not found", __func__); | ||
2387 | return; | ||
2388 | } | ||
2389 | packet_start(SSH2_MSG_GLOBAL_REQUEST); | ||
2390 | packet_put_cstring("cancel-tcpip-forward"); | ||
2391 | packet_put_char(0); | ||
2392 | packet_put_cstring(address_to_bind); | ||
2393 | packet_put_int(port); | ||
2394 | packet_send(); | ||
2395 | |||
2396 | permitted_opens[i].listen_port = 0; | ||
2397 | permitted_opens[i].port_to_connect = 0; | ||
2398 | free(permitted_opens[i].host_to_connect); | ||
2399 | permitted_opens[i].host_to_connect = NULL; | ||
2400 | } | ||
2401 | |||
2402 | /* | ||
2308 | * This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates | 2403 | * This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates |
2309 | * listening for the port, and sends back a success reply (or disconnect | 2404 | * listening for the port, and sends back a success reply (or disconnect |
2310 | * message if there was an error). This never returns if there was an error. | 2405 | * message if there was an error). This never returns if there was an error. |
@@ -2373,7 +2468,8 @@ channel_clear_permitted_opens(void) | |||
2373 | int i; | 2468 | int i; |
2374 | 2469 | ||
2375 | for (i = 0; i < num_permitted_opens; i++) | 2470 | for (i = 0; i < num_permitted_opens; i++) |
2376 | xfree(permitted_opens[i].host_to_connect); | 2471 | if (permitted_opens[i].host_to_connect != NULL) |
2472 | xfree(permitted_opens[i].host_to_connect); | ||
2377 | num_permitted_opens = 0; | 2473 | num_permitted_opens = 0; |
2378 | 2474 | ||
2379 | } | 2475 | } |
@@ -2413,8 +2509,8 @@ connect_to(const char *host, u_short port) | |||
2413 | verbose("socket: %.100s", strerror(errno)); | 2509 | verbose("socket: %.100s", strerror(errno)); |
2414 | continue; | 2510 | continue; |
2415 | } | 2511 | } |
2416 | if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) | 2512 | if (set_nonblock(sock) == -1) |
2417 | fatal("connect_to: F_SETFL: %s", strerror(errno)); | 2513 | fatal("%s: set_nonblock(%d)", __func__, sock); |
2418 | if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0 && | 2514 | if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0 && |
2419 | errno != EINPROGRESS) { | 2515 | errno != EINPROGRESS) { |
2420 | error("connect_to %.100s port %s: %.100s", ntop, strport, | 2516 | error("connect_to %.100s port %s: %.100s", ntop, strport, |
@@ -2441,7 +2537,8 @@ channel_connect_by_listen_address(u_short listen_port) | |||
2441 | int i; | 2537 | int i; |
2442 | 2538 | ||
2443 | for (i = 0; i < num_permitted_opens; i++) | 2539 | for (i = 0; i < num_permitted_opens; i++) |
2444 | if (permitted_opens[i].listen_port == listen_port) | 2540 | if (permitted_opens[i].host_to_connect != NULL && |
2541 | permitted_opens[i].listen_port == listen_port) | ||
2445 | return connect_to( | 2542 | return connect_to( |
2446 | permitted_opens[i].host_to_connect, | 2543 | permitted_opens[i].host_to_connect, |
2447 | permitted_opens[i].port_to_connect); | 2544 | permitted_opens[i].port_to_connect); |
@@ -2459,7 +2556,8 @@ channel_connect_to(const char *host, u_short port) | |||
2459 | permit = all_opens_permitted; | 2556 | permit = all_opens_permitted; |
2460 | if (!permit) { | 2557 | if (!permit) { |
2461 | for (i = 0; i < num_permitted_opens; i++) | 2558 | for (i = 0; i < num_permitted_opens; i++) |
2462 | if (permitted_opens[i].port_to_connect == port && | 2559 | if (permitted_opens[i].host_to_connect != NULL && |
2560 | permitted_opens[i].port_to_connect == port && | ||
2463 | strcmp(permitted_opens[i].host_to_connect, host) == 0) | 2561 | strcmp(permitted_opens[i].host_to_connect, host) == 0) |
2464 | permit = 1; | 2562 | permit = 1; |
2465 | 2563 | ||
@@ -2472,6 +2570,27 @@ channel_connect_to(const char *host, u_short port) | |||
2472 | return connect_to(host, port); | 2570 | return connect_to(host, port); |
2473 | } | 2571 | } |
2474 | 2572 | ||
2573 | void | ||
2574 | channel_send_window_changes(void) | ||
2575 | { | ||
2576 | u_int i; | ||
2577 | struct winsize ws; | ||
2578 | |||
2579 | for (i = 0; i < channels_alloc; i++) { | ||
2580 | if (channels[i] == NULL || | ||
2581 | channels[i]->type != SSH_CHANNEL_OPEN) | ||
2582 | continue; | ||
2583 | if (ioctl(channels[i]->rfd, TIOCGWINSZ, &ws) < 0) | ||
2584 | continue; | ||
2585 | channel_request_start(i, "window-change", 0); | ||
2586 | packet_put_int(ws.ws_col); | ||
2587 | packet_put_int(ws.ws_row); | ||
2588 | packet_put_int(ws.ws_xpixel); | ||
2589 | packet_put_int(ws.ws_ypixel); | ||
2590 | packet_send(); | ||
2591 | } | ||
2592 | } | ||
2593 | |||
2475 | /* -- X11 forwarding */ | 2594 | /* -- X11 forwarding */ |
2476 | 2595 | ||
2477 | /* | 2596 | /* |
@@ -2511,6 +2630,7 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost, | |||
2511 | if (sock < 0) { | 2630 | if (sock < 0) { |
2512 | if ((errno != EINVAL) && (errno != EAFNOSUPPORT)) { | 2631 | if ((errno != EINVAL) && (errno != EAFNOSUPPORT)) { |
2513 | error("socket: %.100s", strerror(errno)); | 2632 | error("socket: %.100s", strerror(errno)); |
2633 | freeaddrinfo(aitop); | ||
2514 | return -1; | 2634 | return -1; |
2515 | } else { | 2635 | } else { |
2516 | debug("x11_create_display_inet: Socket family %d not supported", | 2636 | debug("x11_create_display_inet: Socket family %d not supported", |
@@ -2783,7 +2903,7 @@ x11_request_forwarding_with_spoofing(int client_session_id, | |||
2783 | char *new_data; | 2903 | char *new_data; |
2784 | int screen_number; | 2904 | int screen_number; |
2785 | const char *cp; | 2905 | const char *cp; |
2786 | u_int32_t rand = 0; | 2906 | u_int32_t rnd = 0; |
2787 | 2907 | ||
2788 | cp = getenv("DISPLAY"); | 2908 | cp = getenv("DISPLAY"); |
2789 | if (cp) | 2909 | if (cp) |
@@ -2808,10 +2928,10 @@ x11_request_forwarding_with_spoofing(int client_session_id, | |||
2808 | if (sscanf(data + 2 * i, "%2x", &value) != 1) | 2928 | if (sscanf(data + 2 * i, "%2x", &value) != 1) |
2809 | fatal("x11_request_forwarding: bad authentication data: %.100s", data); | 2929 | fatal("x11_request_forwarding: bad authentication data: %.100s", data); |
2810 | if (i % 4 == 0) | 2930 | if (i % 4 == 0) |
2811 | rand = arc4random(); | 2931 | rnd = arc4random(); |
2812 | x11_saved_data[i] = value; | 2932 | x11_saved_data[i] = value; |
2813 | x11_fake_data[i] = rand & 0xff; | 2933 | x11_fake_data[i] = rnd & 0xff; |
2814 | rand >>= 8; | 2934 | rnd >>= 8; |
2815 | } | 2935 | } |
2816 | x11_saved_data_len = data_len; | 2936 | x11_saved_data_len = data_len; |
2817 | x11_fake_data_len = data_len; | 2937 | x11_fake_data_len = data_len; |