summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2011-05-15 08:48:05 +1000
committerDamien Miller <djm@mindrot.org>2011-05-15 08:48:05 +1000
commit555f3b856f2681b46870a66386396b49426b9719 (patch)
tree88756b47f05c76c5afd5ce739aa26a7b3f124809
parentf4b32aad05cb65caa6eabe09049750b3c8a29cf3 (diff)
- djm@cvs.openbsd.org 2011/05/08 12:52:01
[PROTOCOL.mux clientloop.c clientloop.h mux.c] improve our behaviour when TTY allocation fails: if we are in RequestTTY=auto mode (the default), then do not treat at TTY allocation error as fatal but rather just restore the local TTY to cooked mode and continue. This is more graceful on devices that never allocate TTYs. If RequestTTY is set to "yes" or "force", then failure to allocate a TTY is fatal. ok markus@
-rw-r--r--ChangeLog12
-rw-r--r--PROTOCOL.mux11
-rw-r--r--clientloop.c53
-rw-r--r--clientloop.h4
-rw-r--r--mux.c60
5 files changed, 111 insertions, 29 deletions
diff --git a/ChangeLog b/ChangeLog
index dee43400a..713798cbb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -50,6 +50,18 @@
50 - jmc@cvs.openbsd.org 2011/05/07 23:20:25 50 - jmc@cvs.openbsd.org 2011/05/07 23:20:25
51 [ssh.1] 51 [ssh.1]
52 +.It RequestTTY 52 +.It RequestTTY
53 - djm@cvs.openbsd.org 2011/05/08 12:52:01
54 [PROTOCOL.mux clientloop.c clientloop.h mux.c]
55 improve our behaviour when TTY allocation fails: if we are in
56 RequestTTY=auto mode (the default), then do not treat at TTY
57 allocation error as fatal but rather just restore the local TTY
58 to cooked mode and continue. This is more graceful on devices that
59 never allocate TTYs.
60
61 If RequestTTY is set to "yes" or "force", then failure to allocate
62 a TTY is fatal.
63
64 ok markus@
53 65
5420110510 6620110510
55 - (dtucker) [openbsd-compat/openssl-compat.{c,h}] Bug #1882: fix 67 - (dtucker) [openbsd-compat/openssl-compat.{c,h}] Bug #1882: fix
diff --git a/PROTOCOL.mux b/PROTOCOL.mux
index 3da9e37ae..9ad256602 100644
--- a/PROTOCOL.mux
+++ b/PROTOCOL.mux
@@ -73,6 +73,13 @@ non-multiplexed ssh(1) connection. Two additional cases that the
73client must cope with are it receiving a signal itself and the 73client must cope with are it receiving a signal itself and the
74server disconnecting without sending an exit message. 74server disconnecting without sending an exit message.
75 75
76A master may also send a MUX_S_TTY_ALLOC_FAIL before MUX_S_EXIT_MESSAGE
77if remote TTY allocation was unsuccessful. The client may use this to
78return its local tty to "cooked" mode.
79
80 uint32 MUX_S_TTY_ALLOC_FAIL
81 uint32 session id
82
763. Health checks 833. Health checks
77 84
78The client may request a health check/PID report from a server: 85The client may request a health check/PID report from a server:
@@ -197,6 +204,7 @@ The MUX_S_PERMISSION_DENIED and MUX_S_FAILURE include a reason:
197#define MUX_S_ALIVE 0x80000005 204#define MUX_S_ALIVE 0x80000005
198#define MUX_S_SESSION_OPENED 0x80000006 205#define MUX_S_SESSION_OPENED 0x80000006
199#define MUX_S_REMOTE_PORT 0x80000007 206#define MUX_S_REMOTE_PORT 0x80000007
207#define MUX_S_TTY_ALLOC_FAIL 0x80000008
200 208
201#define MUX_FWD_LOCAL 1 209#define MUX_FWD_LOCAL 1
202#define MUX_FWD_REMOTE 2 210#define MUX_FWD_REMOTE 2
@@ -208,7 +216,6 @@ XXX lock (maybe)
208XXX watch in/out traffic (pre/post crypto) 216XXX watch in/out traffic (pre/post crypto)
209XXX inject packet (what about replies) 217XXX inject packet (what about replies)
210XXX server->client error/warning notifications 218XXX server->client error/warning notifications
211XXX port0 rfwd (need custom response message)
212XXX send signals via mux 219XXX send signals via mux
213 220
214$OpenBSD: PROTOCOL.mux,v 1.6 2011/05/06 22:20:10 djm Exp $ 221$OpenBSD: PROTOCOL.mux,v 1.7 2011/05/08 12:52:01 djm Exp $
diff --git a/clientloop.c b/clientloop.c
index 5bd757dfb..ed1d8a238 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: clientloop.c,v 1.233 2011/05/06 21:34:32 djm Exp $ */ 1/* $OpenBSD: clientloop.c,v 1.234 2011/05/08 12:52:01 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
@@ -174,9 +174,11 @@ struct escape_filter_ctx {
174}; 174};
175 175
176/* Context for channel confirmation replies */ 176/* Context for channel confirmation replies */
177enum confirm_action { CONFIRM_WARN = 0, CONFIRM_CLOSE, CONFIRM_TTY };
177struct channel_reply_ctx { 178struct channel_reply_ctx {
178 const char *request_type; 179 const char *request_type;
179 int id, do_close; 180 int id;
181 enum confirm_action action;
180}; 182};
181 183
182/* Global request success/failure callbacks */ 184/* Global request success/failure callbacks */
@@ -739,6 +741,15 @@ client_status_confirm(int type, Channel *c, void *ctx)
739 char errmsg[256]; 741 char errmsg[256];
740 int tochan; 742 int tochan;
741 743
744 /*
745 * If a TTY was explicitly requested, then a failure to allocate
746 * one is fatal.
747 */
748 if (cr->action == CONFIRM_TTY &&
749 (options.request_tty == REQUEST_TTY_FORCE ||
750 options.request_tty == REQUEST_TTY_YES))
751 cr->action = CONFIRM_CLOSE;
752
742 /* XXX supress on mux _client_ quietmode */ 753 /* XXX supress on mux _client_ quietmode */
743 tochan = options.log_level >= SYSLOG_LEVEL_ERROR && 754 tochan = options.log_level >= SYSLOG_LEVEL_ERROR &&
744 c->ctl_chan != -1 && c->extended_usage == CHAN_EXTENDED_WRITE; 755 c->ctl_chan != -1 && c->extended_usage == CHAN_EXTENDED_WRITE;
@@ -756,14 +767,27 @@ client_status_confirm(int type, Channel *c, void *ctx)
756 cr->request_type, c->self); 767 cr->request_type, c->self);
757 } 768 }
758 /* If error occurred on primary session channel, then exit */ 769 /* If error occurred on primary session channel, then exit */
759 if (cr->do_close && c->self == session_ident) 770 if (cr->action == CONFIRM_CLOSE && c->self == session_ident)
760 fatal("%s", errmsg); 771 fatal("%s", errmsg);
761 /* If error occurred on mux client, append to their stderr */ 772 /*
762 if (tochan) 773 * If error occurred on mux client, append to
763 buffer_append(&c->extended, errmsg, strlen(errmsg)); 774 * their stderr.
764 else 775 */
776 if (tochan) {
777 buffer_append(&c->extended, errmsg,
778 strlen(errmsg));
779 } else
765 error("%s", errmsg); 780 error("%s", errmsg);
766 if (cr->do_close) { 781 if (cr->action == CONFIRM_TTY) {
782 /*
783 * If a TTY allocation error occurred, then arrange
784 * for the correct TTY to leave raw mode.
785 */
786 if (c->self == session_ident)
787 leave_raw_mode(0);
788 else
789 mux_tty_alloc_failed(c);
790 } else if (cr->action == CONFIRM_CLOSE) {
767 chan_read_failed(c); 791 chan_read_failed(c);
768 chan_write_failed(c); 792 chan_write_failed(c);
769 } 793 }
@@ -778,12 +802,13 @@ client_abandon_status_confirm(Channel *c, void *ctx)
778} 802}
779 803
780static void 804static void
781client_expect_confirm(int id, const char *request, int do_close) 805client_expect_confirm(int id, const char *request,
806 enum confirm_action action)
782{ 807{
783 struct channel_reply_ctx *cr = xmalloc(sizeof(*cr)); 808 struct channel_reply_ctx *cr = xmalloc(sizeof(*cr));
784 809
785 cr->request_type = request; 810 cr->request_type = request;
786 cr->do_close = do_close; 811 cr->action = action;
787 812
788 channel_register_status_confirm(id, client_status_confirm, 813 channel_register_status_confirm(id, client_status_confirm,
789 client_abandon_status_confirm, cr); 814 client_abandon_status_confirm, cr);
@@ -1983,7 +2008,7 @@ client_session2_setup(int id, int want_tty, int want_subsystem,
1983 memset(&ws, 0, sizeof(ws)); 2008 memset(&ws, 0, sizeof(ws));
1984 2009
1985 channel_request_start(id, "pty-req", 1); 2010 channel_request_start(id, "pty-req", 1);
1986 client_expect_confirm(id, "PTY allocation", 1); 2011 client_expect_confirm(id, "PTY allocation", CONFIRM_TTY);
1987 packet_put_cstring(term != NULL ? term : ""); 2012 packet_put_cstring(term != NULL ? term : "");
1988 packet_put_int((u_int)ws.ws_col); 2013 packet_put_int((u_int)ws.ws_col);
1989 packet_put_int((u_int)ws.ws_row); 2014 packet_put_int((u_int)ws.ws_row);
@@ -2042,18 +2067,18 @@ client_session2_setup(int id, int want_tty, int want_subsystem,
2042 debug("Sending subsystem: %.*s", 2067 debug("Sending subsystem: %.*s",
2043 len, (u_char*)buffer_ptr(cmd)); 2068 len, (u_char*)buffer_ptr(cmd));
2044 channel_request_start(id, "subsystem", 1); 2069 channel_request_start(id, "subsystem", 1);
2045 client_expect_confirm(id, "subsystem", 1); 2070 client_expect_confirm(id, "subsystem", CONFIRM_CLOSE);
2046 } else { 2071 } else {
2047 debug("Sending command: %.*s", 2072 debug("Sending command: %.*s",
2048 len, (u_char*)buffer_ptr(cmd)); 2073 len, (u_char*)buffer_ptr(cmd));
2049 channel_request_start(id, "exec", 1); 2074 channel_request_start(id, "exec", 1);
2050 client_expect_confirm(id, "exec", 1); 2075 client_expect_confirm(id, "exec", CONFIRM_CLOSE);
2051 } 2076 }
2052 packet_put_string(buffer_ptr(cmd), buffer_len(cmd)); 2077 packet_put_string(buffer_ptr(cmd), buffer_len(cmd));
2053 packet_send(); 2078 packet_send();
2054 } else { 2079 } else {
2055 channel_request_start(id, "shell", 1); 2080 channel_request_start(id, "shell", 1);
2056 client_expect_confirm(id, "shell", 1); 2081 client_expect_confirm(id, "shell", CONFIRM_CLOSE);
2057 packet_send(); 2082 packet_send();
2058 } 2083 }
2059} 2084}
diff --git a/clientloop.h b/clientloop.h
index 37d072906..ad588d14d 100644
--- a/clientloop.h
+++ b/clientloop.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: clientloop.h,v 1.26 2011/04/17 22:42:41 djm Exp $ */ 1/* $OpenBSD: clientloop.h,v 1.27 2011/05/08 12:52:01 djm Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -70,3 +70,5 @@ void client_register_global_confirm(global_confirm_cb *, void *);
70void muxserver_listen(void); 70void muxserver_listen(void);
71void muxclient(const char *); 71void muxclient(const char *);
72void mux_exit_message(Channel *, int); 72void mux_exit_message(Channel *, int);
73void mux_tty_alloc_failed(Channel *);
74
diff --git a/mux.c b/mux.c
index 1afd1bdf3..101d7524b 100644
--- a/mux.c
+++ b/mux.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: mux.c,v 1.27 2011/05/06 21:34:32 djm Exp $ */ 1/* $OpenBSD: mux.c,v 1.28 2011/05/08 12:52:01 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org> 3 * Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
4 * 4 *
@@ -153,6 +153,7 @@ struct mux_master_state {
153#define MUX_S_ALIVE 0x80000005 153#define MUX_S_ALIVE 0x80000005
154#define MUX_S_SESSION_OPENED 0x80000006 154#define MUX_S_SESSION_OPENED 0x80000006
155#define MUX_S_REMOTE_PORT 0x80000007 155#define MUX_S_REMOTE_PORT 0x80000007
156#define MUX_S_TTY_ALLOC_FAIL 0x80000008
156 157
157/* type codes for MUX_C_OPEN_FWD and MUX_C_CLOSE_FWD */ 158/* type codes for MUX_C_OPEN_FWD and MUX_C_CLOSE_FWD */
158#define MUX_FWD_LOCAL 1 159#define MUX_FWD_LOCAL 1
@@ -1054,6 +1055,27 @@ mux_exit_message(Channel *c, int exitval)
1054 buffer_free(&m); 1055 buffer_free(&m);
1055} 1056}
1056 1057
1058void
1059mux_tty_alloc_failed(Channel *c)
1060{
1061 Buffer m;
1062 Channel *mux_chan;
1063
1064 debug3("%s: channel %d: TTY alloc failed", __func__, c->self);
1065
1066 if ((mux_chan = channel_by_id(c->ctl_chan)) == NULL)
1067 fatal("%s: channel %d missing mux channel %d",
1068 __func__, c->self, c->ctl_chan);
1069
1070 /* Append exit message packet to control socket output queue */
1071 buffer_init(&m);
1072 buffer_put_int(&m, MUX_S_TTY_ALLOC_FAIL);
1073 buffer_put_int(&m, c->self);
1074
1075 buffer_put_string(&mux_chan->output, buffer_ptr(&m), buffer_len(&m));
1076 buffer_free(&m);
1077}
1078
1057/* Prepare a mux master to listen on a Unix domain socket. */ 1079/* Prepare a mux master to listen on a Unix domain socket. */
1058void 1080void
1059muxserver_listen(void) 1081muxserver_listen(void)
@@ -1612,7 +1634,7 @@ mux_client_request_session(int fd)
1612 char *e, *term; 1634 char *e, *term;
1613 u_int i, rid, sid, esid, exitval, type, exitval_seen; 1635 u_int i, rid, sid, esid, exitval, type, exitval_seen;
1614 extern char **environ; 1636 extern char **environ;
1615 int devnull; 1637 int devnull, rawmode;
1616 1638
1617 debug3("%s: entering", __func__); 1639 debug3("%s: entering", __func__);
1618 1640
@@ -1708,6 +1730,7 @@ mux_client_request_session(int fd)
1708 signal(SIGTERM, control_client_sighandler); 1730 signal(SIGTERM, control_client_sighandler);
1709 signal(SIGWINCH, control_client_sigrelay); 1731 signal(SIGWINCH, control_client_sigrelay);
1710 1732
1733 rawmode = tty_flag;
1711 if (tty_flag) 1734 if (tty_flag)
1712 enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE); 1735 enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
1713 1736
@@ -1723,22 +1746,35 @@ mux_client_request_session(int fd)
1723 if (mux_client_read_packet(fd, &m) != 0) 1746 if (mux_client_read_packet(fd, &m) != 0)
1724 break; 1747 break;
1725 type = buffer_get_int(&m); 1748 type = buffer_get_int(&m);
1726 if (type != MUX_S_EXIT_MESSAGE) { 1749 switch (type) {
1750 case MUX_S_TTY_ALLOC_FAIL:
1751 if ((esid = buffer_get_int(&m)) != sid)
1752 fatal("%s: tty alloc fail on unknown session: "
1753 "my id %u theirs %u",
1754 __func__, sid, esid);
1755 leave_raw_mode(options.request_tty ==
1756 REQUEST_TTY_FORCE);
1757 rawmode = 0;
1758 continue;
1759 case MUX_S_EXIT_MESSAGE:
1760 if ((esid = buffer_get_int(&m)) != sid)
1761 fatal("%s: exit on unknown session: "
1762 "my id %u theirs %u",
1763 __func__, sid, esid);
1764 if (exitval_seen)
1765 fatal("%s: exitval sent twice", __func__);
1766 exitval = buffer_get_int(&m);
1767 exitval_seen = 1;
1768 continue;
1769 default:
1727 e = buffer_get_string(&m, NULL); 1770 e = buffer_get_string(&m, NULL);
1728 fatal("%s: master returned error: %s", __func__, e); 1771 fatal("%s: master returned error: %s", __func__, e);
1729 } 1772 }
1730 if ((esid = buffer_get_int(&m)) != sid)
1731 fatal("%s: exit on unknown session: my id %u theirs %u",
1732 __func__, sid, esid);
1733 debug("%s: master session id: %u", __func__, sid);
1734 if (exitval_seen)
1735 fatal("%s: exitval sent twice", __func__);
1736 exitval = buffer_get_int(&m);
1737 exitval_seen = 1;
1738 } 1773 }
1739 1774
1740 close(fd); 1775 close(fd);
1741 leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); 1776 if (rawmode)
1777 leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
1742 1778
1743 if (muxclient_terminate) { 1779 if (muxclient_terminate) {
1744 debug2("Exiting on signal %d", muxclient_terminate); 1780 debug2("Exiting on signal %d", muxclient_terminate);