Skip to content

Commit

Permalink
- djm@cvs.openbsd.org 2011/05/08 12:52:01
Browse files Browse the repository at this point in the history
     [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@
  • Loading branch information
djmdjm committed May 14, 2011
1 parent f4b32aa commit 555f3b8
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 29 deletions.
12 changes: 12 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,18 @@
- jmc@cvs.openbsd.org 2011/05/07 23:20:25
[ssh.1]
+.It RequestTTY
- 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@

20110510
- (dtucker) [openbsd-compat/openssl-compat.{c,h}] Bug #1882: fix
Expand Down
11 changes: 9 additions & 2 deletions PROTOCOL.mux
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,13 @@ non-multiplexed ssh(1) connection. Two additional cases that the
client must cope with are it receiving a signal itself and the
server disconnecting without sending an exit message.

A master may also send a MUX_S_TTY_ALLOC_FAIL before MUX_S_EXIT_MESSAGE
if remote TTY allocation was unsuccessful. The client may use this to
return its local tty to "cooked" mode.

uint32 MUX_S_TTY_ALLOC_FAIL
uint32 session id

3. Health checks

The client may request a health check/PID report from a server:
Expand Down Expand Up @@ -197,6 +204,7 @@ The MUX_S_PERMISSION_DENIED and MUX_S_FAILURE include a reason:
#define MUX_S_ALIVE 0x80000005
#define MUX_S_SESSION_OPENED 0x80000006
#define MUX_S_REMOTE_PORT 0x80000007
#define MUX_S_TTY_ALLOC_FAIL 0x80000008

#define MUX_FWD_LOCAL 1
#define MUX_FWD_REMOTE 2
Expand All @@ -208,7 +216,6 @@ XXX lock (maybe)
XXX watch in/out traffic (pre/post crypto)
XXX inject packet (what about replies)
XXX server->client error/warning notifications
XXX port0 rfwd (need custom response message)
XXX send signals via mux

$OpenBSD: PROTOCOL.mux,v 1.6 2011/05/06 22:20:10 djm Exp $
$OpenBSD: PROTOCOL.mux,v 1.7 2011/05/08 12:52:01 djm Exp $
53 changes: 39 additions & 14 deletions clientloop.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* $OpenBSD: clientloop.c,v 1.233 2011/05/06 21:34:32 djm Exp $ */
/* $OpenBSD: clientloop.c,v 1.234 2011/05/08 12:52:01 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
Expand Down Expand Up @@ -174,9 +174,11 @@ struct escape_filter_ctx {
};

/* Context for channel confirmation replies */
enum confirm_action { CONFIRM_WARN = 0, CONFIRM_CLOSE, CONFIRM_TTY };
struct channel_reply_ctx {
const char *request_type;
int id, do_close;
int id;
enum confirm_action action;
};

/* Global request success/failure callbacks */
Expand Down Expand Up @@ -739,6 +741,15 @@ client_status_confirm(int type, Channel *c, void *ctx)
char errmsg[256];
int tochan;

/*
* If a TTY was explicitly requested, then a failure to allocate
* one is fatal.
*/
if (cr->action == CONFIRM_TTY &&
(options.request_tty == REQUEST_TTY_FORCE ||
options.request_tty == REQUEST_TTY_YES))
cr->action = CONFIRM_CLOSE;

/* XXX supress on mux _client_ quietmode */
tochan = options.log_level >= SYSLOG_LEVEL_ERROR &&
c->ctl_chan != -1 && c->extended_usage == CHAN_EXTENDED_WRITE;
Expand All @@ -756,14 +767,27 @@ client_status_confirm(int type, Channel *c, void *ctx)
cr->request_type, c->self);
}
/* If error occurred on primary session channel, then exit */
if (cr->do_close && c->self == session_ident)
if (cr->action == CONFIRM_CLOSE && c->self == session_ident)
fatal("%s", errmsg);
/* If error occurred on mux client, append to their stderr */
if (tochan)
buffer_append(&c->extended, errmsg, strlen(errmsg));
else
/*
* If error occurred on mux client, append to
* their stderr.
*/
if (tochan) {
buffer_append(&c->extended, errmsg,
strlen(errmsg));
} else
error("%s", errmsg);
if (cr->do_close) {
if (cr->action == CONFIRM_TTY) {
/*
* If a TTY allocation error occurred, then arrange
* for the correct TTY to leave raw mode.
*/
if (c->self == session_ident)
leave_raw_mode(0);
else
mux_tty_alloc_failed(c);
} else if (cr->action == CONFIRM_CLOSE) {
chan_read_failed(c);
chan_write_failed(c);
}
Expand All @@ -778,12 +802,13 @@ client_abandon_status_confirm(Channel *c, void *ctx)
}

static void
client_expect_confirm(int id, const char *request, int do_close)
client_expect_confirm(int id, const char *request,
enum confirm_action action)
{
struct channel_reply_ctx *cr = xmalloc(sizeof(*cr));

cr->request_type = request;
cr->do_close = do_close;
cr->action = action;

channel_register_status_confirm(id, client_status_confirm,
client_abandon_status_confirm, cr);
Expand Down Expand Up @@ -1983,7 +2008,7 @@ client_session2_setup(int id, int want_tty, int want_subsystem,
memset(&ws, 0, sizeof(ws));

channel_request_start(id, "pty-req", 1);
client_expect_confirm(id, "PTY allocation", 1);
client_expect_confirm(id, "PTY allocation", CONFIRM_TTY);
packet_put_cstring(term != NULL ? term : "");
packet_put_int((u_int)ws.ws_col);
packet_put_int((u_int)ws.ws_row);
Expand Down Expand Up @@ -2042,18 +2067,18 @@ client_session2_setup(int id, int want_tty, int want_subsystem,
debug("Sending subsystem: %.*s",
len, (u_char*)buffer_ptr(cmd));
channel_request_start(id, "subsystem", 1);
client_expect_confirm(id, "subsystem", 1);
client_expect_confirm(id, "subsystem", CONFIRM_CLOSE);
} else {
debug("Sending command: %.*s",
len, (u_char*)buffer_ptr(cmd));
channel_request_start(id, "exec", 1);
client_expect_confirm(id, "exec", 1);
client_expect_confirm(id, "exec", CONFIRM_CLOSE);
}
packet_put_string(buffer_ptr(cmd), buffer_len(cmd));
packet_send();
} else {
channel_request_start(id, "shell", 1);
client_expect_confirm(id, "shell", 1);
client_expect_confirm(id, "shell", CONFIRM_CLOSE);
packet_send();
}
}
Expand Down
4 changes: 3 additions & 1 deletion clientloop.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* $OpenBSD: clientloop.h,v 1.26 2011/04/17 22:42:41 djm Exp $ */
/* $OpenBSD: clientloop.h,v 1.27 2011/05/08 12:52:01 djm Exp $ */

/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
Expand Down Expand Up @@ -70,3 +70,5 @@ void client_register_global_confirm(global_confirm_cb *, void *);
void muxserver_listen(void);
void muxclient(const char *);
void mux_exit_message(Channel *, int);
void mux_tty_alloc_failed(Channel *);

60 changes: 48 additions & 12 deletions mux.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* $OpenBSD: mux.c,v 1.27 2011/05/06 21:34:32 djm Exp $ */
/* $OpenBSD: mux.c,v 1.28 2011/05/08 12:52:01 djm Exp $ */
/*
* Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
*
Expand Down Expand Up @@ -153,6 +153,7 @@ struct mux_master_state {
#define MUX_S_ALIVE 0x80000005
#define MUX_S_SESSION_OPENED 0x80000006
#define MUX_S_REMOTE_PORT 0x80000007
#define MUX_S_TTY_ALLOC_FAIL 0x80000008

/* type codes for MUX_C_OPEN_FWD and MUX_C_CLOSE_FWD */
#define MUX_FWD_LOCAL 1
Expand Down Expand Up @@ -1054,6 +1055,27 @@ mux_exit_message(Channel *c, int exitval)
buffer_free(&m);
}

void
mux_tty_alloc_failed(Channel *c)
{
Buffer m;
Channel *mux_chan;

debug3("%s: channel %d: TTY alloc failed", __func__, c->self);

if ((mux_chan = channel_by_id(c->ctl_chan)) == NULL)
fatal("%s: channel %d missing mux channel %d",
__func__, c->self, c->ctl_chan);

/* Append exit message packet to control socket output queue */
buffer_init(&m);
buffer_put_int(&m, MUX_S_TTY_ALLOC_FAIL);
buffer_put_int(&m, c->self);

buffer_put_string(&mux_chan->output, buffer_ptr(&m), buffer_len(&m));
buffer_free(&m);
}

/* Prepare a mux master to listen on a Unix domain socket. */
void
muxserver_listen(void)
Expand Down Expand Up @@ -1612,7 +1634,7 @@ mux_client_request_session(int fd)
char *e, *term;
u_int i, rid, sid, esid, exitval, type, exitval_seen;
extern char **environ;
int devnull;
int devnull, rawmode;

debug3("%s: entering", __func__);

Expand Down Expand Up @@ -1708,6 +1730,7 @@ mux_client_request_session(int fd)
signal(SIGTERM, control_client_sighandler);
signal(SIGWINCH, control_client_sigrelay);

rawmode = tty_flag;
if (tty_flag)
enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);

Expand All @@ -1723,22 +1746,35 @@ mux_client_request_session(int fd)
if (mux_client_read_packet(fd, &m) != 0)
break;
type = buffer_get_int(&m);
if (type != MUX_S_EXIT_MESSAGE) {
switch (type) {
case MUX_S_TTY_ALLOC_FAIL:
if ((esid = buffer_get_int(&m)) != sid)
fatal("%s: tty alloc fail on unknown session: "
"my id %u theirs %u",
__func__, sid, esid);
leave_raw_mode(options.request_tty ==
REQUEST_TTY_FORCE);
rawmode = 0;
continue;
case MUX_S_EXIT_MESSAGE:
if ((esid = buffer_get_int(&m)) != sid)
fatal("%s: exit on unknown session: "
"my id %u theirs %u",
__func__, sid, esid);
if (exitval_seen)
fatal("%s: exitval sent twice", __func__);
exitval = buffer_get_int(&m);
exitval_seen = 1;
continue;
default:
e = buffer_get_string(&m, NULL);
fatal("%s: master returned error: %s", __func__, e);
}
if ((esid = buffer_get_int(&m)) != sid)
fatal("%s: exit on unknown session: my id %u theirs %u",
__func__, sid, esid);
debug("%s: master session id: %u", __func__, sid);
if (exitval_seen)
fatal("%s: exitval sent twice", __func__);
exitval = buffer_get_int(&m);
exitval_seen = 1;
}

close(fd);
leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
if (rawmode)
leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);

if (muxclient_terminate) {
debug2("Exiting on signal %d", muxclient_terminate);
Expand Down

0 comments on commit 555f3b8

Please sign in to comment.