diff options
author | Colin Watson <cjwatson@debian.org> | 2017-10-04 11:23:58 +0100 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2017-10-04 11:23:58 +0100 |
commit | 62f54f20bf351468e0124f63cc2902ee40d9b0e9 (patch) | |
tree | 3e090f2711b94ca5029d3fa3e8047b1ed1448b1f /clientloop.c | |
parent | 6fabaf6fd9b07cc8bc6a17c9c4a5b76849cfc874 (diff) | |
parent | 66bf74a92131b7effe49fb0eefe5225151869dc5 (diff) |
Import openssh_7.6p1.orig.tar.gz
Diffstat (limited to 'clientloop.c')
-rw-r--r-- | clientloop.c | 855 |
1 files changed, 196 insertions, 659 deletions
diff --git a/clientloop.c b/clientloop.c index 064816234..791d336e3 100644 --- a/clientloop.c +++ b/clientloop.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: clientloop.c,v 1.291 2017/03/10 05:01:13 djm Exp $ */ | 1 | /* $OpenBSD: clientloop.c,v 1.305 2017/09/19 04:24:22 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -89,7 +89,6 @@ | |||
89 | #include "openbsd-compat/sys-queue.h" | 89 | #include "openbsd-compat/sys-queue.h" |
90 | #include "xmalloc.h" | 90 | #include "xmalloc.h" |
91 | #include "ssh.h" | 91 | #include "ssh.h" |
92 | #include "ssh1.h" | ||
93 | #include "ssh2.h" | 92 | #include "ssh2.h" |
94 | #include "packet.h" | 93 | #include "packet.h" |
95 | #include "buffer.h" | 94 | #include "buffer.h" |
@@ -152,15 +151,9 @@ static time_t control_persist_exit_time = 0; | |||
152 | 151 | ||
153 | /* Common data for the client loop code. */ | 152 | /* Common data for the client loop code. */ |
154 | volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */ | 153 | volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */ |
155 | static int escape_char1; /* Escape character. (proto1 only) */ | ||
156 | static int escape_pending1; /* Last character was an escape (proto1 only) */ | ||
157 | static int last_was_cr; /* Last character was a newline. */ | 154 | static int last_was_cr; /* Last character was a newline. */ |
158 | static int exit_status; /* Used to store the command exit status. */ | 155 | static int exit_status; /* Used to store the command exit status. */ |
159 | static int stdin_eof; /* EOF has been encountered on stderr. */ | 156 | static Buffer stderr_buffer; /* Used for final exit message. */ |
160 | static Buffer stdin_buffer; /* Buffer for stdin data. */ | ||
161 | static Buffer stdout_buffer; /* Buffer for stdout data. */ | ||
162 | static Buffer stderr_buffer; /* Buffer for stderr data. */ | ||
163 | static u_int buffer_high; /* Soft max buffer size. */ | ||
164 | static int connection_in; /* Connection to server (input). */ | 157 | static int connection_in; /* Connection to server (input). */ |
165 | static int connection_out; /* Connection to server (output). */ | 158 | static int connection_out; /* Connection to server (output). */ |
166 | static int need_rekeying; /* Set to non-zero if rekeying is requested. */ | 159 | static int need_rekeying; /* Set to non-zero if rekeying is requested. */ |
@@ -184,6 +177,7 @@ struct channel_reply_ctx { | |||
184 | }; | 177 | }; |
185 | 178 | ||
186 | /* Global request success/failure callbacks */ | 179 | /* Global request success/failure callbacks */ |
180 | /* XXX move to struct ssh? */ | ||
187 | struct global_confirm { | 181 | struct global_confirm { |
188 | TAILQ_ENTRY(global_confirm) entry; | 182 | TAILQ_ENTRY(global_confirm) entry; |
189 | global_confirm_cb *cb; | 183 | global_confirm_cb *cb; |
@@ -207,15 +201,6 @@ leave_non_blocking(void) | |||
207 | } | 201 | } |
208 | } | 202 | } |
209 | 203 | ||
210 | /* Puts stdin terminal in non-blocking mode. */ | ||
211 | |||
212 | static void | ||
213 | enter_non_blocking(void) | ||
214 | { | ||
215 | in_non_blocking_mode = 1; | ||
216 | set_nonblock(fileno(stdin)); | ||
217 | } | ||
218 | |||
219 | /* | 204 | /* |
220 | * Signal handler for the window change signal (SIGWINCH). This just sets a | 205 | * Signal handler for the window change signal (SIGWINCH). This just sets a |
221 | * flag indicating that the window has changed. | 206 | * flag indicating that the window has changed. |
@@ -260,13 +245,13 @@ get_current_time(void) | |||
260 | * control master process, or if there is no ControlPersist timeout. | 245 | * control master process, or if there is no ControlPersist timeout. |
261 | */ | 246 | */ |
262 | static void | 247 | static void |
263 | set_control_persist_exit_time(void) | 248 | set_control_persist_exit_time(struct ssh *ssh) |
264 | { | 249 | { |
265 | if (muxserver_sock == -1 || !options.control_persist | 250 | if (muxserver_sock == -1 || !options.control_persist |
266 | || options.control_persist_timeout == 0) { | 251 | || options.control_persist_timeout == 0) { |
267 | /* not using a ControlPersist timeout */ | 252 | /* not using a ControlPersist timeout */ |
268 | control_persist_exit_time = 0; | 253 | control_persist_exit_time = 0; |
269 | } else if (channel_still_open()) { | 254 | } else if (channel_still_open(ssh)) { |
270 | /* some client connections are still open */ | 255 | /* some client connections are still open */ |
271 | if (control_persist_exit_time > 0) | 256 | if (control_persist_exit_time > 0) |
272 | debug2("%s: cancel scheduled exit", __func__); | 257 | debug2("%s: cancel scheduled exit", __func__); |
@@ -304,8 +289,9 @@ client_x11_display_valid(const char *display) | |||
304 | #define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1" | 289 | #define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1" |
305 | #define X11_TIMEOUT_SLACK 60 | 290 | #define X11_TIMEOUT_SLACK 60 |
306 | int | 291 | int |
307 | client_x11_get_proto(const char *display, const char *xauth_path, | 292 | client_x11_get_proto(struct ssh *ssh, const char *display, |
308 | u_int trusted, u_int timeout, char **_proto, char **_data) | 293 | const char *xauth_path, u_int trusted, u_int timeout, |
294 | char **_proto, char **_data) | ||
309 | { | 295 | { |
310 | char cmd[1024], line[512], xdisplay[512]; | 296 | char cmd[1024], line[512], xdisplay[512]; |
311 | char xauthfile[PATH_MAX], xauthdir[PATH_MAX]; | 297 | char xauthfile[PATH_MAX], xauthdir[PATH_MAX]; |
@@ -389,7 +375,8 @@ client_x11_get_proto(const char *display, const char *xauth_path, | |||
389 | x11_refuse_time = UINT_MAX; | 375 | x11_refuse_time = UINT_MAX; |
390 | else | 376 | else |
391 | x11_refuse_time = now + timeout; | 377 | x11_refuse_time = now + timeout; |
392 | channel_set_x11_refuse_time(x11_refuse_time); | 378 | channel_set_x11_refuse_time(ssh, |
379 | x11_refuse_time); | ||
393 | } | 380 | } |
394 | if (system(cmd) == 0) | 381 | if (system(cmd) == 0) |
395 | generated = 1; | 382 | generated = 1; |
@@ -455,91 +442,6 @@ client_x11_get_proto(const char *display, const char *xauth_path, | |||
455 | } | 442 | } |
456 | 443 | ||
457 | /* | 444 | /* |
458 | * This is called when the interactive is entered. This checks if there is | ||
459 | * an EOF coming on stdin. We must check this explicitly, as select() does | ||
460 | * not appear to wake up when redirecting from /dev/null. | ||
461 | */ | ||
462 | |||
463 | static void | ||
464 | client_check_initial_eof_on_stdin(void) | ||
465 | { | ||
466 | int len; | ||
467 | char buf[1]; | ||
468 | |||
469 | /* | ||
470 | * If standard input is to be "redirected from /dev/null", we simply | ||
471 | * mark that we have seen an EOF and send an EOF message to the | ||
472 | * server. Otherwise, we try to read a single character; it appears | ||
473 | * that for some files, such /dev/null, select() never wakes up for | ||
474 | * read for this descriptor, which means that we never get EOF. This | ||
475 | * way we will get the EOF if stdin comes from /dev/null or similar. | ||
476 | */ | ||
477 | if (stdin_null_flag) { | ||
478 | /* Fake EOF on stdin. */ | ||
479 | debug("Sending eof."); | ||
480 | stdin_eof = 1; | ||
481 | packet_start(SSH_CMSG_EOF); | ||
482 | packet_send(); | ||
483 | } else { | ||
484 | enter_non_blocking(); | ||
485 | |||
486 | /* Check for immediate EOF on stdin. */ | ||
487 | len = read(fileno(stdin), buf, 1); | ||
488 | if (len == 0) { | ||
489 | /* | ||
490 | * EOF. Record that we have seen it and send | ||
491 | * EOF to server. | ||
492 | */ | ||
493 | debug("Sending eof."); | ||
494 | stdin_eof = 1; | ||
495 | packet_start(SSH_CMSG_EOF); | ||
496 | packet_send(); | ||
497 | } else if (len > 0) { | ||
498 | /* | ||
499 | * Got data. We must store the data in the buffer, | ||
500 | * and also process it as an escape character if | ||
501 | * appropriate. | ||
502 | */ | ||
503 | if ((u_char) buf[0] == escape_char1) | ||
504 | escape_pending1 = 1; | ||
505 | else | ||
506 | buffer_append(&stdin_buffer, buf, 1); | ||
507 | } | ||
508 | leave_non_blocking(); | ||
509 | } | ||
510 | } | ||
511 | |||
512 | |||
513 | /* | ||
514 | * Make packets from buffered stdin data, and buffer them for sending to the | ||
515 | * connection. | ||
516 | */ | ||
517 | |||
518 | static void | ||
519 | client_make_packets_from_stdin_data(void) | ||
520 | { | ||
521 | u_int len; | ||
522 | |||
523 | /* Send buffered stdin data to the server. */ | ||
524 | while (buffer_len(&stdin_buffer) > 0 && | ||
525 | packet_not_very_much_data_to_write()) { | ||
526 | len = buffer_len(&stdin_buffer); | ||
527 | /* Keep the packets at reasonable size. */ | ||
528 | if (len > packet_get_maxsize()) | ||
529 | len = packet_get_maxsize(); | ||
530 | packet_start(SSH_CMSG_STDIN_DATA); | ||
531 | packet_put_string(buffer_ptr(&stdin_buffer), len); | ||
532 | packet_send(); | ||
533 | buffer_consume(&stdin_buffer, len); | ||
534 | /* If we have a pending EOF, send it now. */ | ||
535 | if (stdin_eof && buffer_len(&stdin_buffer) == 0) { | ||
536 | packet_start(SSH_CMSG_EOF); | ||
537 | packet_send(); | ||
538 | } | ||
539 | } | ||
540 | } | ||
541 | |||
542 | /* | ||
543 | * Checks if the client window has changed, and sends a packet about it to | 445 | * Checks if the client window has changed, and sends a packet about it to |
544 | * the server if so. The actual change is detected elsewhere (by a software | 446 | * the server if so. The actual change is detected elsewhere (by a software |
545 | * interrupt on Unix); this just checks the flag and sends a message if | 447 | * interrupt on Unix); this just checks the flag and sends a message if |
@@ -547,40 +449,27 @@ client_make_packets_from_stdin_data(void) | |||
547 | */ | 449 | */ |
548 | 450 | ||
549 | static void | 451 | static void |
550 | client_check_window_change(void) | 452 | client_check_window_change(struct ssh *ssh) |
551 | { | 453 | { |
552 | struct winsize ws; | 454 | if (!received_window_change_signal) |
553 | |||
554 | if (! received_window_change_signal) | ||
555 | return; | 455 | return; |
556 | /** XXX race */ | 456 | /** XXX race */ |
557 | received_window_change_signal = 0; | 457 | received_window_change_signal = 0; |
558 | 458 | ||
559 | debug2("client_check_window_change: changed"); | 459 | debug2("%s: changed", __func__); |
560 | 460 | ||
561 | if (compat20) { | 461 | channel_send_window_changes(ssh); |
562 | channel_send_window_changes(); | ||
563 | } else { | ||
564 | if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0) | ||
565 | return; | ||
566 | packet_start(SSH_CMSG_WINDOW_SIZE); | ||
567 | packet_put_int((u_int)ws.ws_row); | ||
568 | packet_put_int((u_int)ws.ws_col); | ||
569 | packet_put_int((u_int)ws.ws_xpixel); | ||
570 | packet_put_int((u_int)ws.ws_ypixel); | ||
571 | packet_send(); | ||
572 | } | ||
573 | } | 462 | } |
574 | 463 | ||
575 | static int | 464 | static int |
576 | client_global_request_reply(int type, u_int32_t seq, void *ctxt) | 465 | client_global_request_reply(int type, u_int32_t seq, struct ssh *ssh) |
577 | { | 466 | { |
578 | struct global_confirm *gc; | 467 | struct global_confirm *gc; |
579 | 468 | ||
580 | if ((gc = TAILQ_FIRST(&global_confirms)) == NULL) | 469 | if ((gc = TAILQ_FIRST(&global_confirms)) == NULL) |
581 | return 0; | 470 | return 0; |
582 | if (gc->cb != NULL) | 471 | if (gc->cb != NULL) |
583 | gc->cb(type, seq, gc->ctx); | 472 | gc->cb(ssh, type, seq, gc->ctx); |
584 | if (--gc->ref_count <= 0) { | 473 | if (--gc->ref_count <= 0) { |
585 | TAILQ_REMOVE(&global_confirms, gc, entry); | 474 | TAILQ_REMOVE(&global_confirms, gc, entry); |
586 | explicit_bzero(gc, sizeof(*gc)); | 475 | explicit_bzero(gc, sizeof(*gc)); |
@@ -611,7 +500,8 @@ server_alive_check(void) | |||
611 | * one of the file descriptors). | 500 | * one of the file descriptors). |
612 | */ | 501 | */ |
613 | static void | 502 | static void |
614 | client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, | 503 | client_wait_until_can_do_something(struct ssh *ssh, |
504 | fd_set **readsetp, fd_set **writesetp, | ||
615 | int *maxfdp, u_int *nallocp, int rekeying) | 505 | int *maxfdp, u_int *nallocp, int rekeying) |
616 | { | 506 | { |
617 | struct timeval tv, *tvp; | 507 | struct timeval tv, *tvp; |
@@ -620,40 +510,20 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, | |||
620 | int ret; | 510 | int ret; |
621 | 511 | ||
622 | /* Add any selections by the channel mechanism. */ | 512 | /* Add any selections by the channel mechanism. */ |
623 | channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, | 513 | channel_prepare_select(active_state, readsetp, writesetp, maxfdp, |
624 | &minwait_secs, rekeying); | 514 | nallocp, &minwait_secs); |
625 | 515 | ||
626 | if (!compat20) { | 516 | /* channel_prepare_select could have closed the last channel */ |
627 | /* Read from the connection, unless our buffers are full. */ | 517 | if (session_closed && !channel_still_open(ssh) && |
628 | if (buffer_len(&stdout_buffer) < buffer_high && | 518 | !packet_have_data_to_write()) { |
629 | buffer_len(&stderr_buffer) < buffer_high && | 519 | /* clear mask since we did not call select() */ |
630 | channel_not_very_much_buffered_data()) | 520 | memset(*readsetp, 0, *nallocp); |
631 | FD_SET(connection_in, *readsetp); | 521 | memset(*writesetp, 0, *nallocp); |
632 | /* | 522 | return; |
633 | * Read from stdin, unless we have seen EOF or have very much | ||
634 | * buffered data to send to the server. | ||
635 | */ | ||
636 | if (!stdin_eof && packet_not_very_much_data_to_write()) | ||
637 | FD_SET(fileno(stdin), *readsetp); | ||
638 | |||
639 | /* Select stdout/stderr if have data in buffer. */ | ||
640 | if (buffer_len(&stdout_buffer) > 0) | ||
641 | FD_SET(fileno(stdout), *writesetp); | ||
642 | if (buffer_len(&stderr_buffer) > 0) | ||
643 | FD_SET(fileno(stderr), *writesetp); | ||
644 | } else { | ||
645 | /* channel_prepare_select could have closed the last channel */ | ||
646 | if (session_closed && !channel_still_open() && | ||
647 | !packet_have_data_to_write()) { | ||
648 | /* clear mask since we did not call select() */ | ||
649 | memset(*readsetp, 0, *nallocp); | ||
650 | memset(*writesetp, 0, *nallocp); | ||
651 | return; | ||
652 | } else { | ||
653 | FD_SET(connection_in, *readsetp); | ||
654 | } | ||
655 | } | 523 | } |
656 | 524 | ||
525 | FD_SET(connection_in, *readsetp); | ||
526 | |||
657 | /* Select server connection if have data to write to the server. */ | 527 | /* Select server connection if have data to write to the server. */ |
658 | if (packet_have_data_to_write()) | 528 | if (packet_have_data_to_write()) |
659 | FD_SET(connection_out, *writesetp); | 529 | FD_SET(connection_out, *writesetp); |
@@ -665,13 +535,13 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, | |||
665 | */ | 535 | */ |
666 | 536 | ||
667 | timeout_secs = INT_MAX; /* we use INT_MAX to mean no timeout */ | 537 | timeout_secs = INT_MAX; /* we use INT_MAX to mean no timeout */ |
668 | if (options.server_alive_interval > 0 && compat20) { | 538 | if (options.server_alive_interval > 0) { |
669 | timeout_secs = options.server_alive_interval; | 539 | timeout_secs = options.server_alive_interval; |
670 | server_alive_time = now + options.server_alive_interval; | 540 | server_alive_time = now + options.server_alive_interval; |
671 | } | 541 | } |
672 | if (options.rekey_interval > 0 && compat20 && !rekeying) | 542 | if (options.rekey_interval > 0 && !rekeying) |
673 | timeout_secs = MINIMUM(timeout_secs, packet_get_rekey_timeout()); | 543 | timeout_secs = MINIMUM(timeout_secs, packet_get_rekey_timeout()); |
674 | set_control_persist_exit_time(); | 544 | set_control_persist_exit_time(ssh); |
675 | if (control_persist_exit_time > 0) { | 545 | if (control_persist_exit_time > 0) { |
676 | timeout_secs = MINIMUM(timeout_secs, | 546 | timeout_secs = MINIMUM(timeout_secs, |
677 | control_persist_exit_time - now); | 547 | control_persist_exit_time - now); |
@@ -730,13 +600,9 @@ client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr) | |||
730 | 600 | ||
731 | leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); | 601 | leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); |
732 | 602 | ||
733 | /* | 603 | sshbuf_reset(bin); |
734 | * Free (and clear) the buffer to reduce the amount of data that gets | 604 | sshbuf_reset(bout); |
735 | * written to swap. | 605 | sshbuf_reset(berr); |
736 | */ | ||
737 | buffer_free(bin); | ||
738 | buffer_free(bout); | ||
739 | buffer_free(berr); | ||
740 | 606 | ||
741 | /* Send the suspend signal to the program itself. */ | 607 | /* Send the suspend signal to the program itself. */ |
742 | kill(getpid(), SIGTSTP); | 608 | kill(getpid(), SIGTSTP); |
@@ -744,11 +610,6 @@ client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr) | |||
744 | /* Reset window sizes in case they have changed */ | 610 | /* Reset window sizes in case they have changed */ |
745 | received_window_change_signal = 1; | 611 | received_window_change_signal = 1; |
746 | 612 | ||
747 | /* OK, we have been continued by the user. Reinitialize buffers. */ | ||
748 | buffer_init(bin); | ||
749 | buffer_init(bout); | ||
750 | buffer_init(berr); | ||
751 | |||
752 | enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE); | 613 | enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE); |
753 | } | 614 | } |
754 | 615 | ||
@@ -802,7 +663,7 @@ client_process_net_input(fd_set *readset) | |||
802 | } | 663 | } |
803 | 664 | ||
804 | static void | 665 | static void |
805 | client_status_confirm(int type, Channel *c, void *ctx) | 666 | client_status_confirm(struct ssh *ssh, int type, Channel *c, void *ctx) |
806 | { | 667 | { |
807 | struct channel_reply_ctx *cr = (struct channel_reply_ctx *)ctx; | 668 | struct channel_reply_ctx *cr = (struct channel_reply_ctx *)ctx; |
808 | char errmsg[256]; | 669 | char errmsg[256]; |
@@ -841,8 +702,7 @@ client_status_confirm(int type, Channel *c, void *ctx) | |||
841 | * their stderr. | 702 | * their stderr. |
842 | */ | 703 | */ |
843 | if (tochan) { | 704 | if (tochan) { |
844 | buffer_append(&c->extended, errmsg, | 705 | buffer_append(c->extended, errmsg, strlen(errmsg)); |
845 | strlen(errmsg)); | ||
846 | } else | 706 | } else |
847 | error("%s", errmsg); | 707 | error("%s", errmsg); |
848 | if (cr->action == CONFIRM_TTY) { | 708 | if (cr->action == CONFIRM_TTY) { |
@@ -853,23 +713,23 @@ client_status_confirm(int type, Channel *c, void *ctx) | |||
853 | if (c->self == session_ident) | 713 | if (c->self == session_ident) |
854 | leave_raw_mode(0); | 714 | leave_raw_mode(0); |
855 | else | 715 | else |
856 | mux_tty_alloc_failed(c); | 716 | mux_tty_alloc_failed(ssh, c); |
857 | } else if (cr->action == CONFIRM_CLOSE) { | 717 | } else if (cr->action == CONFIRM_CLOSE) { |
858 | chan_read_failed(c); | 718 | chan_read_failed(ssh, c); |
859 | chan_write_failed(c); | 719 | chan_write_failed(ssh, c); |
860 | } | 720 | } |
861 | } | 721 | } |
862 | free(cr); | 722 | free(cr); |
863 | } | 723 | } |
864 | 724 | ||
865 | static void | 725 | static void |
866 | client_abandon_status_confirm(Channel *c, void *ctx) | 726 | client_abandon_status_confirm(struct ssh *ssh, Channel *c, void *ctx) |
867 | { | 727 | { |
868 | free(ctx); | 728 | free(ctx); |
869 | } | 729 | } |
870 | 730 | ||
871 | void | 731 | void |
872 | client_expect_confirm(int id, const char *request, | 732 | client_expect_confirm(struct ssh *ssh, int id, const char *request, |
873 | enum confirm_action action) | 733 | enum confirm_action action) |
874 | { | 734 | { |
875 | struct channel_reply_ctx *cr = xcalloc(1, sizeof(*cr)); | 735 | struct channel_reply_ctx *cr = xcalloc(1, sizeof(*cr)); |
@@ -877,7 +737,7 @@ client_expect_confirm(int id, const char *request, | |||
877 | cr->request_type = request; | 737 | cr->request_type = request; |
878 | cr->action = action; | 738 | cr->action = action; |
879 | 739 | ||
880 | channel_register_status_confirm(id, client_status_confirm, | 740 | channel_register_status_confirm(ssh, id, client_status_confirm, |
881 | client_abandon_status_confirm, cr); | 741 | client_abandon_status_confirm, cr); |
882 | } | 742 | } |
883 | 743 | ||
@@ -903,7 +763,7 @@ client_register_global_confirm(global_confirm_cb *cb, void *ctx) | |||
903 | } | 763 | } |
904 | 764 | ||
905 | static void | 765 | static void |
906 | process_cmdline(void) | 766 | process_cmdline(struct ssh *ssh) |
907 | { | 767 | { |
908 | void (*handler)(int); | 768 | void (*handler)(int); |
909 | char *s, *cmd; | 769 | char *s, *cmd; |
@@ -966,11 +826,6 @@ process_cmdline(void) | |||
966 | goto out; | 826 | goto out; |
967 | } | 827 | } |
968 | 828 | ||
969 | if (delete && !compat20) { | ||
970 | logit("Not supported for SSH protocol version 1."); | ||
971 | goto out; | ||
972 | } | ||
973 | |||
974 | while (isspace((u_char)*++s)) | 829 | while (isspace((u_char)*++s)) |
975 | ; | 830 | ; |
976 | 831 | ||
@@ -982,12 +837,12 @@ process_cmdline(void) | |||
982 | goto out; | 837 | goto out; |
983 | } | 838 | } |
984 | if (remote) | 839 | if (remote) |
985 | ok = channel_request_rforward_cancel(&fwd) == 0; | 840 | ok = channel_request_rforward_cancel(ssh, &fwd) == 0; |
986 | else if (dynamic) | 841 | else if (dynamic) |
987 | ok = channel_cancel_lport_listener(&fwd, | 842 | ok = channel_cancel_lport_listener(ssh, &fwd, |
988 | 0, &options.fwd_opts) > 0; | 843 | 0, &options.fwd_opts) > 0; |
989 | else | 844 | else |
990 | ok = channel_cancel_lport_listener(&fwd, | 845 | ok = channel_cancel_lport_listener(ssh, &fwd, |
991 | CHANNEL_CANCEL_PORT_STATIC, | 846 | CHANNEL_CANCEL_PORT_STATIC, |
992 | &options.fwd_opts) > 0; | 847 | &options.fwd_opts) > 0; |
993 | if (!ok) { | 848 | if (!ok) { |
@@ -1001,13 +856,13 @@ process_cmdline(void) | |||
1001 | goto out; | 856 | goto out; |
1002 | } | 857 | } |
1003 | if (local || dynamic) { | 858 | if (local || dynamic) { |
1004 | if (!channel_setup_local_fwd_listener(&fwd, | 859 | if (!channel_setup_local_fwd_listener(ssh, &fwd, |
1005 | &options.fwd_opts)) { | 860 | &options.fwd_opts)) { |
1006 | logit("Port forwarding failed."); | 861 | logit("Port forwarding failed."); |
1007 | goto out; | 862 | goto out; |
1008 | } | 863 | } |
1009 | } else { | 864 | } else { |
1010 | if (channel_request_remote_forwarding(&fwd) < 0) { | 865 | if (channel_request_remote_forwarding(ssh, &fwd) < 0) { |
1011 | logit("Port forwarding failed."); | 866 | logit("Port forwarding failed."); |
1012 | goto out; | 867 | goto out; |
1013 | } | 868 | } |
@@ -1027,10 +882,9 @@ out: | |||
1027 | 882 | ||
1028 | /* reasons to suppress output of an escape command in help output */ | 883 | /* reasons to suppress output of an escape command in help output */ |
1029 | #define SUPPRESS_NEVER 0 /* never suppress, always show */ | 884 | #define SUPPRESS_NEVER 0 /* never suppress, always show */ |
1030 | #define SUPPRESS_PROTO1 1 /* don't show in protocol 1 sessions */ | 885 | #define SUPPRESS_MUXCLIENT 1 /* don't show in mux client sessions */ |
1031 | #define SUPPRESS_MUXCLIENT 2 /* don't show in mux client sessions */ | 886 | #define SUPPRESS_MUXMASTER 2 /* don't show in mux master sessions */ |
1032 | #define SUPPRESS_MUXMASTER 4 /* don't show in mux master sessions */ | 887 | #define SUPPRESS_SYSLOG 4 /* don't show when logging to syslog */ |
1033 | #define SUPPRESS_SYSLOG 8 /* don't show when logging to syslog */ | ||
1034 | struct escape_help_text { | 888 | struct escape_help_text { |
1035 | const char *cmd; | 889 | const char *cmd; |
1036 | const char *text; | 890 | const char *text; |
@@ -1040,9 +894,9 @@ static struct escape_help_text esc_txt[] = { | |||
1040 | {".", "terminate session", SUPPRESS_MUXMASTER}, | 894 | {".", "terminate session", SUPPRESS_MUXMASTER}, |
1041 | {".", "terminate connection (and any multiplexed sessions)", | 895 | {".", "terminate connection (and any multiplexed sessions)", |
1042 | SUPPRESS_MUXCLIENT}, | 896 | SUPPRESS_MUXCLIENT}, |
1043 | {"B", "send a BREAK to the remote system", SUPPRESS_PROTO1}, | 897 | {"B", "send a BREAK to the remote system", SUPPRESS_NEVER}, |
1044 | {"C", "open a command line", SUPPRESS_MUXCLIENT}, | 898 | {"C", "open a command line", SUPPRESS_MUXCLIENT}, |
1045 | {"R", "request rekey", SUPPRESS_PROTO1}, | 899 | {"R", "request rekey", SUPPRESS_NEVER}, |
1046 | {"V/v", "decrease/increase verbosity (LogLevel)", SUPPRESS_MUXCLIENT}, | 900 | {"V/v", "decrease/increase verbosity (LogLevel)", SUPPRESS_MUXCLIENT}, |
1047 | {"^Z", "suspend ssh", SUPPRESS_MUXCLIENT}, | 901 | {"^Z", "suspend ssh", SUPPRESS_MUXCLIENT}, |
1048 | {"#", "list forwarded connections", SUPPRESS_NEVER}, | 902 | {"#", "list forwarded connections", SUPPRESS_NEVER}, |
@@ -1052,8 +906,7 @@ static struct escape_help_text esc_txt[] = { | |||
1052 | }; | 906 | }; |
1053 | 907 | ||
1054 | static void | 908 | static void |
1055 | print_escape_help(Buffer *b, int escape_char, int protocol2, int mux_client, | 909 | print_escape_help(Buffer *b, int escape_char, int mux_client, int using_stderr) |
1056 | int using_stderr) | ||
1057 | { | 910 | { |
1058 | unsigned int i, suppress_flags; | 911 | unsigned int i, suppress_flags; |
1059 | char string[1024]; | 912 | char string[1024]; |
@@ -1062,7 +915,7 @@ print_escape_help(Buffer *b, int escape_char, int protocol2, int mux_client, | |||
1062 | "Supported escape sequences:\r\n", escape_char); | 915 | "Supported escape sequences:\r\n", escape_char); |
1063 | buffer_append(b, string, strlen(string)); | 916 | buffer_append(b, string, strlen(string)); |
1064 | 917 | ||
1065 | suppress_flags = (protocol2 ? 0 : SUPPRESS_PROTO1) | | 918 | suppress_flags = |
1066 | (mux_client ? SUPPRESS_MUXCLIENT : 0) | | 919 | (mux_client ? SUPPRESS_MUXCLIENT : 0) | |
1067 | (mux_client ? 0 : SUPPRESS_MUXMASTER) | | 920 | (mux_client ? 0 : SUPPRESS_MUXMASTER) | |
1068 | (using_stderr ? 0 : SUPPRESS_SYSLOG); | 921 | (using_stderr ? 0 : SUPPRESS_SYSLOG); |
@@ -1083,10 +936,11 @@ print_escape_help(Buffer *b, int escape_char, int protocol2, int mux_client, | |||
1083 | } | 936 | } |
1084 | 937 | ||
1085 | /* | 938 | /* |
1086 | * Process the characters one by one, call with c==NULL for proto1 case. | 939 | * Process the characters one by one. |
1087 | */ | 940 | */ |
1088 | static int | 941 | static int |
1089 | process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | 942 | process_escapes(struct ssh *ssh, Channel *c, |
943 | Buffer *bin, Buffer *bout, Buffer *berr, | ||
1090 | char *buf, int len) | 944 | char *buf, int len) |
1091 | { | 945 | { |
1092 | char string[1024]; | 946 | char string[1024]; |
@@ -1095,19 +949,11 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1095 | u_int i; | 949 | u_int i; |
1096 | u_char ch; | 950 | u_char ch; |
1097 | char *s; | 951 | char *s; |
1098 | int *escape_pendingp, escape_char; | 952 | struct escape_filter_ctx *efc = c->filter_ctx == NULL ? |
1099 | struct escape_filter_ctx *efc; | 953 | NULL : (struct escape_filter_ctx *)c->filter_ctx; |
1100 | 954 | ||
1101 | if (c == NULL) { | 955 | if (c->filter_ctx == NULL) |
1102 | escape_pendingp = &escape_pending1; | 956 | return 0; |
1103 | escape_char = escape_char1; | ||
1104 | } else { | ||
1105 | if (c->filter_ctx == NULL) | ||
1106 | return 0; | ||
1107 | efc = (struct escape_filter_ctx *)c->filter_ctx; | ||
1108 | escape_pendingp = &efc->escape_pending; | ||
1109 | escape_char = efc->escape_char; | ||
1110 | } | ||
1111 | 957 | ||
1112 | if (len <= 0) | 958 | if (len <= 0) |
1113 | return (0); | 959 | return (0); |
@@ -1116,27 +962,29 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1116 | /* Get one character at a time. */ | 962 | /* Get one character at a time. */ |
1117 | ch = buf[i]; | 963 | ch = buf[i]; |
1118 | 964 | ||
1119 | if (*escape_pendingp) { | 965 | if (efc->escape_pending) { |
1120 | /* We have previously seen an escape character. */ | 966 | /* We have previously seen an escape character. */ |
1121 | /* Clear the flag now. */ | 967 | /* Clear the flag now. */ |
1122 | *escape_pendingp = 0; | 968 | efc->escape_pending = 0; |
1123 | 969 | ||
1124 | /* Process the escaped character. */ | 970 | /* Process the escaped character. */ |
1125 | switch (ch) { | 971 | switch (ch) { |
1126 | case '.': | 972 | case '.': |
1127 | /* Terminate the connection. */ | 973 | /* Terminate the connection. */ |
1128 | snprintf(string, sizeof string, "%c.\r\n", | 974 | snprintf(string, sizeof string, "%c.\r\n", |
1129 | escape_char); | 975 | efc->escape_char); |
1130 | buffer_append(berr, string, strlen(string)); | 976 | buffer_append(berr, string, strlen(string)); |
1131 | 977 | ||
1132 | if (c && c->ctl_chan != -1) { | 978 | if (c && c->ctl_chan != -1) { |
1133 | chan_read_failed(c); | 979 | chan_read_failed(ssh, c); |
1134 | chan_write_failed(c); | 980 | chan_write_failed(ssh, c); |
1135 | if (c->detach_user) | 981 | if (c->detach_user) { |
1136 | c->detach_user(c->self, NULL); | 982 | c->detach_user(ssh, |
983 | c->self, NULL); | ||
984 | } | ||
1137 | c->type = SSH_CHANNEL_ABANDONED; | 985 | c->type = SSH_CHANNEL_ABANDONED; |
1138 | buffer_clear(&c->input); | 986 | buffer_clear(c->input); |
1139 | chan_ibuf_empty(c); | 987 | chan_ibuf_empty(ssh, c); |
1140 | return 0; | 988 | return 0; |
1141 | } else | 989 | } else |
1142 | quit_pending = 1; | 990 | quit_pending = 1; |
@@ -1154,14 +1002,14 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1154 | snprintf(string, sizeof string, | 1002 | snprintf(string, sizeof string, |
1155 | "%c%s escape not available to " | 1003 | "%c%s escape not available to " |
1156 | "multiplexed sessions\r\n", | 1004 | "multiplexed sessions\r\n", |
1157 | escape_char, b); | 1005 | efc->escape_char, b); |
1158 | buffer_append(berr, string, | 1006 | buffer_append(berr, string, |
1159 | strlen(string)); | 1007 | strlen(string)); |
1160 | continue; | 1008 | continue; |
1161 | } | 1009 | } |
1162 | /* Suspend the program. Inform the user */ | 1010 | /* Suspend the program. Inform the user */ |
1163 | snprintf(string, sizeof string, | 1011 | snprintf(string, sizeof string, |
1164 | "%c^Z [suspend ssh]\r\n", escape_char); | 1012 | "%c^Z [suspend ssh]\r\n", efc->escape_char); |
1165 | buffer_append(berr, string, strlen(string)); | 1013 | buffer_append(berr, string, strlen(string)); |
1166 | 1014 | ||
1167 | /* Restore terminal modes and suspend. */ | 1015 | /* Restore terminal modes and suspend. */ |
@@ -1171,26 +1019,20 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1171 | continue; | 1019 | continue; |
1172 | 1020 | ||
1173 | case 'B': | 1021 | case 'B': |
1174 | if (compat20) { | 1022 | snprintf(string, sizeof string, |
1175 | snprintf(string, sizeof string, | 1023 | "%cB\r\n", efc->escape_char); |
1176 | "%cB\r\n", escape_char); | 1024 | buffer_append(berr, string, strlen(string)); |
1177 | buffer_append(berr, string, | 1025 | channel_request_start(ssh, c->self, "break", 0); |
1178 | strlen(string)); | 1026 | packet_put_int(1000); |
1179 | channel_request_start(c->self, | 1027 | packet_send(); |
1180 | "break", 0); | ||
1181 | packet_put_int(1000); | ||
1182 | packet_send(); | ||
1183 | } | ||
1184 | continue; | 1028 | continue; |
1185 | 1029 | ||
1186 | case 'R': | 1030 | case 'R': |
1187 | if (compat20) { | 1031 | if (datafellows & SSH_BUG_NOREKEY) |
1188 | if (datafellows & SSH_BUG_NOREKEY) | 1032 | logit("Server does not " |
1189 | logit("Server does not " | 1033 | "support re-keying"); |
1190 | "support re-keying"); | 1034 | else |
1191 | else | 1035 | need_rekeying = 1; |
1192 | need_rekeying = 1; | ||
1193 | } | ||
1194 | continue; | 1036 | continue; |
1195 | 1037 | ||
1196 | case 'V': | 1038 | case 'V': |
@@ -1201,7 +1043,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1201 | if (!log_is_on_stderr()) { | 1043 | if (!log_is_on_stderr()) { |
1202 | snprintf(string, sizeof string, | 1044 | snprintf(string, sizeof string, |
1203 | "%c%c [Logging to syslog]\r\n", | 1045 | "%c%c [Logging to syslog]\r\n", |
1204 | escape_char, ch); | 1046 | efc->escape_char, ch); |
1205 | buffer_append(berr, string, | 1047 | buffer_append(berr, string, |
1206 | strlen(string)); | 1048 | strlen(string)); |
1207 | continue; | 1049 | continue; |
@@ -1213,7 +1055,8 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1213 | SYSLOG_LEVEL_DEBUG3) | 1055 | SYSLOG_LEVEL_DEBUG3) |
1214 | log_change_level(++options.log_level); | 1056 | log_change_level(++options.log_level); |
1215 | snprintf(string, sizeof string, | 1057 | snprintf(string, sizeof string, |
1216 | "%c%c [LogLevel %s]\r\n", escape_char, ch, | 1058 | "%c%c [LogLevel %s]\r\n", |
1059 | efc->escape_char, ch, | ||
1217 | log_level_name(options.log_level)); | 1060 | log_level_name(options.log_level)); |
1218 | buffer_append(berr, string, strlen(string)); | 1061 | buffer_append(berr, string, strlen(string)); |
1219 | continue; | 1062 | continue; |
@@ -1231,10 +1074,10 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1231 | options.request_tty == REQUEST_TTY_FORCE); | 1074 | options.request_tty == REQUEST_TTY_FORCE); |
1232 | 1075 | ||
1233 | /* Stop listening for new connections. */ | 1076 | /* Stop listening for new connections. */ |
1234 | channel_stop_listening(); | 1077 | channel_stop_listening(ssh); |
1235 | 1078 | ||
1236 | snprintf(string, sizeof string, | 1079 | snprintf(string, sizeof string, |
1237 | "%c& [backgrounded]\n", escape_char); | 1080 | "%c& [backgrounded]\n", efc->escape_char); |
1238 | buffer_append(berr, string, strlen(string)); | 1081 | buffer_append(berr, string, strlen(string)); |
1239 | 1082 | ||
1240 | /* Fork into background. */ | 1083 | /* Fork into background. */ |
@@ -1248,39 +1091,20 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1248 | exit(0); | 1091 | exit(0); |
1249 | } | 1092 | } |
1250 | /* The child continues serving connections. */ | 1093 | /* The child continues serving connections. */ |
1251 | if (compat20) { | 1094 | buffer_append(bin, "\004", 1); |
1252 | buffer_append(bin, "\004", 1); | 1095 | /* fake EOF on stdin */ |
1253 | /* fake EOF on stdin */ | 1096 | return -1; |
1254 | return -1; | ||
1255 | } else if (!stdin_eof) { | ||
1256 | /* | ||
1257 | * Sending SSH_CMSG_EOF alone does not | ||
1258 | * always appear to be enough. So we | ||
1259 | * try to send an EOF character first. | ||
1260 | */ | ||
1261 | packet_start(SSH_CMSG_STDIN_DATA); | ||
1262 | packet_put_string("\004", 1); | ||
1263 | packet_send(); | ||
1264 | /* Close stdin. */ | ||
1265 | stdin_eof = 1; | ||
1266 | if (buffer_len(bin) == 0) { | ||
1267 | packet_start(SSH_CMSG_EOF); | ||
1268 | packet_send(); | ||
1269 | } | ||
1270 | } | ||
1271 | continue; | ||
1272 | |||
1273 | case '?': | 1097 | case '?': |
1274 | print_escape_help(berr, escape_char, compat20, | 1098 | print_escape_help(berr, efc->escape_char, |
1275 | (c && c->ctl_chan != -1), | 1099 | (c && c->ctl_chan != -1), |
1276 | log_is_on_stderr()); | 1100 | log_is_on_stderr()); |
1277 | continue; | 1101 | continue; |
1278 | 1102 | ||
1279 | case '#': | 1103 | case '#': |
1280 | snprintf(string, sizeof string, "%c#\r\n", | 1104 | snprintf(string, sizeof string, "%c#\r\n", |
1281 | escape_char); | 1105 | efc->escape_char); |
1282 | buffer_append(berr, string, strlen(string)); | 1106 | buffer_append(berr, string, strlen(string)); |
1283 | s = channel_open_message(); | 1107 | s = channel_open_message(ssh); |
1284 | buffer_append(berr, s, strlen(s)); | 1108 | buffer_append(berr, s, strlen(s)); |
1285 | free(s); | 1109 | free(s); |
1286 | continue; | 1110 | continue; |
@@ -1288,12 +1112,12 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1288 | case 'C': | 1112 | case 'C': |
1289 | if (c && c->ctl_chan != -1) | 1113 | if (c && c->ctl_chan != -1) |
1290 | goto noescape; | 1114 | goto noescape; |
1291 | process_cmdline(); | 1115 | process_cmdline(ssh); |
1292 | continue; | 1116 | continue; |
1293 | 1117 | ||
1294 | default: | 1118 | default: |
1295 | if (ch != escape_char) { | 1119 | if (ch != efc->escape_char) { |
1296 | buffer_put_char(bin, escape_char); | 1120 | buffer_put_char(bin, efc->escape_char); |
1297 | bytes++; | 1121 | bytes++; |
1298 | } | 1122 | } |
1299 | /* Escaped characters fall through here */ | 1123 | /* Escaped characters fall through here */ |
@@ -1304,12 +1128,12 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1304 | * The previous character was not an escape char. | 1128 | * The previous character was not an escape char. |
1305 | * Check if this is an escape. | 1129 | * Check if this is an escape. |
1306 | */ | 1130 | */ |
1307 | if (last_was_cr && ch == escape_char) { | 1131 | if (last_was_cr && ch == efc->escape_char) { |
1308 | /* | 1132 | /* |
1309 | * It is. Set the flag and continue to | 1133 | * It is. Set the flag and continue to |
1310 | * next character. | 1134 | * next character. |
1311 | */ | 1135 | */ |
1312 | *escape_pendingp = 1; | 1136 | efc->escape_pending = 1; |
1313 | continue; | 1137 | continue; |
1314 | } | 1138 | } |
1315 | } | 1139 | } |
@@ -1325,115 +1149,6 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1325 | return bytes; | 1149 | return bytes; |
1326 | } | 1150 | } |
1327 | 1151 | ||
1328 | static void | ||
1329 | client_process_input(fd_set *readset) | ||
1330 | { | ||
1331 | int len; | ||
1332 | char buf[SSH_IOBUFSZ]; | ||
1333 | |||
1334 | /* Read input from stdin. */ | ||
1335 | if (FD_ISSET(fileno(stdin), readset)) { | ||
1336 | /* Read as much as possible. */ | ||
1337 | len = read(fileno(stdin), buf, sizeof(buf)); | ||
1338 | if (len < 0 && | ||
1339 | (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK)) | ||
1340 | return; /* we'll try again later */ | ||
1341 | if (len <= 0) { | ||
1342 | /* | ||
1343 | * Received EOF or error. They are treated | ||
1344 | * similarly, except that an error message is printed | ||
1345 | * if it was an error condition. | ||
1346 | */ | ||
1347 | if (len < 0) { | ||
1348 | snprintf(buf, sizeof buf, "read: %.100s\r\n", | ||
1349 | strerror(errno)); | ||
1350 | buffer_append(&stderr_buffer, buf, strlen(buf)); | ||
1351 | } | ||
1352 | /* Mark that we have seen EOF. */ | ||
1353 | stdin_eof = 1; | ||
1354 | /* | ||
1355 | * Send an EOF message to the server unless there is | ||
1356 | * data in the buffer. If there is data in the | ||
1357 | * buffer, no message will be sent now. Code | ||
1358 | * elsewhere will send the EOF when the buffer | ||
1359 | * becomes empty if stdin_eof is set. | ||
1360 | */ | ||
1361 | if (buffer_len(&stdin_buffer) == 0) { | ||
1362 | packet_start(SSH_CMSG_EOF); | ||
1363 | packet_send(); | ||
1364 | } | ||
1365 | } else if (escape_char1 == SSH_ESCAPECHAR_NONE) { | ||
1366 | /* | ||
1367 | * Normal successful read, and no escape character. | ||
1368 | * Just append the data to buffer. | ||
1369 | */ | ||
1370 | buffer_append(&stdin_buffer, buf, len); | ||
1371 | } else { | ||
1372 | /* | ||
1373 | * Normal, successful read. But we have an escape | ||
1374 | * character and have to process the characters one | ||
1375 | * by one. | ||
1376 | */ | ||
1377 | if (process_escapes(NULL, &stdin_buffer, | ||
1378 | &stdout_buffer, &stderr_buffer, buf, len) == -1) | ||
1379 | return; | ||
1380 | } | ||
1381 | } | ||
1382 | } | ||
1383 | |||
1384 | static void | ||
1385 | client_process_output(fd_set *writeset) | ||
1386 | { | ||
1387 | int len; | ||
1388 | char buf[100]; | ||
1389 | |||
1390 | /* Write buffered output to stdout. */ | ||
1391 | if (FD_ISSET(fileno(stdout), writeset)) { | ||
1392 | /* Write as much data as possible. */ | ||
1393 | len = write(fileno(stdout), buffer_ptr(&stdout_buffer), | ||
1394 | buffer_len(&stdout_buffer)); | ||
1395 | if (len <= 0) { | ||
1396 | if (errno == EINTR || errno == EAGAIN || | ||
1397 | errno == EWOULDBLOCK) | ||
1398 | len = 0; | ||
1399 | else { | ||
1400 | /* | ||
1401 | * An error or EOF was encountered. Put an | ||
1402 | * error message to stderr buffer. | ||
1403 | */ | ||
1404 | snprintf(buf, sizeof buf, | ||
1405 | "write stdout: %.50s\r\n", strerror(errno)); | ||
1406 | buffer_append(&stderr_buffer, buf, strlen(buf)); | ||
1407 | quit_pending = 1; | ||
1408 | return; | ||
1409 | } | ||
1410 | } | ||
1411 | /* Consume printed data from the buffer. */ | ||
1412 | buffer_consume(&stdout_buffer, len); | ||
1413 | } | ||
1414 | /* Write buffered output to stderr. */ | ||
1415 | if (FD_ISSET(fileno(stderr), writeset)) { | ||
1416 | /* Write as much data as possible. */ | ||
1417 | len = write(fileno(stderr), buffer_ptr(&stderr_buffer), | ||
1418 | buffer_len(&stderr_buffer)); | ||
1419 | if (len <= 0) { | ||
1420 | if (errno == EINTR || errno == EAGAIN || | ||
1421 | errno == EWOULDBLOCK) | ||
1422 | len = 0; | ||
1423 | else { | ||
1424 | /* | ||
1425 | * EOF or error, but can't even print | ||
1426 | * error message. | ||
1427 | */ | ||
1428 | quit_pending = 1; | ||
1429 | return; | ||
1430 | } | ||
1431 | } | ||
1432 | /* Consume printed characters from the buffer. */ | ||
1433 | buffer_consume(&stderr_buffer, len); | ||
1434 | } | ||
1435 | } | ||
1436 | |||
1437 | /* | 1152 | /* |
1438 | * Get packets from the connection input buffer, and process them as long as | 1153 | * Get packets from the connection input buffer, and process them as long as |
1439 | * there are packets available. | 1154 | * there are packets available. |
@@ -1449,7 +1164,7 @@ client_process_output(fd_set *writeset) | |||
1449 | static void | 1164 | static void |
1450 | client_process_buffered_input_packets(void) | 1165 | client_process_buffered_input_packets(void) |
1451 | { | 1166 | { |
1452 | dispatch_run(DISPATCH_NONBLOCK, &quit_pending, active_state); | 1167 | ssh_dispatch_run_fatal(active_state, DISPATCH_NONBLOCK, &quit_pending); |
1453 | } | 1168 | } |
1454 | 1169 | ||
1455 | /* scan buf[] for '~' before sending data to the peer */ | 1170 | /* scan buf[] for '~' before sending data to the peer */ |
@@ -1468,25 +1183,25 @@ client_new_escape_filter_ctx(int escape_char) | |||
1468 | 1183 | ||
1469 | /* Free the escape filter context on channel free */ | 1184 | /* Free the escape filter context on channel free */ |
1470 | void | 1185 | void |
1471 | client_filter_cleanup(int cid, void *ctx) | 1186 | client_filter_cleanup(struct ssh *ssh, int cid, void *ctx) |
1472 | { | 1187 | { |
1473 | free(ctx); | 1188 | free(ctx); |
1474 | } | 1189 | } |
1475 | 1190 | ||
1476 | int | 1191 | int |
1477 | client_simple_escape_filter(Channel *c, char *buf, int len) | 1192 | client_simple_escape_filter(struct ssh *ssh, Channel *c, char *buf, int len) |
1478 | { | 1193 | { |
1479 | if (c->extended_usage != CHAN_EXTENDED_WRITE) | 1194 | if (c->extended_usage != CHAN_EXTENDED_WRITE) |
1480 | return 0; | 1195 | return 0; |
1481 | 1196 | ||
1482 | return process_escapes(c, &c->input, &c->output, &c->extended, | 1197 | return process_escapes(ssh, c, c->input, c->output, c->extended, |
1483 | buf, len); | 1198 | buf, len); |
1484 | } | 1199 | } |
1485 | 1200 | ||
1486 | static void | 1201 | static void |
1487 | client_channel_closed(int id, void *arg) | 1202 | client_channel_closed(struct ssh *ssh, int id, void *arg) |
1488 | { | 1203 | { |
1489 | channel_cancel_cleanup(id); | 1204 | channel_cancel_cleanup(ssh, id); |
1490 | session_closed = 1; | 1205 | session_closed = 1; |
1491 | leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); | 1206 | leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); |
1492 | } | 1207 | } |
@@ -1497,9 +1212,9 @@ client_channel_closed(int id, void *arg) | |||
1497 | * remote host. If escape_char != SSH_ESCAPECHAR_NONE, it is the character | 1212 | * remote host. If escape_char != SSH_ESCAPECHAR_NONE, it is the character |
1498 | * used as an escape character for terminating or suspending the session. | 1213 | * used as an escape character for terminating or suspending the session. |
1499 | */ | 1214 | */ |
1500 | |||
1501 | int | 1215 | int |
1502 | client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | 1216 | client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, |
1217 | int ssh2_chan_id) | ||
1503 | { | 1218 | { |
1504 | fd_set *readset = NULL, *writeset = NULL; | 1219 | fd_set *readset = NULL, *writeset = NULL; |
1505 | double start_time, total_time; | 1220 | double start_time, total_time; |
@@ -1537,40 +1252,22 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1537 | 1252 | ||
1538 | } else { | 1253 | } else { |
1539 | debug("pledge: network"); | 1254 | debug("pledge: network"); |
1540 | if (pledge("stdio unix inet dns tty", NULL) == -1) | 1255 | if (pledge("stdio unix inet dns proc tty", NULL) == -1) |
1541 | fatal("%s pledge(): %s", __func__, strerror(errno)); | 1256 | fatal("%s pledge(): %s", __func__, strerror(errno)); |
1542 | } | 1257 | } |
1543 | 1258 | ||
1544 | start_time = get_current_time(); | 1259 | start_time = get_current_time(); |
1545 | 1260 | ||
1546 | /* Initialize variables. */ | 1261 | /* Initialize variables. */ |
1547 | escape_pending1 = 0; | ||
1548 | last_was_cr = 1; | 1262 | last_was_cr = 1; |
1549 | exit_status = -1; | 1263 | exit_status = -1; |
1550 | stdin_eof = 0; | ||
1551 | buffer_high = 64 * 1024; | ||
1552 | connection_in = packet_get_connection_in(); | 1264 | connection_in = packet_get_connection_in(); |
1553 | connection_out = packet_get_connection_out(); | 1265 | connection_out = packet_get_connection_out(); |
1554 | max_fd = MAXIMUM(connection_in, connection_out); | 1266 | max_fd = MAXIMUM(connection_in, connection_out); |
1555 | 1267 | ||
1556 | if (!compat20) { | ||
1557 | /* enable nonblocking unless tty */ | ||
1558 | if (!isatty(fileno(stdin))) | ||
1559 | set_nonblock(fileno(stdin)); | ||
1560 | if (!isatty(fileno(stdout))) | ||
1561 | set_nonblock(fileno(stdout)); | ||
1562 | if (!isatty(fileno(stderr))) | ||
1563 | set_nonblock(fileno(stderr)); | ||
1564 | max_fd = MAXIMUM(max_fd, fileno(stdin)); | ||
1565 | max_fd = MAXIMUM(max_fd, fileno(stdout)); | ||
1566 | max_fd = MAXIMUM(max_fd, fileno(stderr)); | ||
1567 | } | ||
1568 | quit_pending = 0; | 1268 | quit_pending = 0; |
1569 | escape_char1 = escape_char_arg; | ||
1570 | 1269 | ||
1571 | /* Initialize buffers. */ | 1270 | /* Initialize buffers. */ |
1572 | buffer_init(&stdin_buffer); | ||
1573 | buffer_init(&stdout_buffer); | ||
1574 | buffer_init(&stderr_buffer); | 1271 | buffer_init(&stderr_buffer); |
1575 | 1272 | ||
1576 | client_init_dispatch(); | 1273 | client_init_dispatch(); |
@@ -1592,22 +1289,17 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1592 | if (have_pty) | 1289 | if (have_pty) |
1593 | enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE); | 1290 | enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE); |
1594 | 1291 | ||
1595 | if (compat20) { | 1292 | session_ident = ssh2_chan_id; |
1596 | session_ident = ssh2_chan_id; | 1293 | if (session_ident != -1) { |
1597 | if (session_ident != -1) { | 1294 | if (escape_char_arg != SSH_ESCAPECHAR_NONE) { |
1598 | if (escape_char_arg != SSH_ESCAPECHAR_NONE) { | 1295 | channel_register_filter(ssh, session_ident, |
1599 | channel_register_filter(session_ident, | 1296 | client_simple_escape_filter, NULL, |
1600 | client_simple_escape_filter, NULL, | 1297 | client_filter_cleanup, |
1601 | client_filter_cleanup, | 1298 | client_new_escape_filter_ctx( |
1602 | client_new_escape_filter_ctx( | 1299 | escape_char_arg)); |
1603 | escape_char_arg)); | ||
1604 | } | ||
1605 | channel_register_cleanup(session_ident, | ||
1606 | client_channel_closed, 0); | ||
1607 | } | 1300 | } |
1608 | } else { | 1301 | channel_register_cleanup(ssh, session_ident, |
1609 | /* Check if we should immediately send eof on stdin. */ | 1302 | client_channel_closed, 0); |
1610 | client_check_initial_eof_on_stdin(); | ||
1611 | } | 1303 | } |
1612 | 1304 | ||
1613 | /* Main loop of the client for the interactive session mode. */ | 1305 | /* Main loop of the client for the interactive session mode. */ |
@@ -1616,38 +1308,31 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1616 | /* Process buffered packets sent by the server. */ | 1308 | /* Process buffered packets sent by the server. */ |
1617 | client_process_buffered_input_packets(); | 1309 | client_process_buffered_input_packets(); |
1618 | 1310 | ||
1619 | if (compat20 && session_closed && !channel_still_open()) | 1311 | if (session_closed && !channel_still_open(ssh)) |
1620 | break; | 1312 | break; |
1621 | 1313 | ||
1622 | if (ssh_packet_is_rekeying(active_state)) { | 1314 | if (ssh_packet_is_rekeying(ssh)) { |
1623 | debug("rekeying in progress"); | 1315 | debug("rekeying in progress"); |
1624 | } else if (need_rekeying) { | 1316 | } else if (need_rekeying) { |
1625 | /* manual rekey request */ | 1317 | /* manual rekey request */ |
1626 | debug("need rekeying"); | 1318 | debug("need rekeying"); |
1627 | if ((r = kex_start_rekex(active_state)) != 0) | 1319 | if ((r = kex_start_rekex(ssh)) != 0) |
1628 | fatal("%s: kex_start_rekex: %s", __func__, | 1320 | fatal("%s: kex_start_rekex: %s", __func__, |
1629 | ssh_err(r)); | 1321 | ssh_err(r)); |
1630 | need_rekeying = 0; | 1322 | need_rekeying = 0; |
1631 | } else { | 1323 | } else { |
1632 | /* | 1324 | /* |
1633 | * Make packets of buffered stdin data, and buffer | ||
1634 | * them for sending to the server. | ||
1635 | */ | ||
1636 | if (!compat20) | ||
1637 | client_make_packets_from_stdin_data(); | ||
1638 | |||
1639 | /* | ||
1640 | * Make packets from buffered channel data, and | 1325 | * Make packets from buffered channel data, and |
1641 | * enqueue them for sending to the server. | 1326 | * enqueue them for sending to the server. |
1642 | */ | 1327 | */ |
1643 | if (packet_not_very_much_data_to_write()) | 1328 | if (packet_not_very_much_data_to_write()) |
1644 | channel_output_poll(); | 1329 | channel_output_poll(ssh); |
1645 | 1330 | ||
1646 | /* | 1331 | /* |
1647 | * Check if the window size has changed, and buffer a | 1332 | * Check if the window size has changed, and buffer a |
1648 | * message about it to the server if so. | 1333 | * message about it to the server if so. |
1649 | */ | 1334 | */ |
1650 | client_check_window_change(); | 1335 | client_check_window_change(ssh); |
1651 | 1336 | ||
1652 | if (quit_pending) | 1337 | if (quit_pending) |
1653 | break; | 1338 | break; |
@@ -1657,15 +1342,15 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1657 | * available on one of the descriptors). | 1342 | * available on one of the descriptors). |
1658 | */ | 1343 | */ |
1659 | max_fd2 = max_fd; | 1344 | max_fd2 = max_fd; |
1660 | client_wait_until_can_do_something(&readset, &writeset, | 1345 | client_wait_until_can_do_something(ssh, &readset, &writeset, |
1661 | &max_fd2, &nalloc, ssh_packet_is_rekeying(active_state)); | 1346 | &max_fd2, &nalloc, ssh_packet_is_rekeying(ssh)); |
1662 | 1347 | ||
1663 | if (quit_pending) | 1348 | if (quit_pending) |
1664 | break; | 1349 | break; |
1665 | 1350 | ||
1666 | /* Do channel operations unless rekeying in progress. */ | 1351 | /* Do channel operations unless rekeying in progress. */ |
1667 | if (!ssh_packet_is_rekeying(active_state)) | 1352 | if (!ssh_packet_is_rekeying(ssh)) |
1668 | channel_after_select(readset, writeset); | 1353 | channel_after_select(ssh, readset, writeset); |
1669 | 1354 | ||
1670 | /* Buffer input from the connection. */ | 1355 | /* Buffer input from the connection. */ |
1671 | client_process_net_input(readset); | 1356 | client_process_net_input(readset); |
@@ -1673,16 +1358,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1673 | if (quit_pending) | 1358 | if (quit_pending) |
1674 | break; | 1359 | break; |
1675 | 1360 | ||
1676 | if (!compat20) { | ||
1677 | /* Buffer data from stdin */ | ||
1678 | client_process_input(readset); | ||
1679 | /* | ||
1680 | * Process output to stdout and stderr. Output to | ||
1681 | * the connection is processed elsewhere (above). | ||
1682 | */ | ||
1683 | client_process_output(writeset); | ||
1684 | } | ||
1685 | |||
1686 | /* | 1361 | /* |
1687 | * Send as much buffered packet data as possible to the | 1362 | * Send as much buffered packet data as possible to the |
1688 | * sender. | 1363 | * sender. |
@@ -1710,16 +1385,14 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1710 | /* Stop watching for window change. */ | 1385 | /* Stop watching for window change. */ |
1711 | signal(SIGWINCH, SIG_DFL); | 1386 | signal(SIGWINCH, SIG_DFL); |
1712 | 1387 | ||
1713 | if (compat20) { | 1388 | packet_start(SSH2_MSG_DISCONNECT); |
1714 | packet_start(SSH2_MSG_DISCONNECT); | 1389 | packet_put_int(SSH2_DISCONNECT_BY_APPLICATION); |
1715 | packet_put_int(SSH2_DISCONNECT_BY_APPLICATION); | 1390 | packet_put_cstring("disconnected by user"); |
1716 | packet_put_cstring("disconnected by user"); | 1391 | packet_put_cstring(""); /* language tag */ |
1717 | packet_put_cstring(""); /* language tag */ | 1392 | packet_send(); |
1718 | packet_send(); | 1393 | packet_write_wait(); |
1719 | packet_write_wait(); | ||
1720 | } | ||
1721 | 1394 | ||
1722 | channel_free_all(); | 1395 | channel_free_all(ssh); |
1723 | 1396 | ||
1724 | if (have_pty) | 1397 | if (have_pty) |
1725 | leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); | 1398 | leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); |
@@ -1742,8 +1415,10 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1742 | exit_status = 0; | 1415 | exit_status = 0; |
1743 | } | 1416 | } |
1744 | 1417 | ||
1745 | if (received_signal) | 1418 | if (received_signal) { |
1746 | fatal("Killed by signal %d.", (int) received_signal); | 1419 | verbose("Killed by signal %d.", (int) received_signal); |
1420 | cleanup_exit(0); | ||
1421 | } | ||
1747 | 1422 | ||
1748 | /* | 1423 | /* |
1749 | * In interactive mode (with pseudo tty) display a message indicating | 1424 | * In interactive mode (with pseudo tty) display a message indicating |
@@ -1755,16 +1430,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1755 | buffer_append(&stderr_buffer, buf, strlen(buf)); | 1430 | buffer_append(&stderr_buffer, buf, strlen(buf)); |
1756 | } | 1431 | } |
1757 | 1432 | ||
1758 | /* Output any buffered data for stdout. */ | ||
1759 | if (buffer_len(&stdout_buffer) > 0) { | ||
1760 | len = atomicio(vwrite, fileno(stdout), | ||
1761 | buffer_ptr(&stdout_buffer), buffer_len(&stdout_buffer)); | ||
1762 | if (len < 0 || (u_int)len != buffer_len(&stdout_buffer)) | ||
1763 | error("Write failed flushing stdout buffer."); | ||
1764 | else | ||
1765 | buffer_consume(&stdout_buffer, len); | ||
1766 | } | ||
1767 | |||
1768 | /* Output any buffered data for stderr. */ | 1433 | /* Output any buffered data for stderr. */ |
1769 | if (buffer_len(&stderr_buffer) > 0) { | 1434 | if (buffer_len(&stderr_buffer) > 0) { |
1770 | len = atomicio(vwrite, fileno(stderr), | 1435 | len = atomicio(vwrite, fileno(stderr), |
@@ -1777,8 +1442,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1777 | 1442 | ||
1778 | /* Clear and free any buffers. */ | 1443 | /* Clear and free any buffers. */ |
1779 | explicit_bzero(buf, sizeof(buf)); | 1444 | explicit_bzero(buf, sizeof(buf)); |
1780 | buffer_free(&stdin_buffer); | ||
1781 | buffer_free(&stdout_buffer); | ||
1782 | buffer_free(&stderr_buffer); | 1445 | buffer_free(&stderr_buffer); |
1783 | 1446 | ||
1784 | /* Report bytes transferred, and transfer rates. */ | 1447 | /* Report bytes transferred, and transfer rates. */ |
@@ -1796,95 +1459,9 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1796 | 1459 | ||
1797 | /*********/ | 1460 | /*********/ |
1798 | 1461 | ||
1799 | static int | ||
1800 | client_input_stdout_data(int type, u_int32_t seq, void *ctxt) | ||
1801 | { | ||
1802 | u_int data_len; | ||
1803 | char *data = packet_get_string(&data_len); | ||
1804 | packet_check_eom(); | ||
1805 | buffer_append(&stdout_buffer, data, data_len); | ||
1806 | explicit_bzero(data, data_len); | ||
1807 | free(data); | ||
1808 | return 0; | ||
1809 | } | ||
1810 | static int | ||
1811 | client_input_stderr_data(int type, u_int32_t seq, void *ctxt) | ||
1812 | { | ||
1813 | u_int data_len; | ||
1814 | char *data = packet_get_string(&data_len); | ||
1815 | packet_check_eom(); | ||
1816 | buffer_append(&stderr_buffer, data, data_len); | ||
1817 | explicit_bzero(data, data_len); | ||
1818 | free(data); | ||
1819 | return 0; | ||
1820 | } | ||
1821 | static int | ||
1822 | client_input_exit_status(int type, u_int32_t seq, void *ctxt) | ||
1823 | { | ||
1824 | exit_status = packet_get_int(); | ||
1825 | packet_check_eom(); | ||
1826 | /* Acknowledge the exit. */ | ||
1827 | packet_start(SSH_CMSG_EXIT_CONFIRMATION); | ||
1828 | packet_send(); | ||
1829 | /* | ||
1830 | * Must wait for packet to be sent since we are | ||
1831 | * exiting the loop. | ||
1832 | */ | ||
1833 | packet_write_wait(); | ||
1834 | /* Flag that we want to exit. */ | ||
1835 | quit_pending = 1; | ||
1836 | return 0; | ||
1837 | } | ||
1838 | |||
1839 | static int | ||
1840 | client_input_agent_open(int type, u_int32_t seq, void *ctxt) | ||
1841 | { | ||
1842 | Channel *c = NULL; | ||
1843 | int r, remote_id, sock; | ||
1844 | |||
1845 | /* Read the remote channel number from the message. */ | ||
1846 | remote_id = packet_get_int(); | ||
1847 | packet_check_eom(); | ||
1848 | |||
1849 | /* | ||
1850 | * Get a connection to the local authentication agent (this may again | ||
1851 | * get forwarded). | ||
1852 | */ | ||
1853 | if ((r = ssh_get_authentication_socket(&sock)) != 0 && | ||
1854 | r != SSH_ERR_AGENT_NOT_PRESENT) | ||
1855 | debug("%s: ssh_get_authentication_socket: %s", | ||
1856 | __func__, ssh_err(r)); | ||
1857 | |||
1858 | |||
1859 | /* | ||
1860 | * If we could not connect the agent, send an error message back to | ||
1861 | * the server. This should never happen unless the agent dies, | ||
1862 | * because authentication forwarding is only enabled if we have an | ||
1863 | * agent. | ||
1864 | */ | ||
1865 | if (sock >= 0) { | ||
1866 | c = channel_new("", SSH_CHANNEL_OPEN, sock, sock, | ||
1867 | -1, 0, 0, 0, "authentication agent connection", 1); | ||
1868 | c->remote_id = remote_id; | ||
1869 | c->force_drain = 1; | ||
1870 | } | ||
1871 | if (c == NULL) { | ||
1872 | packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); | ||
1873 | packet_put_int(remote_id); | ||
1874 | } else { | ||
1875 | /* Send a confirmation to the remote host. */ | ||
1876 | debug("Forwarding authentication connection."); | ||
1877 | packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION); | ||
1878 | packet_put_int(remote_id); | ||
1879 | packet_put_int(c->self); | ||
1880 | } | ||
1881 | packet_send(); | ||
1882 | return 0; | ||
1883 | } | ||
1884 | |||
1885 | static Channel * | 1462 | static Channel * |
1886 | client_request_forwarded_tcpip(const char *request_type, int rchan, | 1463 | client_request_forwarded_tcpip(struct ssh *ssh, const char *request_type, |
1887 | u_int rwindow, u_int rmaxpack) | 1464 | int rchan, u_int rwindow, u_int rmaxpack) |
1888 | { | 1465 | { |
1889 | Channel *c = NULL; | 1466 | Channel *c = NULL; |
1890 | struct sshbuf *b = NULL; | 1467 | struct sshbuf *b = NULL; |
@@ -1902,7 +1479,7 @@ client_request_forwarded_tcpip(const char *request_type, int rchan, | |||
1902 | debug("%s: listen %s port %d, originator %s port %d", __func__, | 1479 | debug("%s: listen %s port %d, originator %s port %d", __func__, |
1903 | listen_address, listen_port, originator_address, originator_port); | 1480 | listen_address, listen_port, originator_address, originator_port); |
1904 | 1481 | ||
1905 | c = channel_connect_by_listen_address(listen_address, listen_port, | 1482 | c = channel_connect_by_listen_address(ssh, listen_address, listen_port, |
1906 | "forwarded-tcpip", originator_address); | 1483 | "forwarded-tcpip", originator_address); |
1907 | 1484 | ||
1908 | if (c != NULL && c->type == SSH_CHANNEL_MUX_CLIENT) { | 1485 | if (c != NULL && c->type == SSH_CHANNEL_MUX_CLIENT) { |
@@ -1921,7 +1498,7 @@ client_request_forwarded_tcpip(const char *request_type, int rchan, | |||
1921 | (r = sshbuf_put_u32(b, listen_port)) != 0 || | 1498 | (r = sshbuf_put_u32(b, listen_port)) != 0 || |
1922 | (r = sshbuf_put_cstring(b, originator_address)) != 0 || | 1499 | (r = sshbuf_put_cstring(b, originator_address)) != 0 || |
1923 | (r = sshbuf_put_u32(b, originator_port)) != 0 || | 1500 | (r = sshbuf_put_u32(b, originator_port)) != 0 || |
1924 | (r = sshbuf_put_stringb(&c->output, b)) != 0) { | 1501 | (r = sshbuf_put_stringb(c->output, b)) != 0) { |
1925 | error("%s: compose for muxclient %s", __func__, | 1502 | error("%s: compose for muxclient %s", __func__, |
1926 | ssh_err(r)); | 1503 | ssh_err(r)); |
1927 | goto out; | 1504 | goto out; |
@@ -1936,7 +1513,8 @@ client_request_forwarded_tcpip(const char *request_type, int rchan, | |||
1936 | } | 1513 | } |
1937 | 1514 | ||
1938 | static Channel * | 1515 | static Channel * |
1939 | client_request_forwarded_streamlocal(const char *request_type, int rchan) | 1516 | client_request_forwarded_streamlocal(struct ssh *ssh, |
1517 | const char *request_type, int rchan) | ||
1940 | { | 1518 | { |
1941 | Channel *c = NULL; | 1519 | Channel *c = NULL; |
1942 | char *listen_path; | 1520 | char *listen_path; |
@@ -1950,14 +1528,14 @@ client_request_forwarded_streamlocal(const char *request_type, int rchan) | |||
1950 | 1528 | ||
1951 | debug("%s: %s", __func__, listen_path); | 1529 | debug("%s: %s", __func__, listen_path); |
1952 | 1530 | ||
1953 | c = channel_connect_by_listen_path(listen_path, | 1531 | c = channel_connect_by_listen_path(ssh, listen_path, |
1954 | "forwarded-streamlocal@openssh.com", "forwarded-streamlocal"); | 1532 | "forwarded-streamlocal@openssh.com", "forwarded-streamlocal"); |
1955 | free(listen_path); | 1533 | free(listen_path); |
1956 | return c; | 1534 | return c; |
1957 | } | 1535 | } |
1958 | 1536 | ||
1959 | static Channel * | 1537 | static Channel * |
1960 | client_request_x11(const char *request_type, int rchan) | 1538 | client_request_x11(struct ssh *ssh, const char *request_type, int rchan) |
1961 | { | 1539 | { |
1962 | Channel *c = NULL; | 1540 | Channel *c = NULL; |
1963 | char *originator; | 1541 | char *originator; |
@@ -1987,10 +1565,10 @@ client_request_x11(const char *request_type, int rchan) | |||
1987 | debug("client_request_x11: request from %s %d", originator, | 1565 | debug("client_request_x11: request from %s %d", originator, |
1988 | originator_port); | 1566 | originator_port); |
1989 | free(originator); | 1567 | free(originator); |
1990 | sock = x11_connect_display(); | 1568 | sock = x11_connect_display(ssh); |
1991 | if (sock < 0) | 1569 | if (sock < 0) |
1992 | return NULL; | 1570 | return NULL; |
1993 | c = channel_new("x11", | 1571 | c = channel_new(ssh, "x11", |
1994 | SSH_CHANNEL_X11_OPEN, sock, sock, -1, | 1572 | SSH_CHANNEL_X11_OPEN, sock, sock, -1, |
1995 | CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1); | 1573 | CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1); |
1996 | c->force_drain = 1; | 1574 | c->force_drain = 1; |
@@ -1998,7 +1576,7 @@ client_request_x11(const char *request_type, int rchan) | |||
1998 | } | 1576 | } |
1999 | 1577 | ||
2000 | static Channel * | 1578 | static Channel * |
2001 | client_request_agent(const char *request_type, int rchan) | 1579 | client_request_agent(struct ssh *ssh, const char *request_type, int rchan) |
2002 | { | 1580 | { |
2003 | Channel *c = NULL; | 1581 | Channel *c = NULL; |
2004 | int r, sock; | 1582 | int r, sock; |
@@ -2015,7 +1593,7 @@ client_request_agent(const char *request_type, int rchan) | |||
2015 | __func__, ssh_err(r)); | 1593 | __func__, ssh_err(r)); |
2016 | return NULL; | 1594 | return NULL; |
2017 | } | 1595 | } |
2018 | c = channel_new("authentication agent connection", | 1596 | c = channel_new(ssh, "authentication agent connection", |
2019 | SSH_CHANNEL_OPEN, sock, sock, -1, | 1597 | SSH_CHANNEL_OPEN, sock, sock, -1, |
2020 | CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, | 1598 | CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, |
2021 | "authentication agent connection", 1); | 1599 | "authentication agent connection", 1); |
@@ -2024,7 +1602,8 @@ client_request_agent(const char *request_type, int rchan) | |||
2024 | } | 1602 | } |
2025 | 1603 | ||
2026 | int | 1604 | int |
2027 | client_request_tun_fwd(int tun_mode, int local_tun, int remote_tun) | 1605 | client_request_tun_fwd(struct ssh *ssh, int tun_mode, |
1606 | int local_tun, int remote_tun) | ||
2028 | { | 1607 | { |
2029 | Channel *c; | 1608 | Channel *c; |
2030 | int fd; | 1609 | int fd; |
@@ -2032,11 +1611,6 @@ client_request_tun_fwd(int tun_mode, int local_tun, int remote_tun) | |||
2032 | if (tun_mode == SSH_TUNMODE_NO) | 1611 | if (tun_mode == SSH_TUNMODE_NO) |
2033 | return 0; | 1612 | return 0; |
2034 | 1613 | ||
2035 | if (!compat20) { | ||
2036 | error("Tunnel forwarding is not supported for protocol 1"); | ||
2037 | return -1; | ||
2038 | } | ||
2039 | |||
2040 | debug("Requesting tun unit %d in mode %d", local_tun, tun_mode); | 1614 | debug("Requesting tun unit %d in mode %d", local_tun, tun_mode); |
2041 | 1615 | ||
2042 | /* Open local tunnel device */ | 1616 | /* Open local tunnel device */ |
@@ -2045,13 +1619,13 @@ client_request_tun_fwd(int tun_mode, int local_tun, int remote_tun) | |||
2045 | return -1; | 1619 | return -1; |
2046 | } | 1620 | } |
2047 | 1621 | ||
2048 | c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1, | 1622 | c = channel_new(ssh, "tun", SSH_CHANNEL_OPENING, fd, fd, -1, |
2049 | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); | 1623 | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); |
2050 | c->datagram = 1; | 1624 | c->datagram = 1; |
2051 | 1625 | ||
2052 | #if defined(SSH_TUN_FILTER) | 1626 | #if defined(SSH_TUN_FILTER) |
2053 | if (options.tun_open == SSH_TUNMODE_POINTOPOINT) | 1627 | if (options.tun_open == SSH_TUNMODE_POINTOPOINT) |
2054 | channel_register_filter(c->self, sys_tun_infilter, | 1628 | channel_register_filter(ssh, c->self, sys_tun_infilter, |
2055 | sys_tun_outfilter, NULL, NULL); | 1629 | sys_tun_outfilter, NULL, NULL); |
2056 | #endif | 1630 | #endif |
2057 | 1631 | ||
@@ -2069,7 +1643,7 @@ client_request_tun_fwd(int tun_mode, int local_tun, int remote_tun) | |||
2069 | 1643 | ||
2070 | /* XXXX move to generic input handler */ | 1644 | /* XXXX move to generic input handler */ |
2071 | static int | 1645 | static int |
2072 | client_input_channel_open(int type, u_int32_t seq, void *ctxt) | 1646 | client_input_channel_open(int type, u_int32_t seq, struct ssh *ssh) |
2073 | { | 1647 | { |
2074 | Channel *c = NULL; | 1648 | Channel *c = NULL; |
2075 | char *ctype; | 1649 | char *ctype; |
@@ -2085,20 +1659,21 @@ client_input_channel_open(int type, u_int32_t seq, void *ctxt) | |||
2085 | ctype, rchan, rwindow, rmaxpack); | 1659 | ctype, rchan, rwindow, rmaxpack); |
2086 | 1660 | ||
2087 | if (strcmp(ctype, "forwarded-tcpip") == 0) { | 1661 | if (strcmp(ctype, "forwarded-tcpip") == 0) { |
2088 | c = client_request_forwarded_tcpip(ctype, rchan, rwindow, | 1662 | c = client_request_forwarded_tcpip(ssh, ctype, rchan, rwindow, |
2089 | rmaxpack); | 1663 | rmaxpack); |
2090 | } else if (strcmp(ctype, "forwarded-streamlocal@openssh.com") == 0) { | 1664 | } else if (strcmp(ctype, "forwarded-streamlocal@openssh.com") == 0) { |
2091 | c = client_request_forwarded_streamlocal(ctype, rchan); | 1665 | c = client_request_forwarded_streamlocal(ssh, ctype, rchan); |
2092 | } else if (strcmp(ctype, "x11") == 0) { | 1666 | } else if (strcmp(ctype, "x11") == 0) { |
2093 | c = client_request_x11(ctype, rchan); | 1667 | c = client_request_x11(ssh, ctype, rchan); |
2094 | } else if (strcmp(ctype, "auth-agent@openssh.com") == 0) { | 1668 | } else if (strcmp(ctype, "auth-agent@openssh.com") == 0) { |
2095 | c = client_request_agent(ctype, rchan); | 1669 | c = client_request_agent(ssh, ctype, rchan); |
2096 | } | 1670 | } |
2097 | if (c != NULL && c->type == SSH_CHANNEL_MUX_CLIENT) { | 1671 | if (c != NULL && c->type == SSH_CHANNEL_MUX_CLIENT) { |
2098 | debug3("proxied to downstream: %s", ctype); | 1672 | debug3("proxied to downstream: %s", ctype); |
2099 | } else if (c != NULL) { | 1673 | } else if (c != NULL) { |
2100 | debug("confirm %s", ctype); | 1674 | debug("confirm %s", ctype); |
2101 | c->remote_id = rchan; | 1675 | c->remote_id = rchan; |
1676 | c->have_remote_id = 1; | ||
2102 | c->remote_window = rwindow; | 1677 | c->remote_window = rwindow; |
2103 | c->remote_maxpacket = rmaxpack; | 1678 | c->remote_maxpacket = rmaxpack; |
2104 | if (c->type != SSH_CHANNEL_CONNECTING) { | 1679 | if (c->type != SSH_CHANNEL_CONNECTING) { |
@@ -2125,15 +1700,15 @@ client_input_channel_open(int type, u_int32_t seq, void *ctxt) | |||
2125 | } | 1700 | } |
2126 | 1701 | ||
2127 | static int | 1702 | static int |
2128 | client_input_channel_req(int type, u_int32_t seq, void *ctxt) | 1703 | client_input_channel_req(int type, u_int32_t seq, struct ssh *ssh) |
2129 | { | 1704 | { |
2130 | Channel *c = NULL; | 1705 | Channel *c = NULL; |
2131 | int exitval, id, reply, success = 0; | 1706 | int exitval, id, reply, success = 0; |
2132 | char *rtype; | 1707 | char *rtype; |
2133 | 1708 | ||
2134 | id = packet_get_int(); | 1709 | id = packet_get_int(); |
2135 | c = channel_lookup(id); | 1710 | c = channel_lookup(ssh, id); |
2136 | if (channel_proxy_upstream(c, type, seq, ctxt)) | 1711 | if (channel_proxy_upstream(c, type, seq, ssh)) |
2137 | return 0; | 1712 | return 0; |
2138 | rtype = packet_get_string(NULL); | 1713 | rtype = packet_get_string(NULL); |
2139 | reply = packet_get_char(); | 1714 | reply = packet_get_char(); |
@@ -2148,11 +1723,11 @@ client_input_channel_req(int type, u_int32_t seq, void *ctxt) | |||
2148 | "unknown channel", id); | 1723 | "unknown channel", id); |
2149 | } else if (strcmp(rtype, "eow@openssh.com") == 0) { | 1724 | } else if (strcmp(rtype, "eow@openssh.com") == 0) { |
2150 | packet_check_eom(); | 1725 | packet_check_eom(); |
2151 | chan_rcvd_eow(c); | 1726 | chan_rcvd_eow(ssh, c); |
2152 | } else if (strcmp(rtype, "exit-status") == 0) { | 1727 | } else if (strcmp(rtype, "exit-status") == 0) { |
2153 | exitval = packet_get_int(); | 1728 | exitval = packet_get_int(); |
2154 | if (c->ctl_chan != -1) { | 1729 | if (c->ctl_chan != -1) { |
2155 | mux_exit_message(c, exitval); | 1730 | mux_exit_message(ssh, c, exitval); |
2156 | success = 1; | 1731 | success = 1; |
2157 | } else if (id == session_ident) { | 1732 | } else if (id == session_ident) { |
2158 | /* Record exit value of local session */ | 1733 | /* Record exit value of local session */ |
@@ -2166,6 +1741,9 @@ client_input_channel_req(int type, u_int32_t seq, void *ctxt) | |||
2166 | packet_check_eom(); | 1741 | packet_check_eom(); |
2167 | } | 1742 | } |
2168 | if (reply && c != NULL && !(c->flags & CHAN_CLOSE_SENT)) { | 1743 | if (reply && c != NULL && !(c->flags & CHAN_CLOSE_SENT)) { |
1744 | if (!c->have_remote_id) | ||
1745 | fatal("%s: channel %d: no remote_id", | ||
1746 | __func__, c->self); | ||
2169 | packet_start(success ? | 1747 | packet_start(success ? |
2170 | SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); | 1748 | SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); |
2171 | packet_put_int(c->remote_id); | 1749 | packet_put_int(c->remote_id); |
@@ -2187,9 +1765,7 @@ struct hostkeys_update_ctx { | |||
2187 | */ | 1765 | */ |
2188 | struct sshkey **keys; | 1766 | struct sshkey **keys; |
2189 | int *keys_seen; | 1767 | int *keys_seen; |
2190 | size_t nkeys; | 1768 | size_t nkeys, nnew; |
2191 | |||
2192 | size_t nnew; | ||
2193 | 1769 | ||
2194 | /* | 1770 | /* |
2195 | * Keys that are in known_hosts, but were not present in the update | 1771 | * Keys that are in known_hosts, but were not present in the update |
@@ -2226,8 +1802,7 @@ hostkeys_find(struct hostkey_foreach_line *l, void *_ctx) | |||
2226 | size_t i; | 1802 | size_t i; |
2227 | struct sshkey **tmp; | 1803 | struct sshkey **tmp; |
2228 | 1804 | ||
2229 | if (l->status != HKF_STATUS_MATCHED || l->key == NULL || | 1805 | if (l->status != HKF_STATUS_MATCHED || l->key == NULL) |
2230 | l->key->type == KEY_RSA1) | ||
2231 | return 0; | 1806 | return 0; |
2232 | 1807 | ||
2233 | /* Mark off keys we've already seen for this host */ | 1808 | /* Mark off keys we've already seen for this host */ |
@@ -2242,9 +1817,9 @@ hostkeys_find(struct hostkey_foreach_line *l, void *_ctx) | |||
2242 | /* This line contained a key that not offered by the server */ | 1817 | /* This line contained a key that not offered by the server */ |
2243 | debug3("%s: deprecated %s key at %s:%ld", __func__, | 1818 | debug3("%s: deprecated %s key at %s:%ld", __func__, |
2244 | sshkey_ssh_name(l->key), l->path, l->linenum); | 1819 | sshkey_ssh_name(l->key), l->path, l->linenum); |
2245 | if ((tmp = reallocarray(ctx->old_keys, ctx->nold + 1, | 1820 | if ((tmp = recallocarray(ctx->old_keys, ctx->nold, ctx->nold + 1, |
2246 | sizeof(*ctx->old_keys))) == NULL) | 1821 | sizeof(*ctx->old_keys))) == NULL) |
2247 | fatal("%s: reallocarray failed nold = %zu", | 1822 | fatal("%s: recallocarray failed nold = %zu", |
2248 | __func__, ctx->nold); | 1823 | __func__, ctx->nold); |
2249 | ctx->old_keys = tmp; | 1824 | ctx->old_keys = tmp; |
2250 | ctx->old_keys[ctx->nold++] = l->key; | 1825 | ctx->old_keys[ctx->nold++] = l->key; |
@@ -2323,9 +1898,9 @@ update_known_hosts(struct hostkeys_update_ctx *ctx) | |||
2323 | } | 1898 | } |
2324 | 1899 | ||
2325 | static void | 1900 | static void |
2326 | client_global_hostkeys_private_confirm(int type, u_int32_t seq, void *_ctx) | 1901 | client_global_hostkeys_private_confirm(struct ssh *ssh, int type, |
1902 | u_int32_t seq, void *_ctx) | ||
2327 | { | 1903 | { |
2328 | struct ssh *ssh = active_state; /* XXX */ | ||
2329 | struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx; | 1904 | struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx; |
2330 | size_t i, ndone; | 1905 | size_t i, ndone; |
2331 | struct sshbuf *signdata; | 1906 | struct sshbuf *signdata; |
@@ -2476,9 +2051,9 @@ client_input_hostkeys(void) | |||
2476 | } | 2051 | } |
2477 | } | 2052 | } |
2478 | /* Key is good, record it */ | 2053 | /* Key is good, record it */ |
2479 | if ((tmp = reallocarray(ctx->keys, ctx->nkeys + 1, | 2054 | if ((tmp = recallocarray(ctx->keys, ctx->nkeys, ctx->nkeys + 1, |
2480 | sizeof(*ctx->keys))) == NULL) | 2055 | sizeof(*ctx->keys))) == NULL) |
2481 | fatal("%s: reallocarray failed nkeys = %zu", | 2056 | fatal("%s: recallocarray failed nkeys = %zu", |
2482 | __func__, ctx->nkeys); | 2057 | __func__, ctx->nkeys); |
2483 | ctx->keys = tmp; | 2058 | ctx->keys = tmp; |
2484 | ctx->keys[ctx->nkeys++] = key; | 2059 | ctx->keys[ctx->nkeys++] = key; |
@@ -2566,7 +2141,7 @@ client_input_hostkeys(void) | |||
2566 | } | 2141 | } |
2567 | 2142 | ||
2568 | static int | 2143 | static int |
2569 | client_input_global_request(int type, u_int32_t seq, void *ctxt) | 2144 | client_input_global_request(int type, u_int32_t seq, struct ssh *ssh) |
2570 | { | 2145 | { |
2571 | char *rtype; | 2146 | char *rtype; |
2572 | int want_reply; | 2147 | int want_reply; |
@@ -2589,7 +2164,7 @@ client_input_global_request(int type, u_int32_t seq, void *ctxt) | |||
2589 | } | 2164 | } |
2590 | 2165 | ||
2591 | void | 2166 | void |
2592 | client_session2_setup(int id, int want_tty, int want_subsystem, | 2167 | client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem, |
2593 | const char *term, struct termios *tiop, int in_fd, Buffer *cmd, char **env) | 2168 | const char *term, struct termios *tiop, int in_fd, Buffer *cmd, char **env) |
2594 | { | 2169 | { |
2595 | int len; | 2170 | int len; |
@@ -2597,8 +2172,8 @@ client_session2_setup(int id, int want_tty, int want_subsystem, | |||
2597 | 2172 | ||
2598 | debug2("%s: id %d", __func__, id); | 2173 | debug2("%s: id %d", __func__, id); |
2599 | 2174 | ||
2600 | if ((c = channel_lookup(id)) == NULL) | 2175 | if ((c = channel_lookup(ssh, id)) == NULL) |
2601 | fatal("client_session2_setup: channel %d: unknown channel", id); | 2176 | fatal("%s: channel %d: unknown channel", __func__, id); |
2602 | 2177 | ||
2603 | packet_set_interactive(want_tty, | 2178 | packet_set_interactive(want_tty, |
2604 | options.ip_qos_interactive, options.ip_qos_bulk); | 2179 | options.ip_qos_interactive, options.ip_qos_bulk); |
@@ -2610,8 +2185,8 @@ client_session2_setup(int id, int want_tty, int want_subsystem, | |||
2610 | if (ioctl(in_fd, TIOCGWINSZ, &ws) < 0) | 2185 | if (ioctl(in_fd, TIOCGWINSZ, &ws) < 0) |
2611 | memset(&ws, 0, sizeof(ws)); | 2186 | memset(&ws, 0, sizeof(ws)); |
2612 | 2187 | ||
2613 | channel_request_start(id, "pty-req", 1); | 2188 | channel_request_start(ssh, id, "pty-req", 1); |
2614 | client_expect_confirm(id, "PTY allocation", CONFIRM_TTY); | 2189 | client_expect_confirm(ssh, id, "PTY allocation", CONFIRM_TTY); |
2615 | packet_put_cstring(term != NULL ? term : ""); | 2190 | packet_put_cstring(term != NULL ? term : ""); |
2616 | packet_put_int((u_int)ws.ws_col); | 2191 | packet_put_int((u_int)ws.ws_col); |
2617 | packet_put_int((u_int)ws.ws_row); | 2192 | packet_put_int((u_int)ws.ws_row); |
@@ -2654,7 +2229,7 @@ client_session2_setup(int id, int want_tty, int want_subsystem, | |||
2654 | } | 2229 | } |
2655 | 2230 | ||
2656 | debug("Sending env %s = %s", name, val); | 2231 | debug("Sending env %s = %s", name, val); |
2657 | channel_request_start(id, "env", 0); | 2232 | channel_request_start(ssh, id, "env", 0); |
2658 | packet_put_cstring(name); | 2233 | packet_put_cstring(name); |
2659 | packet_put_cstring(val); | 2234 | packet_put_cstring(val); |
2660 | packet_send(); | 2235 | packet_send(); |
@@ -2669,25 +2244,26 @@ client_session2_setup(int id, int want_tty, int want_subsystem, | |||
2669 | if (want_subsystem) { | 2244 | if (want_subsystem) { |
2670 | debug("Sending subsystem: %.*s", | 2245 | debug("Sending subsystem: %.*s", |
2671 | len, (u_char*)buffer_ptr(cmd)); | 2246 | len, (u_char*)buffer_ptr(cmd)); |
2672 | channel_request_start(id, "subsystem", 1); | 2247 | channel_request_start(ssh, id, "subsystem", 1); |
2673 | client_expect_confirm(id, "subsystem", CONFIRM_CLOSE); | 2248 | client_expect_confirm(ssh, id, "subsystem", |
2249 | CONFIRM_CLOSE); | ||
2674 | } else { | 2250 | } else { |
2675 | debug("Sending command: %.*s", | 2251 | debug("Sending command: %.*s", |
2676 | len, (u_char*)buffer_ptr(cmd)); | 2252 | len, (u_char*)buffer_ptr(cmd)); |
2677 | channel_request_start(id, "exec", 1); | 2253 | channel_request_start(ssh, id, "exec", 1); |
2678 | client_expect_confirm(id, "exec", CONFIRM_CLOSE); | 2254 | client_expect_confirm(ssh, id, "exec", CONFIRM_CLOSE); |
2679 | } | 2255 | } |
2680 | packet_put_string(buffer_ptr(cmd), buffer_len(cmd)); | 2256 | packet_put_string(buffer_ptr(cmd), buffer_len(cmd)); |
2681 | packet_send(); | 2257 | packet_send(); |
2682 | } else { | 2258 | } else { |
2683 | channel_request_start(id, "shell", 1); | 2259 | channel_request_start(ssh, id, "shell", 1); |
2684 | client_expect_confirm(id, "shell", CONFIRM_CLOSE); | 2260 | client_expect_confirm(ssh, id, "shell", CONFIRM_CLOSE); |
2685 | packet_send(); | 2261 | packet_send(); |
2686 | } | 2262 | } |
2687 | } | 2263 | } |
2688 | 2264 | ||
2689 | static void | 2265 | static void |
2690 | client_init_dispatch_20(void) | 2266 | client_init_dispatch(void) |
2691 | { | 2267 | { |
2692 | dispatch_init(&dispatch_protocol_error); | 2268 | dispatch_init(&dispatch_protocol_error); |
2693 | 2269 | ||
@@ -2712,45 +2288,6 @@ client_init_dispatch_20(void) | |||
2712 | dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &client_global_request_reply); | 2288 | dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &client_global_request_reply); |
2713 | } | 2289 | } |
2714 | 2290 | ||
2715 | static void | ||
2716 | client_init_dispatch_13(void) | ||
2717 | { | ||
2718 | dispatch_init(NULL); | ||
2719 | dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_close); | ||
2720 | dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_close_confirmation); | ||
2721 | dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data); | ||
2722 | dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation); | ||
2723 | dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure); | ||
2724 | dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open); | ||
2725 | dispatch_set(SSH_SMSG_EXITSTATUS, &client_input_exit_status); | ||
2726 | dispatch_set(SSH_SMSG_STDERR_DATA, &client_input_stderr_data); | ||
2727 | dispatch_set(SSH_SMSG_STDOUT_DATA, &client_input_stdout_data); | ||
2728 | |||
2729 | dispatch_set(SSH_SMSG_AGENT_OPEN, options.forward_agent ? | ||
2730 | &client_input_agent_open : &deny_input_open); | ||
2731 | dispatch_set(SSH_SMSG_X11_OPEN, options.forward_x11 ? | ||
2732 | &x11_input_open : &deny_input_open); | ||
2733 | } | ||
2734 | |||
2735 | static void | ||
2736 | client_init_dispatch_15(void) | ||
2737 | { | ||
2738 | client_init_dispatch_13(); | ||
2739 | dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof); | ||
2740 | dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, & channel_input_oclose); | ||
2741 | } | ||
2742 | |||
2743 | static void | ||
2744 | client_init_dispatch(void) | ||
2745 | { | ||
2746 | if (compat20) | ||
2747 | client_init_dispatch_20(); | ||
2748 | else if (compat13) | ||
2749 | client_init_dispatch_13(); | ||
2750 | else | ||
2751 | client_init_dispatch_15(); | ||
2752 | } | ||
2753 | |||
2754 | void | 2291 | void |
2755 | client_stop_mux(void) | 2292 | client_stop_mux(void) |
2756 | { | 2293 | { |