diff options
Diffstat (limited to 'clientloop.c')
-rw-r--r-- | clientloop.c | 106 |
1 files changed, 73 insertions, 33 deletions
diff --git a/clientloop.c b/clientloop.c index edd801440..c40f2c303 100644 --- a/clientloop.c +++ b/clientloop.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: clientloop.c,v 1.189 2008/05/08 12:02:23 djm Exp $ */ | 1 | /* $OpenBSD: clientloop.c,v 1.190 2008/05/08 13:06:10 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 |
@@ -173,6 +173,11 @@ struct confirm_ctx { | |||
173 | char **env; | 173 | char **env; |
174 | }; | 174 | }; |
175 | 175 | ||
176 | struct channel_reply_ctx { | ||
177 | const char *request_type; | ||
178 | int id, do_close; | ||
179 | }; | ||
180 | |||
176 | /*XXX*/ | 181 | /*XXX*/ |
177 | extern Kex *xxx_kex; | 182 | extern Kex *xxx_kex; |
178 | 183 | ||
@@ -645,25 +650,60 @@ client_process_net_input(fd_set *readset) | |||
645 | } | 650 | } |
646 | 651 | ||
647 | static void | 652 | static void |
648 | client_subsystem_reply(int type, u_int32_t seq, void *ctxt) | 653 | client_status_confirm(int type, Channel *c, void *ctx) |
649 | { | 654 | { |
650 | int id; | 655 | struct channel_reply_ctx *cr = (struct channel_reply_ctx *)ctx; |
651 | Channel *c; | 656 | char errmsg[256]; |
657 | int tochan; | ||
658 | |||
659 | /* XXX supress on mux _client_ quietmode */ | ||
660 | tochan = options.log_level >= SYSLOG_LEVEL_ERROR && | ||
661 | c->ctl_fd != -1 && c->extended_usage == CHAN_EXTENDED_WRITE; | ||
662 | |||
663 | if (type == SSH2_MSG_CHANNEL_SUCCESS) { | ||
664 | debug2("%s request accepted on channel %d", | ||
665 | cr->request_type, c->self); | ||
666 | } else if (type == SSH2_MSG_CHANNEL_FAILURE) { | ||
667 | if (tochan) { | ||
668 | snprintf(errmsg, sizeof(errmsg), | ||
669 | "%s request failed\r\n", cr->request_type); | ||
670 | } else { | ||
671 | snprintf(errmsg, sizeof(errmsg), | ||
672 | "%s request failed on channel %d", | ||
673 | cr->request_type, c->self); | ||
674 | } | ||
675 | /* If error occurred on primary session channel, then exit */ | ||
676 | if (cr->do_close && c->self == session_ident) | ||
677 | fatal("%s", errmsg); | ||
678 | /* If error occurred on mux client, append to their stderr */ | ||
679 | if (tochan) | ||
680 | buffer_append(&c->extended, errmsg, strlen(errmsg)); | ||
681 | else | ||
682 | error("%s", errmsg); | ||
683 | if (cr->do_close) { | ||
684 | chan_read_failed(c); | ||
685 | chan_write_failed(c); | ||
686 | } | ||
687 | } | ||
688 | xfree(cr); | ||
689 | } | ||
652 | 690 | ||
653 | id = packet_get_int(); | 691 | static void |
654 | packet_check_eom(); | 692 | client_abandon_status_confirm(Channel *c, void *ctx) |
693 | { | ||
694 | xfree(ctx); | ||
695 | } | ||
655 | 696 | ||
656 | if ((c = channel_lookup(id)) == NULL) { | 697 | static void |
657 | error("%s: no channel for id %d", __func__, id); | 698 | client_expect_confirm(int id, const char *request, int do_close) |
658 | return; | 699 | { |
659 | } | 700 | struct channel_reply_ctx *cr = xmalloc(sizeof(*cr)); |
660 | 701 | ||
661 | if (type == SSH2_MSG_CHANNEL_SUCCESS) | 702 | cr->request_type = request; |
662 | debug2("Request suceeded on channel %d", id); | 703 | cr->do_close = do_close; |
663 | else if (type == SSH2_MSG_CHANNEL_FAILURE) { | 704 | |
664 | error("Request failed on channel %d", id); | 705 | channel_register_status_confirm(id, client_status_confirm, |
665 | channel_free(c); | 706 | client_abandon_status_confirm, cr); |
666 | } | ||
667 | } | 707 | } |
668 | 708 | ||
669 | static void | 709 | static void |
@@ -698,8 +738,7 @@ client_extra_session2_setup(int id, void *arg) | |||
698 | } | 738 | } |
699 | 739 | ||
700 | client_session2_setup(id, cctx->want_tty, cctx->want_subsys, | 740 | client_session2_setup(id, cctx->want_tty, cctx->want_subsys, |
701 | cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env, | 741 | cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env); |
702 | client_subsystem_reply); | ||
703 | 742 | ||
704 | c->open_confirm_ctx = NULL; | 743 | c->open_confirm_ctx = NULL; |
705 | buffer_free(&cctx->cmd); | 744 | buffer_free(&cctx->cmd); |
@@ -1366,7 +1405,9 @@ client_process_buffered_input_packets(void) | |||
1366 | static int | 1405 | static int |
1367 | simple_escape_filter(Channel *c, char *buf, int len) | 1406 | simple_escape_filter(Channel *c, char *buf, int len) |
1368 | { | 1407 | { |
1369 | /* XXX we assume c->extended is writeable */ | 1408 | if (c->extended_usage != CHAN_EXTENDED_WRITE) |
1409 | return 0; | ||
1410 | |||
1370 | return process_escapes(&c->input, &c->output, &c->extended, buf, len); | 1411 | return process_escapes(&c->input, &c->output, &c->extended, buf, len); |
1371 | } | 1412 | } |
1372 | 1413 | ||
@@ -1962,8 +2003,7 @@ client_input_global_request(int type, u_int32_t seq, void *ctxt) | |||
1962 | 2003 | ||
1963 | void | 2004 | void |
1964 | client_session2_setup(int id, int want_tty, int want_subsystem, | 2005 | client_session2_setup(int id, int want_tty, int want_subsystem, |
1965 | const char *term, struct termios *tiop, int in_fd, Buffer *cmd, char **env, | 2006 | const char *term, struct termios *tiop, int in_fd, Buffer *cmd, char **env) |
1966 | dispatch_fn *subsys_repl) | ||
1967 | { | 2007 | { |
1968 | int len; | 2008 | int len; |
1969 | Channel *c = NULL; | 2009 | Channel *c = NULL; |
@@ -1981,7 +2021,8 @@ client_session2_setup(int id, int want_tty, int want_subsystem, | |||
1981 | if (ioctl(in_fd, TIOCGWINSZ, &ws) < 0) | 2021 | if (ioctl(in_fd, TIOCGWINSZ, &ws) < 0) |
1982 | memset(&ws, 0, sizeof(ws)); | 2022 | memset(&ws, 0, sizeof(ws)); |
1983 | 2023 | ||
1984 | channel_request_start(id, "pty-req", 0); | 2024 | channel_request_start(id, "pty-req", 1); |
2025 | client_expect_confirm(id, "PTY allocation", 0); | ||
1985 | packet_put_cstring(term != NULL ? term : ""); | 2026 | packet_put_cstring(term != NULL ? term : ""); |
1986 | packet_put_int((u_int)ws.ws_col); | 2027 | packet_put_int((u_int)ws.ws_col); |
1987 | packet_put_int((u_int)ws.ws_row); | 2028 | packet_put_int((u_int)ws.ws_row); |
@@ -2036,22 +2077,21 @@ client_session2_setup(int id, int want_tty, int want_subsystem, | |||
2036 | if (len > 900) | 2077 | if (len > 900) |
2037 | len = 900; | 2078 | len = 900; |
2038 | if (want_subsystem) { | 2079 | if (want_subsystem) { |
2039 | debug("Sending subsystem: %.*s", len, (u_char*)buffer_ptr(cmd)); | 2080 | debug("Sending subsystem: %.*s", |
2040 | channel_request_start(id, "subsystem", subsys_repl != NULL); | 2081 | len, (u_char*)buffer_ptr(cmd)); |
2041 | if (subsys_repl != NULL) { | 2082 | channel_request_start(id, "subsystem", 1); |
2042 | /* register callback for reply */ | 2083 | client_expect_confirm(id, "subsystem", 1); |
2043 | /* XXX we assume that client_loop has already been called */ | ||
2044 | dispatch_set(SSH2_MSG_CHANNEL_FAILURE, subsys_repl); | ||
2045 | dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, subsys_repl); | ||
2046 | } | ||
2047 | } else { | 2084 | } else { |
2048 | debug("Sending command: %.*s", len, (u_char*)buffer_ptr(cmd)); | 2085 | debug("Sending command: %.*s", |
2049 | channel_request_start(id, "exec", 0); | 2086 | len, (u_char*)buffer_ptr(cmd)); |
2087 | channel_request_start(id, "exec", 1); | ||
2088 | client_expect_confirm(id, "exec", 1); | ||
2050 | } | 2089 | } |
2051 | packet_put_string(buffer_ptr(cmd), buffer_len(cmd)); | 2090 | packet_put_string(buffer_ptr(cmd), buffer_len(cmd)); |
2052 | packet_send(); | 2091 | packet_send(); |
2053 | } else { | 2092 | } else { |
2054 | channel_request_start(id, "shell", 0); | 2093 | channel_request_start(id, "shell", 1); |
2094 | client_expect_confirm(id, "shell", 1); | ||
2055 | packet_send(); | 2095 | packet_send(); |
2056 | } | 2096 | } |
2057 | } | 2097 | } |