upstream commit

remove compat20/compat13/compat15 variables

ok markus@

Upstream-ID: 43802c035ceb3fef6c50c400e4ecabf12354691c
This commit is contained in:
djm@openbsd.org 2017-04-30 23:13:25 +00:00 committed by Damien Miller
parent 99f95ba826
commit 97f4d3083b
15 changed files with 426 additions and 1701 deletions

View File

@ -1,4 +1,4 @@
/* $OpenBSD: channels.c,v 1.357 2017/02/01 02:59:09 dtucker Exp $ */
/* $OpenBSD: channels.c,v 1.358 2017/04/30 23:13:25 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -571,14 +571,6 @@ channel_not_very_much_buffered_data(void)
for (i = 0; i < channels_alloc; i++) {
c = channels[i];
if (c != NULL && c->type == SSH_CHANNEL_OPEN) {
#if 0
if (!compat20 &&
buffer_len(&c->input) > packet_get_maxsize()) {
debug2("channel %d: big input buffer %d",
c->self, buffer_len(&c->input));
return 0;
}
#endif
if (buffer_len(&c->output) > packet_get_maxsize()) {
debug2("channel %d: big output buffer %u > %u",
c->self, buffer_len(&c->output),
@ -616,8 +608,6 @@ channel_still_open(void)
case SSH_CHANNEL_RUNIX_LISTENER:
continue;
case SSH_CHANNEL_LARVAL:
if (!compat20)
fatal("cannot happen: SSH_CHANNEL_LARVAL");
continue;
case SSH_CHANNEL_OPENING:
case SSH_CHANNEL_OPEN:
@ -627,11 +617,9 @@ channel_still_open(void)
return 1;
case SSH_CHANNEL_INPUT_DRAINING:
case SSH_CHANNEL_OUTPUT_DRAINING:
if (!compat13)
fatal("cannot happen: OUT_DRAIN");
return 1;
fatal("cannot happen: OUT_DRAIN");
default:
fatal("channel_still_open: bad channel type %d", c->type);
fatal("%s: bad channel type %d", __func__, c->type);
/* NOTREACHED */
}
}
@ -672,11 +660,9 @@ channel_find_open(void)
return i;
case SSH_CHANNEL_INPUT_DRAINING:
case SSH_CHANNEL_OUTPUT_DRAINING:
if (!compat13)
fatal("cannot happen: OUT_DRAIN");
return i;
fatal("cannot happen: OUT_DRAIN");
default:
fatal("channel_find_open: bad channel type %d", c->type);
fatal("%s: bad channel type %d", __func__, c->type);
/* NOTREACHED */
}
}
@ -895,23 +881,12 @@ channel_pre_connecting(Channel *c, fd_set *readset, fd_set *writeset)
FD_SET(c->sock, writeset);
}
static void
channel_pre_open_13(Channel *c, fd_set *readset, fd_set *writeset)
{
if (buffer_len(&c->input) < packet_get_maxsize())
FD_SET(c->sock, readset);
if (buffer_len(&c->output) > 0)
FD_SET(c->sock, writeset);
}
static void
channel_pre_open(Channel *c, fd_set *readset, fd_set *writeset)
{
u_int limit = compat20 ? c->remote_window : packet_get_maxsize();
if (c->istate == CHAN_INPUT_OPEN &&
limit > 0 &&
buffer_len(&c->input) < limit &&
c->remote_window > 0 &&
buffer_len(&c->input) < c->remote_window &&
buffer_check_alloc(&c->input, CHAN_RBUF))
FD_SET(c->rfd, readset);
if (c->ostate == CHAN_OUTPUT_OPEN ||
@ -927,8 +902,8 @@ channel_pre_open(Channel *c, fd_set *readset, fd_set *writeset)
}
}
/** XXX check close conditions, too */
if (compat20 && c->efd != -1 &&
!(c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED)) {
if (c->efd != -1 && !(c->istate == CHAN_INPUT_CLOSED &&
c->ostate == CHAN_OUTPUT_CLOSED)) {
if (c->extended_usage == CHAN_EXTENDED_WRITE &&
buffer_len(&c->extended) > 0)
FD_SET(c->efd, writeset);
@ -941,29 +916,6 @@ channel_pre_open(Channel *c, fd_set *readset, fd_set *writeset)
/* XXX: What about efd? races? */
}
/* ARGSUSED */
static void
channel_pre_input_draining(Channel *c, fd_set *readset, fd_set *writeset)
{
if (buffer_len(&c->input) == 0) {
packet_start(SSH_MSG_CHANNEL_CLOSE);
packet_put_int(c->remote_id);
packet_send();
c->type = SSH_CHANNEL_CLOSED;
debug2("channel %d: closing after input drain.", c->self);
}
}
/* ARGSUSED */
static void
channel_pre_output_draining(Channel *c, fd_set *readset, fd_set *writeset)
{
if (buffer_len(&c->output) == 0)
chan_mark_dead(c);
else
FD_SET(c->sock, writeset);
}
/*
* This is a special state for X11 authentication spoofing. An opened X11
* connection (when authentication spoofing is being done) remains in this
@ -1038,32 +990,6 @@ x11_open_helper(Buffer *b)
return 1;
}
static void
channel_pre_x11_open_13(Channel *c, fd_set *readset, fd_set *writeset)
{
int ret = x11_open_helper(&c->output);
if (ret == 1) {
/* Start normal processing for the channel. */
c->type = SSH_CHANNEL_OPEN;
channel_pre_open_13(c, readset, writeset);
} else if (ret == -1) {
/*
* We have received an X11 connection that has bad
* authentication information.
*/
logit("X11 connection rejected because of wrong authentication.");
buffer_clear(&c->input);
buffer_clear(&c->output);
channel_close_fd(&c->sock);
c->sock = -1;
c->type = SSH_CHANNEL_CLOSED;
packet_start(SSH_MSG_CHANNEL_CLOSE);
packet_put_int(c->remote_id);
packet_send();
}
}
static void
channel_pre_x11_open(Channel *c, fd_set *readset, fd_set *writeset)
{
@ -1081,11 +1007,7 @@ channel_pre_x11_open(Channel *c, fd_set *readset, fd_set *writeset)
buffer_clear(&c->input);
chan_ibuf_empty(c);
buffer_clear(&c->output);
/* for proto v1, the peer will send an IEOF */
if (compat20)
chan_write_failed(c);
else
c->type = SSH_CHANNEL_OPEN;
chan_write_failed(c);
debug2("X11 closed %d i%d/o%d", c->self, c->istate, c->ostate);
}
}
@ -1449,28 +1371,19 @@ channel_post_x11_listener(Channel *c, fd_set *readset, fd_set *writeset)
nc = channel_new("accepted x11 socket",
SSH_CHANNEL_OPENING, newsock, newsock, -1,
c->local_window_max, c->local_maxpacket, 0, buf, 1);
if (compat20) {
packet_start(SSH2_MSG_CHANNEL_OPEN);
packet_put_cstring("x11");
packet_put_int(nc->self);
packet_put_int(nc->local_window_max);
packet_put_int(nc->local_maxpacket);
/* originator ipaddr and port */
packet_put_cstring(remote_ipaddr);
if (datafellows & SSH_BUG_X11FWD) {
debug2("ssh2 x11 bug compat mode");
} else {
packet_put_int(remote_port);
}
packet_send();
packet_start(SSH2_MSG_CHANNEL_OPEN);
packet_put_cstring("x11");
packet_put_int(nc->self);
packet_put_int(nc->local_window_max);
packet_put_int(nc->local_maxpacket);
/* originator ipaddr and port */
packet_put_cstring(remote_ipaddr);
if (datafellows & SSH_BUG_X11FWD) {
debug2("ssh2 x11 bug compat mode");
} else {
packet_start(SSH_SMSG_X11_OPEN);
packet_put_int(nc->self);
if (packet_get_protocol_flags() &
SSH_PROTOFLAG_HOST_IN_FWD_OPEN)
packet_put_cstring(buf);
packet_send();
packet_put_int(remote_port);
}
packet_send();
free(remote_ipaddr);
}
}
@ -1500,46 +1413,35 @@ port_open_helper(Channel *c, char *rtype)
free(c->remote_name);
c->remote_name = xstrdup(buf);
if (compat20) {
packet_start(SSH2_MSG_CHANNEL_OPEN);
packet_put_cstring(rtype);
packet_put_int(c->self);
packet_put_int(c->local_window_max);
packet_put_int(c->local_maxpacket);
if (strcmp(rtype, "direct-tcpip") == 0) {
/* target host, port */
packet_put_cstring(c->path);
packet_put_int(c->host_port);
} else if (strcmp(rtype, "direct-streamlocal@openssh.com") == 0) {
/* target path */
packet_put_cstring(c->path);
} else if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) {
/* listen path */
packet_put_cstring(c->path);
} else {
/* listen address, port */
packet_put_cstring(c->path);
packet_put_int(local_port);
}
if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) {
/* reserved for future owner/mode info */
packet_put_cstring("");
} else {
/* originator host and port */
packet_put_cstring(remote_ipaddr);
packet_put_int((u_int)remote_port);
}
packet_send();
} else {
packet_start(SSH_MSG_PORT_OPEN);
packet_put_int(c->self);
packet_start(SSH2_MSG_CHANNEL_OPEN);
packet_put_cstring(rtype);
packet_put_int(c->self);
packet_put_int(c->local_window_max);
packet_put_int(c->local_maxpacket);
if (strcmp(rtype, "direct-tcpip") == 0) {
/* target host, port */
packet_put_cstring(c->path);
packet_put_int(c->host_port);
if (packet_get_protocol_flags() &
SSH_PROTOFLAG_HOST_IN_FWD_OPEN)
packet_put_cstring(c->remote_name);
packet_send();
} else if (strcmp(rtype, "direct-streamlocal@openssh.com") == 0) {
/* target path */
packet_put_cstring(c->path);
} else if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) {
/* listen path */
packet_put_cstring(c->path);
} else {
/* listen address, port */
packet_put_cstring(c->path);
packet_put_int(local_port);
}
if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) {
/* reserved for future owner/mode info */
packet_put_cstring("");
} else {
/* originator host and port */
packet_put_cstring(remote_ipaddr);
packet_put_int((u_int)remote_port);
}
packet_send();
free(remote_ipaddr);
free(local_ipaddr);
}
@ -1649,16 +1551,11 @@ channel_post_auth_listener(Channel *c, fd_set *readset, fd_set *writeset)
SSH_CHANNEL_OPENING, newsock, newsock, -1,
c->local_window_max, c->local_maxpacket,
0, "accepted auth socket", 1);
if (compat20) {
packet_start(SSH2_MSG_CHANNEL_OPEN);
packet_put_cstring("auth-agent@openssh.com");
packet_put_int(nc->self);
packet_put_int(c->local_window_max);
packet_put_int(c->local_maxpacket);
} else {
packet_start(SSH_SMSG_AGENT_OPEN);
packet_put_int(nc->self);
}
packet_start(SSH2_MSG_CHANNEL_OPEN);
packet_put_cstring("auth-agent@openssh.com");
packet_put_int(nc->self);
packet_put_int(c->local_window_max);
packet_put_int(c->local_maxpacket);
packet_send();
}
}
@ -1680,17 +1577,11 @@ channel_post_connecting(Channel *c, fd_set *readset, fd_set *writeset)
c->self, c->connect_ctx.host, c->connect_ctx.port);
channel_connect_ctx_free(&c->connect_ctx);
c->type = SSH_CHANNEL_OPEN;
if (compat20) {
packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
packet_put_int(c->remote_id);
packet_put_int(c->self);
packet_put_int(c->local_window);
packet_put_int(c->local_maxpacket);
} else {
packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
packet_put_int(c->remote_id);
packet_put_int(c->self);
}
packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
packet_put_int(c->remote_id);
packet_put_int(c->self);
packet_put_int(c->local_window);
packet_put_int(c->local_maxpacket);
} else {
debug("channel %d: connection failed: %s",
c->self, strerror(err));
@ -1705,17 +1596,12 @@ channel_post_connecting(Channel *c, fd_set *readset, fd_set *writeset)
error("connect_to %.100s port %d: failed.",
c->connect_ctx.host, c->connect_ctx.port);
channel_connect_ctx_free(&c->connect_ctx);
if (compat20) {
packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
packet_put_int(c->remote_id);
packet_put_int(SSH2_OPEN_CONNECT_FAILED);
if (!(datafellows & SSH_BUG_OPENFAILURE)) {
packet_put_cstring(strerror(err));
packet_put_cstring("");
}
} else {
packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
packet_put_int(c->remote_id);
packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
packet_put_int(c->remote_id);
packet_put_int(SSH2_OPEN_CONNECT_FAILED);
if (!(datafellows & SSH_BUG_OPENFAILURE)) {
packet_put_cstring(strerror(err));
packet_put_cstring("");
}
chan_mark_dead(c);
}
@ -1749,10 +1635,6 @@ channel_handle_rfd(Channel *c, fd_set *readset, fd_set *writeset)
debug2("channel %d: not open", c->self);
chan_mark_dead(c);
return -1;
} else if (compat13) {
buffer_clear(&c->output);
c->type = SSH_CHANNEL_INPUT_DRAINING;
debug2("channel %d: input draining.", c->self);
} else {
chan_read_failed(c);
}
@ -1820,7 +1702,7 @@ channel_handle_wfd(Channel *c, fd_set *readset, fd_set *writeset)
}
#ifdef _AIX
/* XXX: Later AIX versions can't push as much data to tty */
if (compat20 && c->wfd_isatty)
if (c->wfd_isatty)
dlen = MIN(dlen, 8*1024);
#endif
@ -1833,17 +1715,13 @@ channel_handle_wfd(Channel *c, fd_set *readset, fd_set *writeset)
debug2("channel %d: not open", c->self);
chan_mark_dead(c);
return -1;
} else if (compat13) {
buffer_clear(&c->output);
debug2("channel %d: input draining.", c->self);
c->type = SSH_CHANNEL_INPUT_DRAINING;
} else {
chan_write_failed(c);
}
return -1;
}
#ifndef BROKEN_TCGETATTR_ICANON
if (compat20 && c->isatty && dlen >= 1 && buf[0] != '\r') {
if (c->isatty && dlen >= 1 && buf[0] != '\r') {
if (tcgetattr(c->wfd, &tio) == 0 &&
!(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) {
/*
@ -1860,7 +1738,7 @@ channel_handle_wfd(Channel *c, fd_set *readset, fd_set *writeset)
buffer_consume(&c->output, len);
}
out:
if (compat20 && olen > 0)
if (olen > 0)
c->local_consumed += olen - buffer_len(&c->output);
return 1;
}
@ -1944,8 +1822,6 @@ channel_post_open(Channel *c, fd_set *readset, fd_set *writeset)
{
channel_handle_rfd(c, readset, writeset);
channel_handle_wfd(c, readset, writeset);
if (!compat20)
return;
channel_handle_efd(c, readset, writeset);
channel_check_window(c);
}
@ -1979,9 +1855,6 @@ channel_post_mux_client(Channel *c, fd_set *readset, fd_set *writeset)
u_int need;
ssize_t len;
if (!compat20)
fatal("%s: entered with !compat20", __func__);
if (c->rfd != -1 && !c->mux_pause && FD_ISSET(c->rfd, readset) &&
(c->istate == CHAN_INPUT_OPEN ||
c->istate == CHAN_INPUT_WAIT_DRAIN)) {
@ -2074,26 +1947,15 @@ channel_post_mux_listener(Channel *c, fd_set *readset, fd_set *writeset)
nc->flags |= CHAN_LOCAL;
}
/* ARGSUSED */
static void
channel_post_output_drain_13(Channel *c, fd_set *readset, fd_set *writeset)
channel_handler_init(void)
{
int len;
int i;
/* Send buffered output data to the socket. */
if (FD_ISSET(c->sock, writeset) && buffer_len(&c->output) > 0) {
len = write(c->sock, buffer_ptr(&c->output),
buffer_len(&c->output));
if (len <= 0)
buffer_clear(&c->output);
else
buffer_consume(&c->output, len);
for (i = 0; i < SSH_CHANNEL_MAX_TYPE; i++) {
channel_pre[i] = NULL;
channel_post[i] = NULL;
}
}
static void
channel_handler_init_20(void)
{
channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open;
channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open;
channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener;
@ -2120,64 +1982,6 @@ channel_handler_init_20(void)
channel_post[SSH_CHANNEL_MUX_CLIENT] = &channel_post_mux_client;
}
static void
channel_handler_init_13(void)
{
channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open_13;
channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open_13;
channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener;
channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener;
channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener;
channel_pre[SSH_CHANNEL_INPUT_DRAINING] = &channel_pre_input_draining;
channel_pre[SSH_CHANNEL_OUTPUT_DRAINING] = &channel_pre_output_draining;
channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting;
channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic;
channel_post[SSH_CHANNEL_OPEN] = &channel_post_open;
channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener;
channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener;
channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
channel_post[SSH_CHANNEL_OUTPUT_DRAINING] = &channel_post_output_drain_13;
channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open;
}
static void
channel_handler_init_15(void)
{
channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open;
channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open;
channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener;
channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener;
channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener;
channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting;
channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic;
channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener;
channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener;
channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
channel_post[SSH_CHANNEL_OPEN] = &channel_post_open;
channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open;
}
static void
channel_handler_init(void)
{
int i;
for (i = 0; i < SSH_CHANNEL_MAX_TYPE; i++) {
channel_pre[i] = NULL;
channel_post[i] = NULL;
}
if (compat20)
channel_handler_init_20();
else if (compat13)
channel_handler_init_13();
else
channel_handler_init_15();
}
/* gc dead channels */
static void
channel_garbage_collect(Channel *c)
@ -2312,16 +2116,9 @@ channel_output_poll(void)
* We are only interested in channels that can have buffered
* incoming data.
*/
if (compat13) {
if (c->type != SSH_CHANNEL_OPEN &&
c->type != SSH_CHANNEL_INPUT_DRAINING)
continue;
} else {
if (c->type != SSH_CHANNEL_OPEN)
continue;
}
if (compat20 &&
(c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD))) {
if (c->type != SSH_CHANNEL_OPEN)
continue;
if ((c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD))) {
/* XXX is this true? */
debug3("channel %d: will not send data after close", c->self);
continue;
@ -2359,24 +2156,12 @@ channel_output_poll(void)
* Send some data for the other side over the secure
* connection.
*/
if (compat20) {
if (len > c->remote_window)
len = c->remote_window;
if (len > c->remote_maxpacket)
len = c->remote_maxpacket;
} else {
if (packet_is_interactive()) {
if (len > 1024)
len = 512;
} else {
/* Keep the packets at reasonable size. */
if (len > packet_get_maxsize()/2)
len = packet_get_maxsize()/2;
}
}
if (len > c->remote_window)
len = c->remote_window;
if (len > c->remote_maxpacket)
len = c->remote_maxpacket;
if (len > 0) {
packet_start(compat20 ?
SSH2_MSG_CHANNEL_DATA : SSH_MSG_CHANNEL_DATA);
packet_start(SSH2_MSG_CHANNEL_DATA);
packet_put_int(c->remote_id);
packet_put_string(buffer_ptr(&c->input), len);
packet_send();
@ -2384,8 +2169,6 @@ channel_output_poll(void)
c->remote_window -= len;
}
} else if (c->istate == CHAN_INPUT_WAIT_DRAIN) {
if (compat13)
fatal("cannot happen: istate == INPUT_WAIT_DRAIN for proto 1.3");
/*
* input-buffer is empty and read-socket shutdown:
* tell peer, that we will not send more data: send IEOF.
@ -2398,8 +2181,7 @@ channel_output_poll(void)
chan_ibuf_empty(c);
}
/* Send extended data, i.e. stderr */
if (compat20 &&
!(c->flags & CHAN_EOF_SENT) &&
if (!(c->flags & CHAN_EOF_SENT) &&
c->remote_window > 0 &&
(len = buffer_len(&c->extended)) > 0 &&
c->extended_usage == CHAN_EXTENDED_READ) {
@ -2738,26 +2520,23 @@ channel_input_data(int type, u_int32_t seq, void *ctxt)
* that window updates are sent back. Otherwise the connection might
* deadlock.
*/
if (!compat13 && c->ostate != CHAN_OUTPUT_OPEN) {
if (compat20) {
c->local_window -= win_len;
c->local_consumed += win_len;
}
if (c->ostate != CHAN_OUTPUT_OPEN) {
c->local_window -= win_len;
c->local_consumed += win_len;
return 0;
}
if (compat20) {
if (win_len > c->local_maxpacket) {
logit("channel %d: rcvd big packet %d, maxpack %d",
c->self, win_len, c->local_maxpacket);
}
if (win_len > c->local_window) {
logit("channel %d: rcvd too much data %d, win %d",
c->self, win_len, c->local_window);
return 0;
}
c->local_window -= win_len;
if (win_len > c->local_maxpacket) {
logit("channel %d: rcvd big packet %d, maxpack %d",
c->self, win_len, c->local_maxpacket);
}
if (win_len > c->local_window) {
logit("channel %d: rcvd too much data %d, win %d",
c->self, win_len, c->local_window);
return 0;
}
c->local_window -= win_len;
if (c->datagram)
buffer_put_string(&c->output, data, data_len);
else
@ -2942,17 +2721,15 @@ channel_input_open_confirmation(int type, u_int32_t seq, void *ctxt)
c->remote_id = remote_id;
c->type = SSH_CHANNEL_OPEN;
if (compat20) {
c->remote_window = packet_get_int();
c->remote_maxpacket = packet_get_int();
if (c->open_confirm) {
debug2("callback start");
c->open_confirm(c->self, 1, c->open_confirm_ctx);
debug2("callback done");
}
debug2("channel %d: open confirm rwindow %u rmax %u", c->self,
c->remote_window, c->remote_maxpacket);
c->remote_window = packet_get_int();
c->remote_maxpacket = packet_get_int();
if (c->open_confirm) {
debug2("callback start");
c->open_confirm(c->self, 1, c->open_confirm_ctx);
debug2("callback done");
}
debug2("channel %d: open confirm rwindow %u rmax %u", c->self,
c->remote_window, c->remote_maxpacket);
packet_check_eom();
return 0;
}
@ -2992,21 +2769,19 @@ channel_input_open_failure(int type, u_int32_t seq, void *ctxt)
if (c->type != SSH_CHANNEL_OPENING)
packet_disconnect("Received open failure for "
"non-opening channel %d.", id);
if (compat20) {
reason = packet_get_int();
if (!(datafellows & SSH_BUG_OPENFAILURE)) {
msg = packet_get_string(NULL);
lang = packet_get_string(NULL);
}
logit("channel %d: open failed: %s%s%s", id,
reason2txt(reason), msg ? ": ": "", msg ? msg : "");
free(msg);
free(lang);
if (c->open_confirm) {
debug2("callback start");
c->open_confirm(c->self, 0, c->open_confirm_ctx);
debug2("callback done");
}
reason = packet_get_int();
if (!(datafellows & SSH_BUG_OPENFAILURE)) {
msg = packet_get_string(NULL);
lang = packet_get_string(NULL);
}
logit("channel %d: open failed: %s%s%s", id,
reason2txt(reason), msg ? ": ": "", msg ? msg : "");
free(msg);
free(lang);
if (c->open_confirm) {
debug2("callback start");
c->open_confirm(c->self, 0, c->open_confirm_ctx);
debug2("callback done");
}
packet_check_eom();
/* Schedule the channel for cleanup/deletion. */
@ -3022,9 +2797,6 @@ channel_input_window_adjust(int type, u_int32_t seq, void *ctxt)
int id;
u_int adjust, tmp;
if (!compat20)
return 0;
/* Get the channel number and verify it. */
id = packet_get_int();
c = channel_lookup(id);
@ -3581,49 +3353,24 @@ channel_rfwd_bind_host(const char *listen_host)
int
channel_request_remote_forwarding(struct Forward *fwd)
{
int type, success = 0, idx = -1;
int success = 0, idx = -1;
/* Send the forward request to the remote side. */
if (compat20) {
packet_start(SSH2_MSG_GLOBAL_REQUEST);
if (fwd->listen_path != NULL) {
packet_put_cstring("streamlocal-forward@openssh.com");
packet_put_char(1); /* boolean: want reply */
packet_put_cstring(fwd->listen_path);
} else {
packet_put_cstring("tcpip-forward");
packet_put_char(1); /* boolean: want reply */
packet_put_cstring(channel_rfwd_bind_host(fwd->listen_host));
packet_put_int(fwd->listen_port);
}
packet_send();
packet_write_wait();
/* Assume that server accepts the request */
success = 1;
} else if (fwd->listen_path == NULL) {
packet_start(SSH_CMSG_PORT_FORWARD_REQUEST);
packet_put_int(fwd->listen_port);
packet_put_cstring(fwd->connect_host);
packet_put_int(fwd->connect_port);
packet_send();
packet_write_wait();
/* Wait for response from the remote side. */
type = packet_read();
switch (type) {
case SSH_SMSG_SUCCESS:
success = 1;
break;
case SSH_SMSG_FAILURE:
break;
default:
/* Unknown packet */
packet_disconnect("Protocol error for port forward request:"
"received packet type %d.", type);
}
packet_start(SSH2_MSG_GLOBAL_REQUEST);
if (fwd->listen_path != NULL) {
packet_put_cstring("streamlocal-forward@openssh.com");
packet_put_char(1); /* boolean: want reply */
packet_put_cstring(fwd->listen_path);
} else {
logit("Warning: Server does not support remote stream local forwarding.");
packet_put_cstring("tcpip-forward");
packet_put_char(1); /* boolean: want reply */
packet_put_cstring(channel_rfwd_bind_host(fwd->listen_host));
packet_put_int(fwd->listen_port);
}
packet_send();
packet_write_wait();
/* Assume that server accepts the request */
success = 1;
if (success) {
/* Record that connection to this host/port is permitted. */
permitted_opens = xreallocarray(permitted_opens,
@ -3722,9 +3469,6 @@ channel_request_rforward_cancel_tcpip(const char *host, u_short port)
{
int i;
if (!compat20)
return -1;
for (i = 0; i < num_permitted_opens; i++) {
if (open_listen_match_tcpip(&permitted_opens[i], host, port, 0))
break;
@ -3761,9 +3505,6 @@ channel_request_rforward_cancel_streamlocal(const char *path)
{
int i;
if (!compat20)
return -1;
for (i = 0; i < num_permitted_opens; i++) {
if (open_listen_match_streamlocal(&permitted_opens[i], path))
break;
@ -4644,12 +4385,8 @@ x11_request_forwarding_with_spoofing(int client_session_id, const char *disp,
new_data = tohex(x11_fake_data, data_len);
/* Send the request packet. */
if (compat20) {
channel_request_start(client_session_id, "x11-req", want_reply);
packet_put_char(0); /* XXX bool single connection */
} else {
packet_start(SSH_CMSG_X11_REQUEST_FORWARDING);
}
channel_request_start(client_session_id, "x11-req", want_reply);
packet_put_char(0); /* XXX bool single connection */
packet_put_cstring(proto);
packet_put_cstring(new_data);
packet_put_int(screen_number);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: channels.h,v 1.121 2017/02/01 02:59:09 dtucker Exp $ */
/* $OpenBSD: channels.h,v 1.122 2017/04/30 23:13:25 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -200,11 +200,11 @@ struct Channel {
/* check whether 'efd' is still in use */
#define CHANNEL_EFD_INPUT_ACTIVE(c) \
(compat20 && c->extended_usage == CHAN_EXTENDED_READ && \
(c->extended_usage == CHAN_EXTENDED_READ && \
(c->efd != -1 || \
buffer_len(&c->extended) > 0))
#define CHANNEL_EFD_OUTPUT_ACTIVE(c) \
(compat20 && c->extended_usage == CHAN_EXTENDED_WRITE && \
(c->extended_usage == CHAN_EXTENDED_WRITE && \
c->efd != -1 && (!(c->flags & (CHAN_EOF_RCVD|CHAN_CLOSE_RCVD)) || \
buffer_len(&c->extended) > 0))

View File

@ -1,4 +1,4 @@
/* $OpenBSD: clientloop.c,v 1.291 2017/03/10 05:01:13 djm Exp $ */
/* $OpenBSD: clientloop.c,v 1.292 2017/04/30 23:13:25 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -207,15 +207,6 @@ leave_non_blocking(void)
}
}
/* Puts stdin terminal in non-blocking mode. */
static void
enter_non_blocking(void)
{
in_non_blocking_mode = 1;
set_nonblock(fileno(stdin));
}
/*
* Signal handler for the window change signal (SIGWINCH). This just sets a
* flag indicating that the window has changed.
@ -454,91 +445,6 @@ client_x11_get_proto(const char *display, const char *xauth_path,
return 0;
}
/*
* This is called when the interactive is entered. This checks if there is
* an EOF coming on stdin. We must check this explicitly, as select() does
* not appear to wake up when redirecting from /dev/null.
*/
static void
client_check_initial_eof_on_stdin(void)
{
int len;
char buf[1];
/*
* If standard input is to be "redirected from /dev/null", we simply
* mark that we have seen an EOF and send an EOF message to the
* server. Otherwise, we try to read a single character; it appears
* that for some files, such /dev/null, select() never wakes up for
* read for this descriptor, which means that we never get EOF. This
* way we will get the EOF if stdin comes from /dev/null or similar.
*/
if (stdin_null_flag) {
/* Fake EOF on stdin. */
debug("Sending eof.");
stdin_eof = 1;
packet_start(SSH_CMSG_EOF);
packet_send();
} else {
enter_non_blocking();
/* Check for immediate EOF on stdin. */
len = read(fileno(stdin), buf, 1);
if (len == 0) {
/*
* EOF. Record that we have seen it and send
* EOF to server.
*/
debug("Sending eof.");
stdin_eof = 1;
packet_start(SSH_CMSG_EOF);
packet_send();
} else if (len > 0) {
/*
* Got data. We must store the data in the buffer,
* and also process it as an escape character if
* appropriate.
*/
if ((u_char) buf[0] == escape_char1)
escape_pending1 = 1;
else
buffer_append(&stdin_buffer, buf, 1);
}
leave_non_blocking();
}
}
/*
* Make packets from buffered stdin data, and buffer them for sending to the
* connection.
*/
static void
client_make_packets_from_stdin_data(void)
{
u_int len;
/* Send buffered stdin data to the server. */
while (buffer_len(&stdin_buffer) > 0 &&
packet_not_very_much_data_to_write()) {
len = buffer_len(&stdin_buffer);
/* Keep the packets at reasonable size. */
if (len > packet_get_maxsize())
len = packet_get_maxsize();
packet_start(SSH_CMSG_STDIN_DATA);
packet_put_string(buffer_ptr(&stdin_buffer), len);
packet_send();
buffer_consume(&stdin_buffer, len);
/* If we have a pending EOF, send it now. */
if (stdin_eof && buffer_len(&stdin_buffer) == 0) {
packet_start(SSH_CMSG_EOF);
packet_send();
}
}
}
/*
* Checks if the client window has changed, and sends a packet about it to
* the server if so. The actual change is detected elsewhere (by a software
@ -549,27 +455,14 @@ client_make_packets_from_stdin_data(void)
static void
client_check_window_change(void)
{
struct winsize ws;
if (! received_window_change_signal)
if (!received_window_change_signal)
return;
/** XXX race */
received_window_change_signal = 0;
debug2("client_check_window_change: changed");
debug2("%s: changed", __func__);
if (compat20) {
channel_send_window_changes();
} else {
if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
return;
packet_start(SSH_CMSG_WINDOW_SIZE);
packet_put_int((u_int)ws.ws_row);
packet_put_int((u_int)ws.ws_col);
packet_put_int((u_int)ws.ws_xpixel);
packet_put_int((u_int)ws.ws_ypixel);
packet_send();
}
channel_send_window_changes();
}
static int
@ -623,35 +516,15 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
channel_prepare_select(readsetp, writesetp, maxfdp, nallocp,
&minwait_secs, rekeying);
if (!compat20) {
/* Read from the connection, unless our buffers are full. */
if (buffer_len(&stdout_buffer) < buffer_high &&
buffer_len(&stderr_buffer) < buffer_high &&
channel_not_very_much_buffered_data())
FD_SET(connection_in, *readsetp);
/*
* Read from stdin, unless we have seen EOF or have very much
* buffered data to send to the server.
*/
if (!stdin_eof && packet_not_very_much_data_to_write())
FD_SET(fileno(stdin), *readsetp);
/* Select stdout/stderr if have data in buffer. */
if (buffer_len(&stdout_buffer) > 0)
FD_SET(fileno(stdout), *writesetp);
if (buffer_len(&stderr_buffer) > 0)
FD_SET(fileno(stderr), *writesetp);
/* channel_prepare_select could have closed the last channel */
if (session_closed && !channel_still_open() &&
!packet_have_data_to_write()) {
/* clear mask since we did not call select() */
memset(*readsetp, 0, *nallocp);
memset(*writesetp, 0, *nallocp);
return;
} else {
/* channel_prepare_select could have closed the last channel */
if (session_closed && !channel_still_open() &&
!packet_have_data_to_write()) {
/* clear mask since we did not call select() */
memset(*readsetp, 0, *nallocp);
memset(*writesetp, 0, *nallocp);
return;
} else {
FD_SET(connection_in, *readsetp);
}
FD_SET(connection_in, *readsetp);
}
/* Select server connection if have data to write to the server. */
@ -665,11 +538,11 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
*/
timeout_secs = INT_MAX; /* we use INT_MAX to mean no timeout */
if (options.server_alive_interval > 0 && compat20) {
if (options.server_alive_interval > 0) {
timeout_secs = options.server_alive_interval;
server_alive_time = now + options.server_alive_interval;
}
if (options.rekey_interval > 0 && compat20 && !rekeying)
if (options.rekey_interval > 0 && !rekeying)
timeout_secs = MINIMUM(timeout_secs, packet_get_rekey_timeout());
set_control_persist_exit_time();
if (control_persist_exit_time > 0) {
@ -966,11 +839,6 @@ process_cmdline(void)
goto out;
}
if (delete && !compat20) {
logit("Not supported for SSH protocol version 1.");
goto out;
}
while (isspace((u_char)*++s))
;
@ -1027,10 +895,9 @@ out:
/* reasons to suppress output of an escape command in help output */
#define SUPPRESS_NEVER 0 /* never suppress, always show */
#define SUPPRESS_PROTO1 1 /* don't show in protocol 1 sessions */
#define SUPPRESS_MUXCLIENT 2 /* don't show in mux client sessions */
#define SUPPRESS_MUXMASTER 4 /* don't show in mux master sessions */
#define SUPPRESS_SYSLOG 8 /* don't show when logging to syslog */
#define SUPPRESS_MUXCLIENT 1 /* don't show in mux client sessions */
#define SUPPRESS_MUXMASTER 2 /* don't show in mux master sessions */
#define SUPPRESS_SYSLOG 4 /* don't show when logging to syslog */
struct escape_help_text {
const char *cmd;
const char *text;
@ -1040,9 +907,9 @@ static struct escape_help_text esc_txt[] = {
{".", "terminate session", SUPPRESS_MUXMASTER},
{".", "terminate connection (and any multiplexed sessions)",
SUPPRESS_MUXCLIENT},
{"B", "send a BREAK to the remote system", SUPPRESS_PROTO1},
{"B", "send a BREAK to the remote system", SUPPRESS_NEVER},
{"C", "open a command line", SUPPRESS_MUXCLIENT},
{"R", "request rekey", SUPPRESS_PROTO1},
{"R", "request rekey", SUPPRESS_NEVER},
{"V/v", "decrease/increase verbosity (LogLevel)", SUPPRESS_MUXCLIENT},
{"^Z", "suspend ssh", SUPPRESS_MUXCLIENT},
{"#", "list forwarded connections", SUPPRESS_NEVER},
@ -1052,8 +919,7 @@ static struct escape_help_text esc_txt[] = {
};
static void
print_escape_help(Buffer *b, int escape_char, int protocol2, int mux_client,
int using_stderr)
print_escape_help(Buffer *b, int escape_char, int mux_client, int using_stderr)
{
unsigned int i, suppress_flags;
char string[1024];
@ -1062,7 +928,7 @@ print_escape_help(Buffer *b, int escape_char, int protocol2, int mux_client,
"Supported escape sequences:\r\n", escape_char);
buffer_append(b, string, strlen(string));
suppress_flags = (protocol2 ? 0 : SUPPRESS_PROTO1) |
suppress_flags =
(mux_client ? SUPPRESS_MUXCLIENT : 0) |
(mux_client ? 0 : SUPPRESS_MUXMASTER) |
(using_stderr ? 0 : SUPPRESS_SYSLOG);
@ -1171,26 +1037,20 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
continue;
case 'B':
if (compat20) {
snprintf(string, sizeof string,
"%cB\r\n", escape_char);
buffer_append(berr, string,
strlen(string));
channel_request_start(c->self,
"break", 0);
packet_put_int(1000);
packet_send();
}
snprintf(string, sizeof string,
"%cB\r\n", escape_char);
buffer_append(berr, string, strlen(string));
channel_request_start(c->self, "break", 0);
packet_put_int(1000);
packet_send();
continue;
case 'R':
if (compat20) {
if (datafellows & SSH_BUG_NOREKEY)
logit("Server does not "
"support re-keying");
else
need_rekeying = 1;
}
if (datafellows & SSH_BUG_NOREKEY)
logit("Server does not "
"support re-keying");
else
need_rekeying = 1;
continue;
case 'V':
@ -1248,30 +1108,11 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
exit(0);
}
/* The child continues serving connections. */
if (compat20) {
buffer_append(bin, "\004", 1);
/* fake EOF on stdin */
return -1;
} else if (!stdin_eof) {
/*
* Sending SSH_CMSG_EOF alone does not
* always appear to be enough. So we
* try to send an EOF character first.
*/
packet_start(SSH_CMSG_STDIN_DATA);
packet_put_string("\004", 1);
packet_send();
/* Close stdin. */
stdin_eof = 1;
if (buffer_len(bin) == 0) {
packet_start(SSH_CMSG_EOF);
packet_send();
}
}
continue;
buffer_append(bin, "\004", 1);
/* fake EOF on stdin */
return -1;
case '?':
print_escape_help(berr, escape_char, compat20,
print_escape_help(berr, escape_char,
(c && c->ctl_chan != -1),
log_is_on_stderr());
continue;
@ -1325,115 +1166,6 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
return bytes;
}
static void
client_process_input(fd_set *readset)
{
int len;
char buf[SSH_IOBUFSZ];
/* Read input from stdin. */
if (FD_ISSET(fileno(stdin), readset)) {
/* Read as much as possible. */
len = read(fileno(stdin), buf, sizeof(buf));
if (len < 0 &&
(errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK))
return; /* we'll try again later */
if (len <= 0) {
/*
* Received EOF or error. They are treated
* similarly, except that an error message is printed
* if it was an error condition.
*/
if (len < 0) {
snprintf(buf, sizeof buf, "read: %.100s\r\n",
strerror(errno));
buffer_append(&stderr_buffer, buf, strlen(buf));
}
/* Mark that we have seen EOF. */
stdin_eof = 1;
/*
* Send an EOF message to the server unless there is
* data in the buffer. If there is data in the
* buffer, no message will be sent now. Code
* elsewhere will send the EOF when the buffer
* becomes empty if stdin_eof is set.
*/
if (buffer_len(&stdin_buffer) == 0) {
packet_start(SSH_CMSG_EOF);
packet_send();
}
} else if (escape_char1 == SSH_ESCAPECHAR_NONE) {
/*
* Normal successful read, and no escape character.
* Just append the data to buffer.
*/
buffer_append(&stdin_buffer, buf, len);
} else {
/*
* Normal, successful read. But we have an escape
* character and have to process the characters one
* by one.
*/
if (process_escapes(NULL, &stdin_buffer,
&stdout_buffer, &stderr_buffer, buf, len) == -1)
return;
}
}
}
static void
client_process_output(fd_set *writeset)
{
int len;
char buf[100];
/* Write buffered output to stdout. */
if (FD_ISSET(fileno(stdout), writeset)) {
/* Write as much data as possible. */
len = write(fileno(stdout), buffer_ptr(&stdout_buffer),
buffer_len(&stdout_buffer));
if (len <= 0) {
if (errno == EINTR || errno == EAGAIN ||
errno == EWOULDBLOCK)
len = 0;
else {
/*
* An error or EOF was encountered. Put an
* error message to stderr buffer.
*/
snprintf(buf, sizeof buf,
"write stdout: %.50s\r\n", strerror(errno));
buffer_append(&stderr_buffer, buf, strlen(buf));
quit_pending = 1;
return;
}
}
/* Consume printed data from the buffer. */
buffer_consume(&stdout_buffer, len);
}
/* Write buffered output to stderr. */
if (FD_ISSET(fileno(stderr), writeset)) {
/* Write as much data as possible. */
len = write(fileno(stderr), buffer_ptr(&stderr_buffer),
buffer_len(&stderr_buffer));
if (len <= 0) {
if (errno == EINTR || errno == EAGAIN ||
errno == EWOULDBLOCK)
len = 0;
else {
/*
* EOF or error, but can't even print
* error message.
*/
quit_pending = 1;
return;
}
}
/* Consume printed characters from the buffer. */
buffer_consume(&stderr_buffer, len);
}
}
/*
* Get packets from the connection input buffer, and process them as long as
* there are packets available.
@ -1553,18 +1285,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
connection_out = packet_get_connection_out();
max_fd = MAXIMUM(connection_in, connection_out);
if (!compat20) {
/* enable nonblocking unless tty */
if (!isatty(fileno(stdin)))
set_nonblock(fileno(stdin));
if (!isatty(fileno(stdout)))
set_nonblock(fileno(stdout));
if (!isatty(fileno(stderr)))
set_nonblock(fileno(stderr));
max_fd = MAXIMUM(max_fd, fileno(stdin));
max_fd = MAXIMUM(max_fd, fileno(stdout));
max_fd = MAXIMUM(max_fd, fileno(stderr));
}
quit_pending = 0;
escape_char1 = escape_char_arg;
@ -1592,22 +1312,17 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
if (have_pty)
enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
if (compat20) {
session_ident = ssh2_chan_id;
if (session_ident != -1) {
if (escape_char_arg != SSH_ESCAPECHAR_NONE) {
channel_register_filter(session_ident,
client_simple_escape_filter, NULL,
client_filter_cleanup,
client_new_escape_filter_ctx(
escape_char_arg));
}
channel_register_cleanup(session_ident,
client_channel_closed, 0);
session_ident = ssh2_chan_id;
if (session_ident != -1) {
if (escape_char_arg != SSH_ESCAPECHAR_NONE) {
channel_register_filter(session_ident,
client_simple_escape_filter, NULL,
client_filter_cleanup,
client_new_escape_filter_ctx(
escape_char_arg));
}
} else {
/* Check if we should immediately send eof on stdin. */
client_check_initial_eof_on_stdin();
channel_register_cleanup(session_ident,
client_channel_closed, 0);
}
/* Main loop of the client for the interactive session mode. */
@ -1616,7 +1331,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
/* Process buffered packets sent by the server. */
client_process_buffered_input_packets();
if (compat20 && session_closed && !channel_still_open())
if (session_closed && !channel_still_open())
break;
if (ssh_packet_is_rekeying(active_state)) {
@ -1629,13 +1344,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
ssh_err(r));
need_rekeying = 0;
} else {
/*
* Make packets of buffered stdin data, and buffer
* them for sending to the server.
*/
if (!compat20)
client_make_packets_from_stdin_data();
/*
* Make packets from buffered channel data, and
* enqueue them for sending to the server.
@ -1673,16 +1381,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
if (quit_pending)
break;
if (!compat20) {
/* Buffer data from stdin */
client_process_input(readset);
/*
* Process output to stdout and stderr. Output to
* the connection is processed elsewhere (above).
*/
client_process_output(writeset);
}
/*
* Send as much buffered packet data as possible to the
* sender.
@ -1710,14 +1408,12 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
/* Stop watching for window change. */
signal(SIGWINCH, SIG_DFL);
if (compat20) {
packet_start(SSH2_MSG_DISCONNECT);
packet_put_int(SSH2_DISCONNECT_BY_APPLICATION);
packet_put_cstring("disconnected by user");
packet_put_cstring(""); /* language tag */
packet_send();
packet_write_wait();
}
packet_start(SSH2_MSG_DISCONNECT);
packet_put_int(SSH2_DISCONNECT_BY_APPLICATION);
packet_put_cstring("disconnected by user");
packet_put_cstring(""); /* language tag */
packet_send();
packet_write_wait();
channel_free_all();
@ -1796,92 +1492,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
/*********/
static int
client_input_stdout_data(int type, u_int32_t seq, void *ctxt)
{
u_int data_len;
char *data = packet_get_string(&data_len);
packet_check_eom();
buffer_append(&stdout_buffer, data, data_len);
explicit_bzero(data, data_len);
free(data);
return 0;
}
static int
client_input_stderr_data(int type, u_int32_t seq, void *ctxt)
{
u_int data_len;
char *data = packet_get_string(&data_len);
packet_check_eom();
buffer_append(&stderr_buffer, data, data_len);
explicit_bzero(data, data_len);
free(data);
return 0;
}
static int
client_input_exit_status(int type, u_int32_t seq, void *ctxt)
{
exit_status = packet_get_int();
packet_check_eom();
/* Acknowledge the exit. */
packet_start(SSH_CMSG_EXIT_CONFIRMATION);
packet_send();
/*
* Must wait for packet to be sent since we are
* exiting the loop.
*/
packet_write_wait();
/* Flag that we want to exit. */
quit_pending = 1;
return 0;
}
static int
client_input_agent_open(int type, u_int32_t seq, void *ctxt)
{
Channel *c = NULL;
int r, remote_id, sock;
/* Read the remote channel number from the message. */
remote_id = packet_get_int();
packet_check_eom();
/*
* Get a connection to the local authentication agent (this may again
* get forwarded).
*/
if ((r = ssh_get_authentication_socket(&sock)) != 0 &&
r != SSH_ERR_AGENT_NOT_PRESENT)
debug("%s: ssh_get_authentication_socket: %s",
__func__, ssh_err(r));
/*
* If we could not connect the agent, send an error message back to
* the server. This should never happen unless the agent dies,
* because authentication forwarding is only enabled if we have an
* agent.
*/
if (sock >= 0) {
c = channel_new("", SSH_CHANNEL_OPEN, sock, sock,
-1, 0, 0, 0, "authentication agent connection", 1);
c->remote_id = remote_id;
c->force_drain = 1;
}
if (c == NULL) {
packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
packet_put_int(remote_id);
} else {
/* Send a confirmation to the remote host. */
debug("Forwarding authentication connection.");
packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
packet_put_int(remote_id);
packet_put_int(c->self);
}
packet_send();
return 0;
}
static Channel *
client_request_forwarded_tcpip(const char *request_type, int rchan,
u_int rwindow, u_int rmaxpack)
@ -2032,11 +1642,6 @@ client_request_tun_fwd(int tun_mode, int local_tun, int remote_tun)
if (tun_mode == SSH_TUNMODE_NO)
return 0;
if (!compat20) {
error("Tunnel forwarding is not supported for protocol 1");
return -1;
}
debug("Requesting tun unit %d in mode %d", local_tun, tun_mode);
/* Open local tunnel device */
@ -2687,7 +2292,7 @@ client_session2_setup(int id, int want_tty, int want_subsystem,
}
static void
client_init_dispatch_20(void)
client_init_dispatch(void)
{
dispatch_init(&dispatch_protocol_error);
@ -2712,45 +2317,6 @@ client_init_dispatch_20(void)
dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &client_global_request_reply);
}
static void
client_init_dispatch_13(void)
{
dispatch_init(NULL);
dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_close);
dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_close_confirmation);
dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data);
dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open);
dispatch_set(SSH_SMSG_EXITSTATUS, &client_input_exit_status);
dispatch_set(SSH_SMSG_STDERR_DATA, &client_input_stderr_data);
dispatch_set(SSH_SMSG_STDOUT_DATA, &client_input_stdout_data);
dispatch_set(SSH_SMSG_AGENT_OPEN, options.forward_agent ?
&client_input_agent_open : &deny_input_open);
dispatch_set(SSH_SMSG_X11_OPEN, options.forward_x11 ?
&x11_input_open : &deny_input_open);
}
static void
client_init_dispatch_15(void)
{
client_init_dispatch_13();
dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof);
dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, & channel_input_oclose);
}
static void
client_init_dispatch(void)
{
if (compat20)
client_init_dispatch_20();
else if (compat13)
client_init_dispatch_13();
else
client_init_dispatch_15();
}
void
client_stop_mux(void)
{

View File

@ -1,4 +1,4 @@
/* $OpenBSD: compat.c,v 1.102 2017/04/30 23:11:45 djm Exp $ */
/* $OpenBSD: compat.c,v 1.103 2017/04/30 23:13:25 djm Exp $ */
/*
* Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved.
*
@ -39,24 +39,8 @@
#include "match.h"
#include "kex.h"
int compat13 = 0;
int compat20 = 0;
int datafellows = 0;
void
enable_compat20(void)
{
if (compat20)
return;
debug("Enabling compatibility mode for protocol 2.0");
compat20 = 1;
}
void
enable_compat13(void)
{
debug("Enabling compatibility mode for protocol 1.3");
compat13 = 1;
}
/* datafellows bug compatibility */
u_int
compat_datafellows(const char *version)

View File

@ -1,4 +1,4 @@
/* $OpenBSD: compat.h,v 1.48 2015/05/26 23:23:40 dtucker Exp $ */
/* $OpenBSD: compat.h,v 1.49 2017/04/30 23:13:25 djm Exp $ */
/*
* Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved.
@ -63,15 +63,11 @@
#define SSH_BUG_HOSTKEYS 0x20000000
#define SSH_BUG_DHGEX_LARGE 0x40000000
void enable_compat13(void);
void enable_compat20(void);
u_int compat_datafellows(const char *);
int proto_spec(const char *);
char *compat_cipher_proposal(char *);
char *compat_pkalg_proposal(char *);
char *compat_kex_proposal(char *);
extern int compat13;
extern int compat20;
extern int datafellows;
#endif

View File

@ -1,4 +1,4 @@
/* $OpenBSD: dispatch.c,v 1.27 2015/05/01 07:10:01 djm Exp $ */
/* $OpenBSD: dispatch.c,v 1.28 2017/04/30 23:13:25 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -45,8 +45,6 @@ dispatch_protocol_error(int type, u_int32_t seq, void *ctx)
int r;
logit("dispatch_protocol_error: type %d seq %u", type, seq);
if (!compat20)
fatal("protocol error");
if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 ||
(r = sshpkt_put_u32(ssh, seq)) != 0 ||
(r = sshpkt_send(ssh)) != 0 ||

308
nchan.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: nchan.c,v 1.63 2010/01/26 01:28:35 djm Exp $ */
/* $OpenBSD: nchan.c,v 1.64 2017/04/30 23:13:25 djm Exp $ */
/*
* Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved.
*
@ -74,9 +74,6 @@
/*
* ACTIONS: should never update the channel states
*/
static void chan_send_ieof1(Channel *);
static void chan_send_oclose1(Channel *);
static void chan_send_close2(Channel *);
static void chan_send_eof2(Channel *);
static void chan_send_eow2(Channel *);
@ -96,6 +93,7 @@ chan_set_istate(Channel *c, u_int next)
istates[next]);
c->istate = next;
}
static void
chan_set_ostate(Channel *c, u_int next)
{
@ -106,34 +104,6 @@ chan_set_ostate(Channel *c, u_int next)
c->ostate = next;
}
/*
* SSH1 specific implementation of event functions
*/
static void
chan_rcvd_oclose1(Channel *c)
{
debug2("channel %d: rcvd oclose", c->self);
switch (c->istate) {
case CHAN_INPUT_WAIT_OCLOSE:
chan_set_istate(c, CHAN_INPUT_CLOSED);
break;
case CHAN_INPUT_OPEN:
chan_shutdown_read(c);
chan_send_ieof1(c);
chan_set_istate(c, CHAN_INPUT_CLOSED);
break;
case CHAN_INPUT_WAIT_DRAIN:
/* both local read_failed and remote write_failed */
chan_send_ieof1(c);
chan_set_istate(c, CHAN_INPUT_CLOSED);
break;
default:
error("channel %d: protocol error: rcvd_oclose for istate %d",
c->self, c->istate);
return;
}
}
void
chan_read_failed(Channel *c)
{
@ -149,6 +119,7 @@ chan_read_failed(Channel *c)
break;
}
}
void
chan_ibuf_empty(Channel *c)
{
@ -160,14 +131,9 @@ chan_ibuf_empty(Channel *c)
}
switch (c->istate) {
case CHAN_INPUT_WAIT_DRAIN:
if (compat20) {
if (!(c->flags & (CHAN_CLOSE_SENT|CHAN_LOCAL)))
chan_send_eof2(c);
chan_set_istate(c, CHAN_INPUT_CLOSED);
} else {
chan_send_ieof1(c);
chan_set_istate(c, CHAN_INPUT_WAIT_OCLOSE);
}
if (!(c->flags & (CHAN_CLOSE_SENT|CHAN_LOCAL)))
chan_send_eof2(c);
chan_set_istate(c, CHAN_INPUT_CLOSED);
break;
default:
error("channel %d: chan_ibuf_empty for istate %d",
@ -175,44 +141,7 @@ chan_ibuf_empty(Channel *c)
break;
}
}
static void
chan_rcvd_ieof1(Channel *c)
{
debug2("channel %d: rcvd ieof", c->self);
switch (c->ostate) {
case CHAN_OUTPUT_OPEN:
chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
break;
case CHAN_OUTPUT_WAIT_IEOF:
chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
break;
default:
error("channel %d: protocol error: rcvd_ieof for ostate %d",
c->self, c->ostate);
break;
}
}
static void
chan_write_failed1(Channel *c)
{
debug2("channel %d: write failed", c->self);
switch (c->ostate) {
case CHAN_OUTPUT_OPEN:
chan_shutdown_write(c);
chan_send_oclose1(c);
chan_set_ostate(c, CHAN_OUTPUT_WAIT_IEOF);
break;
case CHAN_OUTPUT_WAIT_DRAIN:
chan_shutdown_write(c);
chan_send_oclose1(c);
chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
break;
default:
error("channel %d: chan_write_failed for ostate %d",
c->self, c->ostate);
break;
}
}
void
chan_obuf_empty(Channel *c)
{
@ -225,8 +154,6 @@ chan_obuf_empty(Channel *c)
switch (c->ostate) {
case CHAN_OUTPUT_WAIT_DRAIN:
chan_shutdown_write(c);
if (!compat20)
chan_send_oclose1(c);
chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
break;
default:
@ -235,47 +162,90 @@ chan_obuf_empty(Channel *c)
break;
}
}
static void
chan_send_ieof1(Channel *c)
void
chan_rcvd_eow(Channel *c)
{
debug2("channel %d: send ieof", c->self);
debug2("channel %d: rcvd eow", c->self);
switch (c->istate) {
case CHAN_INPUT_OPEN:
case CHAN_INPUT_WAIT_DRAIN:
packet_start(SSH_MSG_CHANNEL_INPUT_EOF);
packet_put_int(c->remote_id);
packet_send();
break;
default:
error("channel %d: cannot send ieof for istate %d",
c->self, c->istate);
break;
}
}
static void
chan_send_oclose1(Channel *c)
{
debug2("channel %d: send oclose", c->self);
switch (c->ostate) {
case CHAN_OUTPUT_OPEN:
case CHAN_OUTPUT_WAIT_DRAIN:
buffer_clear(&c->output);
packet_start(SSH_MSG_CHANNEL_OUTPUT_CLOSE);
packet_put_int(c->remote_id);
packet_send();
break;
default:
error("channel %d: cannot send oclose for ostate %d",
c->self, c->ostate);
chan_shutdown_read(c);
chan_set_istate(c, CHAN_INPUT_CLOSED);
break;
}
}
/*
* the same for SSH2
*/
static void
chan_rcvd_close2(Channel *c)
chan_send_eof2(Channel *c)
{
debug2("channel %d: send eof", c->self);
switch (c->istate) {
case CHAN_INPUT_WAIT_DRAIN:
packet_start(SSH2_MSG_CHANNEL_EOF);
packet_put_int(c->remote_id);
packet_send();
c->flags |= CHAN_EOF_SENT;
break;
default:
error("channel %d: cannot send eof for istate %d",
c->self, c->istate);
break;
}
}
static void
chan_send_close2(Channel *c)
{
debug2("channel %d: send close", c->self);
if (c->ostate != CHAN_OUTPUT_CLOSED ||
c->istate != CHAN_INPUT_CLOSED) {
error("channel %d: cannot send close for istate/ostate %d/%d",
c->self, c->istate, c->ostate);
} else if (c->flags & CHAN_CLOSE_SENT) {
error("channel %d: already sent close", c->self);
} else {
packet_start(SSH2_MSG_CHANNEL_CLOSE);
packet_put_int(c->remote_id);
packet_send();
c->flags |= CHAN_CLOSE_SENT;
}
}
static void
chan_send_eow2(Channel *c)
{
debug2("channel %d: send eow", c->self);
if (c->ostate == CHAN_OUTPUT_CLOSED) {
error("channel %d: must not sent eow on closed output",
c->self);
return;
}
if (!(datafellows & SSH_NEW_OPENSSH))
return;
packet_start(SSH2_MSG_CHANNEL_REQUEST);
packet_put_int(c->remote_id);
packet_put_cstring("eow@openssh.com");
packet_put_char(0);
packet_send();
}
/* shared */
void
chan_rcvd_ieof(Channel *c)
{
debug2("channel %d: rcvd eof", c->self);
c->flags |= CHAN_EOF_RCVD;
if (c->ostate == CHAN_OUTPUT_OPEN)
chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN &&
buffer_len(&c->output) == 0 &&
!CHANNEL_EFD_OUTPUT_ACTIVE(c))
chan_obuf_empty(c);
}
void
chan_rcvd_oclose(Channel *c)
{
debug2("channel %d: rcvd close", c->self);
if (!(c->flags & CHAN_LOCAL)) {
@ -313,26 +283,7 @@ chan_rcvd_close2(Channel *c)
}
void
chan_rcvd_eow(Channel *c)
{
debug2("channel %d: rcvd eow", c->self);
switch (c->istate) {
case CHAN_INPUT_OPEN:
chan_shutdown_read(c);
chan_set_istate(c, CHAN_INPUT_CLOSED);
break;
}
}
static void
chan_rcvd_eof2(Channel *c)
{
debug2("channel %d: rcvd eof", c->self);
c->flags |= CHAN_EOF_RCVD;
if (c->ostate == CHAN_OUTPUT_OPEN)
chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
}
static void
chan_write_failed2(Channel *c)
chan_write_failed(Channel *c)
{
debug2("channel %d: write failed", c->self);
switch (c->ostate) {
@ -349,88 +300,6 @@ chan_write_failed2(Channel *c)
break;
}
}
static void
chan_send_eof2(Channel *c)
{
debug2("channel %d: send eof", c->self);
switch (c->istate) {
case CHAN_INPUT_WAIT_DRAIN:
packet_start(SSH2_MSG_CHANNEL_EOF);
packet_put_int(c->remote_id);
packet_send();
c->flags |= CHAN_EOF_SENT;
break;
default:
error("channel %d: cannot send eof for istate %d",
c->self, c->istate);
break;
}
}
static void
chan_send_close2(Channel *c)
{
debug2("channel %d: send close", c->self);
if (c->ostate != CHAN_OUTPUT_CLOSED ||
c->istate != CHAN_INPUT_CLOSED) {
error("channel %d: cannot send close for istate/ostate %d/%d",
c->self, c->istate, c->ostate);
} else if (c->flags & CHAN_CLOSE_SENT) {
error("channel %d: already sent close", c->self);
} else {
packet_start(SSH2_MSG_CHANNEL_CLOSE);
packet_put_int(c->remote_id);
packet_send();
c->flags |= CHAN_CLOSE_SENT;
}
}
static void
chan_send_eow2(Channel *c)
{
debug2("channel %d: send eow", c->self);
if (c->ostate == CHAN_OUTPUT_CLOSED) {
error("channel %d: must not sent eow on closed output",
c->self);
return;
}
if (!(datafellows & SSH_NEW_OPENSSH))
return;
packet_start(SSH2_MSG_CHANNEL_REQUEST);
packet_put_int(c->remote_id);
packet_put_cstring("eow@openssh.com");
packet_put_char(0);
packet_send();
}
/* shared */
void
chan_rcvd_ieof(Channel *c)
{
if (compat20)
chan_rcvd_eof2(c);
else
chan_rcvd_ieof1(c);
if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN &&
buffer_len(&c->output) == 0 &&
!CHANNEL_EFD_OUTPUT_ACTIVE(c))
chan_obuf_empty(c);
}
void
chan_rcvd_oclose(Channel *c)
{
if (compat20)
chan_rcvd_close2(c);
else
chan_rcvd_oclose1(c);
}
void
chan_write_failed(Channel *c)
{
if (compat20)
chan_write_failed2(c);
else
chan_write_failed1(c);
}
void
chan_mark_dead(Channel *c)
@ -447,10 +316,6 @@ chan_is_dead(Channel *c, int do_send)
}
if (c->istate != CHAN_INPUT_CLOSED || c->ostate != CHAN_OUTPUT_CLOSED)
return 0;
if (!compat20) {
debug2("channel %d: is dead", c->self);
return 1;
}
if ((datafellows & SSH_BUG_EXTEOF) &&
c->extended_usage == CHAN_EXTENDED_WRITE &&
c->efd != -1 &&
@ -488,7 +353,7 @@ static void
chan_shutdown_write(Channel *c)
{
buffer_clear(&c->output);
if (compat20 && c->type == SSH_CHANNEL_LARVAL)
if (c->type == SSH_CHANNEL_LARVAL)
return;
/* shutdown failure is allowed if write failed already */
debug2("channel %d: close_write", c->self);
@ -504,10 +369,11 @@ chan_shutdown_write(Channel *c)
c->self, c->wfd, strerror(errno));
}
}
static void
chan_shutdown_read(Channel *c)
{
if (compat20 && c->type == SSH_CHANNEL_LARVAL)
if (c->type == SSH_CHANNEL_LARVAL)
return;
debug2("channel %d: close_read", c->self);
if (c->sock != -1) {

391
packet.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: packet.c,v 1.248 2017/04/30 23:10:43 djm Exp $ */
/* $OpenBSD: packet.c,v 1.249 2017/04/30 23:13:25 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -278,8 +278,8 @@ ssh_packet_set_input_hook(struct ssh *ssh, ssh_packet_hook_fn *hook, void *ctx)
int
ssh_packet_is_rekeying(struct ssh *ssh)
{
return compat20 &&
(ssh->state->rekeying || (ssh->kex != NULL && ssh->kex->done == 0));
return ssh->state->rekeying ||
(ssh->kex != NULL && ssh->kex->done == 0);
}
/*
@ -698,7 +698,7 @@ ssh_packet_start_compression(struct ssh *ssh, int level)
{
int r;
if (ssh->state->packet_compression && !compat20)
if (ssh->state->packet_compression)
return SSH_ERR_INTERNAL_ERROR;
ssh->state->packet_compression = 1;
if ((r = ssh_packet_init_compression(ssh)) != 0 ||
@ -814,99 +814,6 @@ ssh_packet_set_encryption_key(struct ssh *ssh, const u_char *key, u_int keylen,
fatal("no SSH protocol 1 support");
}
/*
* Finalizes and sends the packet. If the encryption key has been set,
* encrypts the packet before sending.
*/
int
ssh_packet_send1(struct ssh *ssh)
{
struct session_state *state = ssh->state;
u_char buf[8], *cp;
int r, padding, len;
u_int checksum;
/*
* If using packet compression, compress the payload of the outgoing
* packet.
*/
if (state->packet_compression) {
sshbuf_reset(state->compression_buffer);
/* Skip padding. */
if ((r = sshbuf_consume(state->outgoing_packet, 8)) != 0)
goto out;
/* padding */
if ((r = sshbuf_put(state->compression_buffer,
"\0\0\0\0\0\0\0\0", 8)) != 0)
goto out;
if ((r = compress_buffer(ssh, state->outgoing_packet,
state->compression_buffer)) != 0)
goto out;
sshbuf_reset(state->outgoing_packet);
if ((r = sshbuf_putb(state->outgoing_packet,
state->compression_buffer)) != 0)
goto out;
}
/* Compute packet length without padding (add checksum, remove padding). */
len = sshbuf_len(state->outgoing_packet) + 4 - 8;
/* Insert padding. Initialized to zero in packet_start1() */
padding = 8 - len % 8;
if (!cipher_ctx_is_plaintext(state->send_context)) {
cp = sshbuf_mutable_ptr(state->outgoing_packet);
if (cp == NULL) {
r = SSH_ERR_INTERNAL_ERROR;
goto out;
}
arc4random_buf(cp + 8 - padding, padding);
}
if ((r = sshbuf_consume(state->outgoing_packet, 8 - padding)) != 0)
goto out;
/* Add check bytes. */
checksum = ssh_crc32(sshbuf_ptr(state->outgoing_packet),
sshbuf_len(state->outgoing_packet));
POKE_U32(buf, checksum);
if ((r = sshbuf_put(state->outgoing_packet, buf, 4)) != 0)
goto out;
#ifdef PACKET_DEBUG
fprintf(stderr, "packet_send plain: ");
sshbuf_dump(state->outgoing_packet, stderr);
#endif
/* Append to output. */
POKE_U32(buf, len);
if ((r = sshbuf_put(state->output, buf, 4)) != 0)
goto out;
if ((r = sshbuf_reserve(state->output,
sshbuf_len(state->outgoing_packet), &cp)) != 0)
goto out;
if ((r = cipher_crypt(state->send_context, 0, cp,
sshbuf_ptr(state->outgoing_packet),
sshbuf_len(state->outgoing_packet), 0, 0)) != 0)
goto out;
#ifdef PACKET_DEBUG
fprintf(stderr, "encrypted: ");
sshbuf_dump(state->output, stderr);
#endif
state->p_send.packets++;
state->p_send.bytes += len +
sshbuf_len(state->outgoing_packet);
sshbuf_reset(state->outgoing_packet);
/*
* Note that the packet is now only buffered in output. It won't be
* actually sent until ssh_packet_write_wait or ssh_packet_write_poll
* is called.
*/
r = 0;
out:
return r;
}
int
ssh_set_newkeys(struct ssh *ssh, int mode)
{
@ -1397,13 +1304,6 @@ ssh_packet_read_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
r = ssh_packet_read_poll_seqnr(ssh, typep, seqnr_p);
if (r != 0)
break;
if (!compat20 && (
*typep == SSH_SMSG_SUCCESS
|| *typep == SSH_SMSG_FAILURE
|| *typep == SSH_CMSG_EOF
|| *typep == SSH_CMSG_EXIT_CONFIRMATION))
if ((r = sshpkt_get_end(ssh)) != 0)
break;
/* If we got a packet, return it. */
if (*typep != SSH_MSG_NONE)
break;
@ -1924,75 +1824,48 @@ ssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
for (;;) {
msg = NULL;
if (compat20) {
r = ssh_packet_read_poll2(ssh, typep, seqnr_p);
if (r != 0)
r = ssh_packet_read_poll2(ssh, typep, seqnr_p);
if (r != 0)
return r;
if (*typep) {
state->keep_alive_timeouts = 0;
DBG(debug("received packet type %d", *typep));
}
switch (*typep) {
case SSH2_MSG_IGNORE:
debug3("Received SSH2_MSG_IGNORE");
break;
case SSH2_MSG_DEBUG:
if ((r = sshpkt_get_u8(ssh, NULL)) != 0 ||
(r = sshpkt_get_string(ssh, &msg, NULL)) != 0 ||
(r = sshpkt_get_string(ssh, NULL, NULL)) != 0) {
free(msg);
return r;
if (*typep) {
state->keep_alive_timeouts = 0;
DBG(debug("received packet type %d", *typep));
}
switch (*typep) {
case SSH2_MSG_IGNORE:
debug3("Received SSH2_MSG_IGNORE");
break;
case SSH2_MSG_DEBUG:
if ((r = sshpkt_get_u8(ssh, NULL)) != 0 ||
(r = sshpkt_get_string(ssh, &msg, NULL)) != 0 ||
(r = sshpkt_get_string(ssh, NULL, NULL)) != 0) {
free(msg);
return r;
}
debug("Remote: %.900s", msg);
free(msg);
break;
case SSH2_MSG_DISCONNECT:
if ((r = sshpkt_get_u32(ssh, &reason)) != 0 ||
(r = sshpkt_get_string(ssh, &msg, NULL)) != 0)
return r;
/* Ignore normal client exit notifications */
do_log2(ssh->state->server_side &&
reason == SSH2_DISCONNECT_BY_APPLICATION ?
SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR,
"Received disconnect from %s port %d:"
"%u: %.400s", ssh_remote_ipaddr(ssh),
ssh_remote_port(ssh), reason, msg);
free(msg);
return SSH_ERR_DISCONNECTED;
case SSH2_MSG_UNIMPLEMENTED:
if ((r = sshpkt_get_u32(ssh, &seqnr)) != 0)
return r;
debug("Received SSH2_MSG_UNIMPLEMENTED for %u",
seqnr);
break;
default:
return 0;
}
} else {
r = ssh_packet_read_poll1(ssh, typep);
switch (*typep) {
case SSH_MSG_NONE:
return SSH_MSG_NONE;
case SSH_MSG_IGNORE:
break;
case SSH_MSG_DEBUG:
if ((r = sshpkt_get_string(ssh, &msg, NULL)) != 0)
return r;
debug("Remote: %.900s", msg);
free(msg);
break;
case SSH_MSG_DISCONNECT:
if ((r = sshpkt_get_string(ssh, &msg, NULL)) != 0)
return r;
error("Received disconnect from %s port %d: "
"%.400s", ssh_remote_ipaddr(ssh),
ssh_remote_port(ssh), msg);
free(msg);
return SSH_ERR_DISCONNECTED;
default:
DBG(debug("received packet type %d", *typep));
return 0;
}
debug("Remote: %.900s", msg);
free(msg);
break;
case SSH2_MSG_DISCONNECT:
if ((r = sshpkt_get_u32(ssh, &reason)) != 0 ||
(r = sshpkt_get_string(ssh, &msg, NULL)) != 0)
return r;
/* Ignore normal client exit notifications */
do_log2(ssh->state->server_side &&
reason == SSH2_DISCONNECT_BY_APPLICATION ?
SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR,
"Received disconnect from %s port %d:"
"%u: %.400s", ssh_remote_ipaddr(ssh),
ssh_remote_port(ssh), reason, msg);
free(msg);
return SSH_ERR_DISCONNECTED;
case SSH2_MSG_UNIMPLEMENTED:
if ((r = sshpkt_get_u32(ssh, &seqnr)) != 0)
return r;
debug("Received SSH2_MSG_UNIMPLEMENTED for %u",
seqnr);
break;
default:
return 0;
}
}
}
@ -2044,27 +1917,19 @@ ssh_packet_send_debug(struct ssh *ssh, const char *fmt,...)
va_list args;
int r;
if (compat20 && (ssh->compat & SSH_BUG_DEBUG))
if ((ssh->compat & SSH_BUG_DEBUG))
return;
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
if (compat20) {
if ((r = sshpkt_start(ssh, SSH2_MSG_DEBUG)) != 0 ||
(r = sshpkt_put_u8(ssh, 0)) != 0 || /* always display */
(r = sshpkt_put_cstring(ssh, buf)) != 0 ||
(r = sshpkt_put_cstring(ssh, "")) != 0 ||
(r = sshpkt_send(ssh)) != 0)
fatal("%s: %s", __func__, ssh_err(r));
} else {
if ((r = sshpkt_start(ssh, SSH_MSG_DEBUG)) != 0 ||
(r = sshpkt_put_cstring(ssh, buf)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
fatal("%s: %s", __func__, ssh_err(r));
}
if ((r = ssh_packet_write_wait(ssh)) != 0)
if ((r = sshpkt_start(ssh, SSH2_MSG_DEBUG)) != 0 ||
(r = sshpkt_put_u8(ssh, 0)) != 0 || /* always display */
(r = sshpkt_put_cstring(ssh, buf)) != 0 ||
(r = sshpkt_put_cstring(ssh, "")) != 0 ||
(r = sshpkt_send(ssh)) != 0 ||
(r = ssh_packet_write_wait(ssh)) != 0)
fatal("%s: %s", __func__, ssh_err(r));
}
@ -2385,8 +2250,7 @@ ssh_packet_send_ignore(struct ssh *ssh, int nbytes)
u_int32_t rnd = 0;
int r, i;
if ((r = sshpkt_start(ssh, compat20 ?
SSH2_MSG_IGNORE : SSH_MSG_IGNORE)) != 0 ||
if ((r = sshpkt_start(ssh, SSH2_MSG_IGNORE)) != 0 ||
(r = sshpkt_put_u32(ssh, nbytes)) != 0)
fatal("%s: %s", __func__, ssh_err(r));
for (i = 0; i < nbytes; i++) {
@ -2531,38 +2395,22 @@ ssh_packet_get_state(struct ssh *ssh, struct sshbuf *m)
struct session_state *state = ssh->state;
u_char *p;
size_t slen, rlen;
int r, ssh1cipher;
int r;
if (!compat20) {
ssh1cipher = cipher_ctx_get_number(state->receive_context);
slen = cipher_get_keyiv_len(state->send_context);
rlen = cipher_get_keyiv_len(state->receive_context);
if ((r = sshbuf_put_u32(m, state->remote_protocol_flags)) != 0 ||
(r = sshbuf_put_u32(m, ssh1cipher)) != 0 ||
(r = sshbuf_put_string(m, state->ssh1_key, state->ssh1_keylen)) != 0 ||
(r = sshbuf_put_u32(m, slen)) != 0 ||
(r = sshbuf_reserve(m, slen, &p)) != 0 ||
(r = cipher_get_keyiv(state->send_context, p, slen)) != 0 ||
(r = sshbuf_put_u32(m, rlen)) != 0 ||
(r = sshbuf_reserve(m, rlen, &p)) != 0 ||
(r = cipher_get_keyiv(state->receive_context, p, rlen)) != 0)
return r;
} else {
if ((r = kex_to_blob(m, ssh->kex)) != 0 ||
(r = newkeys_to_blob(m, ssh, MODE_OUT)) != 0 ||
(r = newkeys_to_blob(m, ssh, MODE_IN)) != 0 ||
(r = sshbuf_put_u64(m, state->rekey_limit)) != 0 ||
(r = sshbuf_put_u32(m, state->rekey_interval)) != 0 ||
(r = sshbuf_put_u32(m, state->p_send.seqnr)) != 0 ||
(r = sshbuf_put_u64(m, state->p_send.blocks)) != 0 ||
(r = sshbuf_put_u32(m, state->p_send.packets)) != 0 ||
(r = sshbuf_put_u64(m, state->p_send.bytes)) != 0 ||
(r = sshbuf_put_u32(m, state->p_read.seqnr)) != 0 ||
(r = sshbuf_put_u64(m, state->p_read.blocks)) != 0 ||
(r = sshbuf_put_u32(m, state->p_read.packets)) != 0 ||
(r = sshbuf_put_u64(m, state->p_read.bytes)) != 0)
return r;
}
if ((r = kex_to_blob(m, ssh->kex)) != 0 ||
(r = newkeys_to_blob(m, ssh, MODE_OUT)) != 0 ||
(r = newkeys_to_blob(m, ssh, MODE_IN)) != 0 ||
(r = sshbuf_put_u64(m, state->rekey_limit)) != 0 ||
(r = sshbuf_put_u32(m, state->rekey_interval)) != 0 ||
(r = sshbuf_put_u32(m, state->p_send.seqnr)) != 0 ||
(r = sshbuf_put_u64(m, state->p_send.blocks)) != 0 ||
(r = sshbuf_put_u32(m, state->p_send.packets)) != 0 ||
(r = sshbuf_put_u64(m, state->p_send.bytes)) != 0 ||
(r = sshbuf_put_u32(m, state->p_read.seqnr)) != 0 ||
(r = sshbuf_put_u64(m, state->p_read.blocks)) != 0 ||
(r = sshbuf_put_u32(m, state->p_read.packets)) != 0 ||
(r = sshbuf_put_u64(m, state->p_read.bytes)) != 0)
return r;
slen = cipher_get_keycontext(state->send_context, NULL);
rlen = cipher_get_keycontext(state->receive_context, NULL);
@ -2701,53 +2549,34 @@ int
ssh_packet_set_state(struct ssh *ssh, struct sshbuf *m)
{
struct session_state *state = ssh->state;
const u_char *ssh1key, *ivin, *ivout, *keyin, *keyout, *input, *output;
size_t ssh1keylen, rlen, slen, ilen, olen;
const u_char *keyin, *keyout, *input, *output;
size_t rlen, slen, ilen, olen;
int r;
u_int ssh1cipher = 0;
if (!compat20) {
if ((r = sshbuf_get_u32(m, &state->remote_protocol_flags)) != 0 ||
(r = sshbuf_get_u32(m, &ssh1cipher)) != 0 ||
(r = sshbuf_get_string_direct(m, &ssh1key, &ssh1keylen)) != 0 ||
(r = sshbuf_get_string_direct(m, &ivout, &slen)) != 0 ||
(r = sshbuf_get_string_direct(m, &ivin, &rlen)) != 0)
return r;
if (ssh1cipher > INT_MAX)
return SSH_ERR_KEY_UNKNOWN_CIPHER;
ssh_packet_set_encryption_key(ssh, ssh1key, ssh1keylen,
(int)ssh1cipher);
if (cipher_get_keyiv_len(state->send_context) != (int)slen ||
cipher_get_keyiv_len(state->receive_context) != (int)rlen)
return SSH_ERR_INVALID_FORMAT;
if ((r = cipher_set_keyiv(state->send_context, ivout)) != 0 ||
(r = cipher_set_keyiv(state->receive_context, ivin)) != 0)
return r;
} else {
if ((r = kex_from_blob(m, &ssh->kex)) != 0 ||
(r = newkeys_from_blob(m, ssh, MODE_OUT)) != 0 ||
(r = newkeys_from_blob(m, ssh, MODE_IN)) != 0 ||
(r = sshbuf_get_u64(m, &state->rekey_limit)) != 0 ||
(r = sshbuf_get_u32(m, &state->rekey_interval)) != 0 ||
(r = sshbuf_get_u32(m, &state->p_send.seqnr)) != 0 ||
(r = sshbuf_get_u64(m, &state->p_send.blocks)) != 0 ||
(r = sshbuf_get_u32(m, &state->p_send.packets)) != 0 ||
(r = sshbuf_get_u64(m, &state->p_send.bytes)) != 0 ||
(r = sshbuf_get_u32(m, &state->p_read.seqnr)) != 0 ||
(r = sshbuf_get_u64(m, &state->p_read.blocks)) != 0 ||
(r = sshbuf_get_u32(m, &state->p_read.packets)) != 0 ||
(r = sshbuf_get_u64(m, &state->p_read.bytes)) != 0)
return r;
/*
* We set the time here so that in post-auth privsep slave we
* count from the completion of the authentication.
*/
state->rekey_time = monotime();
/* XXX ssh_set_newkeys overrides p_read.packets? XXX */
if ((r = ssh_set_newkeys(ssh, MODE_IN)) != 0 ||
(r = ssh_set_newkeys(ssh, MODE_OUT)) != 0)
return r;
}
if ((r = kex_from_blob(m, &ssh->kex)) != 0 ||
(r = newkeys_from_blob(m, ssh, MODE_OUT)) != 0 ||
(r = newkeys_from_blob(m, ssh, MODE_IN)) != 0 ||
(r = sshbuf_get_u64(m, &state->rekey_limit)) != 0 ||
(r = sshbuf_get_u32(m, &state->rekey_interval)) != 0 ||
(r = sshbuf_get_u32(m, &state->p_send.seqnr)) != 0 ||
(r = sshbuf_get_u64(m, &state->p_send.blocks)) != 0 ||
(r = sshbuf_get_u32(m, &state->p_send.packets)) != 0 ||
(r = sshbuf_get_u64(m, &state->p_send.bytes)) != 0 ||
(r = sshbuf_get_u32(m, &state->p_read.seqnr)) != 0 ||
(r = sshbuf_get_u64(m, &state->p_read.blocks)) != 0 ||
(r = sshbuf_get_u32(m, &state->p_read.packets)) != 0 ||
(r = sshbuf_get_u64(m, &state->p_read.bytes)) != 0)
return r;
/*
* We set the time here so that in post-auth privsep slave we
* count from the completion of the authentication.
*/
state->rekey_time = monotime();
/* XXX ssh_set_newkeys overrides p_read.packets? XXX */
if ((r = ssh_set_newkeys(ssh, MODE_IN)) != 0 ||
(r = ssh_set_newkeys(ssh, MODE_OUT)) != 0)
return r;
if ((r = sshbuf_get_string_direct(m, &keyout, &slen)) != 0 ||
(r = sshbuf_get_string_direct(m, &keyin, &rlen)) != 0)
return r;
@ -2925,15 +2754,13 @@ sshpkt_ptr(struct ssh *ssh, size_t *lenp)
int
sshpkt_start(struct ssh *ssh, u_char type)
{
u_char buf[9];
int len;
u_char buf[6]; /* u32 packet length, u8 pad len, u8 type */
DBG(debug("packet_start[%d]", type));
len = compat20 ? 6 : 9;
memset(buf, 0, len - 1);
buf[len - 1] = type;
memset(buf, 0, sizeof(buf));
buf[sizeof(buf) - 1] = type;
sshbuf_reset(ssh->state->outgoing_packet);
return sshbuf_put(ssh->state->outgoing_packet, buf, len);
return sshbuf_put(ssh->state->outgoing_packet, buf, sizeof(buf));
}
static int
@ -2973,10 +2800,7 @@ sshpkt_send(struct ssh *ssh)
{
if (ssh->state && ssh->state->mux)
return ssh_packet_send_mux(ssh);
if (compat20)
return ssh_packet_send2(ssh);
else
return ssh_packet_send1(ssh);
return ssh_packet_send2(ssh);
}
int
@ -2990,19 +2814,12 @@ sshpkt_disconnect(struct ssh *ssh, const char *fmt,...)
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
if (compat20) {
if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT)) != 0 ||
(r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_PROTOCOL_ERROR)) != 0 ||
(r = sshpkt_put_cstring(ssh, buf)) != 0 ||
(r = sshpkt_put_cstring(ssh, "")) != 0 ||
(r = sshpkt_send(ssh)) != 0)
return r;
} else {
if ((r = sshpkt_start(ssh, SSH_MSG_DISCONNECT)) != 0 ||
(r = sshpkt_put_cstring(ssh, buf)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
return r;
}
if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT)) != 0 ||
(r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_PROTOCOL_ERROR)) != 0 ||
(r = sshpkt_put_cstring(ssh, buf)) != 0 ||
(r = sshpkt_put_cstring(ssh, "")) != 0 ||
(r = sshpkt_send(ssh)) != 0)
return r;
return 0;
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: packet.h,v 1.76 2017/02/03 23:03:33 djm Exp $ */
/* $OpenBSD: packet.h,v 1.77 2017/04/30 23:13:25 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -112,7 +112,6 @@ int ssh_packet_set_log_preamble(struct ssh *, const char *, ...)
int ssh_packet_log_type(u_char);
int ssh_packet_send1(struct ssh *);
int ssh_packet_send2_wrapped(struct ssh *);
int ssh_packet_send2(struct ssh *);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-keyscan.c,v 1.110 2017/04/30 23:10:43 djm Exp $ */
/* $OpenBSD: ssh-keyscan.c,v 1.111 2017/04/30 23:13:25 djm Exp $ */
/*
* Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>.
*
@ -221,7 +221,6 @@ keygrab_ssh2(con *c)
char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
int r;
enable_compat20();
switch (c->c_keytype) {
case KT_DSA:
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ?

174
ssh.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh.c,v 1.454 2017/04/30 23:11:45 djm Exp $ */
/* $OpenBSD: ssh.c,v 1.455 2017/04/30 23:13:25 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -209,7 +209,6 @@ usage(void)
exit(255);
}
static int ssh_session(void);
static int ssh_session2(void);
static void load_public_identity_files(void);
static void main_sigchld_handler(int);
@ -1243,7 +1242,6 @@ main(int ac, char **av)
if ((sock = muxclient(options.control_path)) >= 0) {
packet_set_connection(sock, sock);
ssh = active_state; /* XXX */
enable_compat20(); /* XXX */
packet_set_mux();
goto skip_connect;
}
@ -1447,7 +1445,7 @@ main(int ac, char **av)
}
skip_connect:
exit_status = compat20 ? ssh_session2() : ssh_session();
exit_status = ssh_session2();
packet_close();
if (options.control_path != NULL && muxserver_sock != -1)
@ -1591,8 +1589,6 @@ ssh_init_stdio_forwarding(void)
if (options.stdio_forward_host == NULL)
return;
if (!compat20)
fatal("stdio forwarding require Protocol 2");
debug3("%s: %s:%d", __func__, options.stdio_forward_host,
options.stdio_forward_port);
@ -1691,172 +1687,6 @@ check_agent_present(void)
}
}
static int
ssh_session(void)
{
int type;
int interactive = 0;
int have_tty = 0;
struct winsize ws;
char *cp;
const char *display;
char *proto = NULL, *data = NULL;
/* Enable compression if requested. */
if (options.compression) {
debug("Requesting compression at level %d.",
options.compression_level);
if (options.compression_level < 1 ||
options.compression_level > 9)
fatal("Compression level must be from 1 (fast) to "
"9 (slow, best).");
/* Send the request. */
packet_start(SSH_CMSG_REQUEST_COMPRESSION);
packet_put_int(options.compression_level);
packet_send();
packet_write_wait();
type = packet_read();
if (type == SSH_SMSG_SUCCESS)
packet_start_compression(options.compression_level);
else if (type == SSH_SMSG_FAILURE)
logit("Warning: Remote host refused compression.");
else
packet_disconnect("Protocol error waiting for "
"compression response.");
}
/* Allocate a pseudo tty if appropriate. */
if (tty_flag) {
debug("Requesting pty.");
/* Start the packet. */
packet_start(SSH_CMSG_REQUEST_PTY);
/* Store TERM in the packet. There is no limit on the
length of the string. */
cp = getenv("TERM");
if (!cp)
cp = "";
packet_put_cstring(cp);
/* Store window size in the packet. */
if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
memset(&ws, 0, sizeof(ws));
packet_put_int((u_int)ws.ws_row);
packet_put_int((u_int)ws.ws_col);
packet_put_int((u_int)ws.ws_xpixel);
packet_put_int((u_int)ws.ws_ypixel);
/* Store tty modes in the packet. */
tty_make_modes(fileno(stdin), NULL);
/* Send the packet, and wait for it to leave. */
packet_send();
packet_write_wait();
/* Read response from the server. */
type = packet_read();
if (type == SSH_SMSG_SUCCESS) {
interactive = 1;
have_tty = 1;
} else if (type == SSH_SMSG_FAILURE)
logit("Warning: Remote host failed or refused to "
"allocate a pseudo tty.");
else
packet_disconnect("Protocol error waiting for pty "
"request response.");
}
/* Request X11 forwarding if enabled and DISPLAY is set. */
display = getenv("DISPLAY");
if (display == NULL && options.forward_x11)
debug("X11 forwarding requested but DISPLAY not set");
if (options.forward_x11 && client_x11_get_proto(display,
options.xauth_location, options.forward_x11_trusted,
options.forward_x11_timeout, &proto, &data) == 0) {
/* Request forwarding with authentication spoofing. */
debug("Requesting X11 forwarding with authentication "
"spoofing.");
x11_request_forwarding_with_spoofing(0, display, proto,
data, 0);
/* Read response from the server. */
type = packet_read();
if (type == SSH_SMSG_SUCCESS) {
interactive = 1;
} else if (type == SSH_SMSG_FAILURE) {
logit("Warning: Remote host denied X11 forwarding.");
} else {
packet_disconnect("Protocol error waiting for X11 "
"forwarding");
}
}
/* Tell the packet module whether this is an interactive session. */
packet_set_interactive(interactive,
options.ip_qos_interactive, options.ip_qos_bulk);
/* Request authentication agent forwarding if appropriate. */
check_agent_present();
if (options.forward_agent) {
debug("Requesting authentication agent forwarding.");
auth_request_forwarding();
/* Read response from the server. */
type = packet_read();
packet_check_eom();
if (type != SSH_SMSG_SUCCESS)
logit("Warning: Remote host denied authentication agent forwarding.");
}
/* Initiate port forwardings. */
ssh_init_stdio_forwarding();
ssh_init_forwarding();
/* Execute a local command */
if (options.local_command != NULL &&
options.permit_local_command)
ssh_local_cmd(options.local_command);
/*
* If requested and we are not interested in replies to remote
* forwarding requests, then let ssh continue in the background.
*/
if (fork_after_authentication_flag) {
if (options.exit_on_forward_failure &&
options.num_remote_forwards > 0) {
debug("deferring postauth fork until remote forward "
"confirmation received");
} else
fork_postauth();
}
/*
* If a command was specified on the command line, execute the
* command now. Otherwise request the server to start a shell.
*/
if (buffer_len(&command) > 0) {
int len = buffer_len(&command);
if (len > 900)
len = 900;
debug("Sending command: %.*s", len,
(u_char *)buffer_ptr(&command));
packet_start(SSH_CMSG_EXEC_CMD);
packet_put_string(buffer_ptr(&command), buffer_len(&command));
packet_send();
packet_write_wait();
} else {
debug("Requesting shell.");
packet_start(SSH_CMSG_EXEC_SHELL);
packet_send();
packet_write_wait();
}
/* Enter the interactive session. */
return client_loop(have_tty, tty_flag ?
options.escape_char : SSH_ESCAPECHAR_NONE, 0);
}
/* request pty/x11/agent/tcpfwd/shell for channel */
static void
ssh_session2_setup(int id, int success, void *arg)
{

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh_api.c,v 1.7 2016/05/04 14:22:33 markus Exp $ */
/* $OpenBSD: ssh_api.c,v 1.8 2017/04/30 23:13:25 djm Exp $ */
/*
* Copyright (c) 2012 Markus Friedl. All rights reserved.
*
@ -371,7 +371,6 @@ _ssh_read_banner(struct ssh *ssh, char **bannerp)
}
if (remote_major != 2)
return SSH_ERR_PROTOCOL_MISMATCH;
enable_compat20();
chop(buf);
debug("Remote version string %.100s", buf);
if ((*bannerp = strdup(buf)) == NULL)

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshconnect.c,v 1.275 2017/04/30 23:11:45 djm Exp $ */
/* $OpenBSD: sshconnect.c,v 1.276 2017/04/30 23:13:25 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -524,13 +524,8 @@ static void
send_client_banner(int connection_out, int minor1)
{
/* Send our own protocol version identification. */
if (compat20) {
xasprintf(&client_version_string, "SSH-%d.%d-%.100s\r\n",
PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION);
} else {
xasprintf(&client_version_string, "SSH-%d.%d-%.100s\n",
PROTOCOL_MAJOR_1, minor1, SSH_VERSION);
}
xasprintf(&client_version_string, "SSH-%d.%d-%.100s\r\n",
PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION);
if (atomicio(vwrite, connection_out, client_version_string,
strlen(client_version_string)) != strlen(client_version_string))
fatal("write: %.100s", strerror(errno));
@ -559,7 +554,6 @@ ssh_exchange_identification(int timeout_ms)
fdsetsz = howmany(connection_in + 1, NFDBITS) * sizeof(fd_mask);
fdset = xcalloc(1, fdsetsz);
enable_compat20();
send_client_banner(connection_out, 0);
client_banner_sent = 1;
@ -628,14 +622,11 @@ ssh_exchange_identification(int timeout_ms)
mismatch = 0;
switch (remote_major) {
case 1:
if (remote_minor == 99)
enable_compat20();
else
mismatch = 1;
break;
case 2:
enable_compat20();
break;
case 1:
if (remote_minor != 99)
mismatch = 1;
break;
default:
mismatch = 1;
@ -1243,8 +1234,7 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
host_key->cert->principals[i]);
}
} else {
debug("Server host key: %s %s", compat20 ?
sshkey_ssh_name(host_key) : sshkey_type(host_key), fp);
debug("Server host key: %s %s", sshkey_ssh_name(host_key), fp);
}
if (sshkey_equal(previous_host_key, host_key)) {
@ -1349,12 +1339,8 @@ ssh_login(Sensitive *sensitive, const char *orighost,
/* key exchange */
/* authenticate user */
debug("Authenticating to %s:%d as '%s'", host, port, server_user);
if (compat20) {
ssh_kex2(host, hostaddr, port);
ssh_userauth2(local_user, server_user, host, sensitive);
} else {
fatal("ssh1 is not supported");
}
ssh_kex2(host, hostaddr, port);
ssh_userauth2(local_user, server_user, host, sensitive);
free(local_user);
}

8
sshd.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshd.c,v 1.485 2017/03/15 03:52:30 deraadt Exp $ */
/* $OpenBSD: sshd.c,v 1.486 2017/04/30 23:13:25 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -450,10 +450,8 @@ sshd_exchange_identification(struct ssh *ssh, int sock_in, int sock_out)
chop(server_version_string);
debug("Local version string %.200s", server_version_string);
if (remote_major == 2 ||
(remote_major == 1 && remote_minor == 99)) {
enable_compat20();
} else {
if (remote_major != 2 ||
(remote_major == 1 && remote_minor != 99)) {
s = "Protocol major versions differ.\n";
(void) atomicio(vwrite, sock_out, s, strlen(s));
close(sock_in);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ttymodes.c,v 1.30 2016/05/04 14:22:33 markus Exp $ */
/* $OpenBSD: ttymodes.c,v 1.31 2017/04/30 23:13:25 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -283,18 +283,10 @@ tty_make_modes(int fd, struct termios *tiop)
int baud;
Buffer buf;
int tty_op_ospeed, tty_op_ispeed;
void (*put_arg)(Buffer *, u_int);
buffer_init(&buf);
if (compat20) {
tty_op_ospeed = TTY_OP_OSPEED_PROTO2;
tty_op_ispeed = TTY_OP_ISPEED_PROTO2;
put_arg = buffer_put_int;
} else {
tty_op_ospeed = TTY_OP_OSPEED_PROTO1;
tty_op_ispeed = TTY_OP_ISPEED_PROTO1;
put_arg = (void (*)(Buffer *, u_int)) buffer_put_char;
}
tty_op_ospeed = TTY_OP_OSPEED_PROTO2;
tty_op_ispeed = TTY_OP_ISPEED_PROTO2;
if (tiop == NULL) {
if (fd == -1) {
@ -319,11 +311,11 @@ tty_make_modes(int fd, struct termios *tiop)
/* Store values of mode flags. */
#define TTYCHAR(NAME, OP) \
buffer_put_char(&buf, OP); \
put_arg(&buf, special_char_encode(tio.c_cc[NAME]));
buffer_put_int(&buf, special_char_encode(tio.c_cc[NAME]));
#define TTYMODE(NAME, FIELD, OP) \
buffer_put_char(&buf, OP); \
put_arg(&buf, ((tio.FIELD & NAME) != 0));
buffer_put_int(&buf, ((tio.FIELD & NAME) != 0));
#include "ttymodes.h"
@ -333,10 +325,7 @@ tty_make_modes(int fd, struct termios *tiop)
end:
/* Mark end of mode data. */
buffer_put_char(&buf, TTY_OP_END);
if (compat20)
packet_put_string(buffer_ptr(&buf), buffer_len(&buf));
else
packet_put_raw(buffer_ptr(&buf), buffer_len(&buf));
packet_put_string(buffer_ptr(&buf), buffer_len(&buf));
buffer_free(&buf);
}
@ -351,19 +340,10 @@ tty_parse_modes(int fd, int *n_bytes_ptr)
int opcode, baud;
int n_bytes = 0;
int failure = 0;
u_int (*get_arg)(void);
int arg_size;
if (compat20) {
*n_bytes_ptr = packet_get_int();
if (*n_bytes_ptr == 0)
return;
get_arg = packet_get_int;
arg_size = 4;
} else {
get_arg = packet_get_char;
arg_size = 1;
}
*n_bytes_ptr = packet_get_int();
if (*n_bytes_ptr == 0)
return;
/*
* Get old attributes for the terminal. We will modify these
@ -404,13 +384,13 @@ tty_parse_modes(int fd, int *n_bytes_ptr)
#define TTYCHAR(NAME, OP) \
case OP: \
n_bytes += arg_size; \
tio.c_cc[NAME] = special_char_decode(get_arg()); \
n_bytes += 4; \
tio.c_cc[NAME] = special_char_decode(packet_get_int()); \
break;
#define TTYMODE(NAME, FIELD, OP) \
case OP: \
n_bytes += arg_size; \
if (get_arg()) \
n_bytes += 4; \
if (packet_get_int()) \
tio.FIELD |= NAME; \
else \
tio.FIELD &= ~NAME; \
@ -424,51 +404,21 @@ tty_parse_modes(int fd, int *n_bytes_ptr)
default:
debug("Ignoring unsupported tty mode opcode %d (0x%x)",
opcode, opcode);
if (!compat20) {
/*
* SSH1:
* Opcodes 1 to 127 are defined to have
* a one-byte argument.
* Opcodes 128 to 159 are defined to have
* an integer argument.
*/
if (opcode > 0 && opcode < 128) {
n_bytes += 1;
(void) packet_get_char();
break;
} else if (opcode >= 128 && opcode < 160) {
n_bytes += 4;
(void) packet_get_int();
break;
} else {
/*
* It is a truly undefined opcode (160 to 255).
* We have no idea about its arguments. So we
* must stop parsing. Note that some data
* may be left in the packet; hopefully there
* is nothing more coming after the mode data.
*/
logit("parse_tty_modes: unknown opcode %d",
opcode);
goto set;
}
/*
* SSH2:
* Opcodes 1 to 159 are defined to have a uint32
* argument.
* Opcodes 160 to 255 are undefined and cause parsing
* to stop.
*/
if (opcode > 0 && opcode < 160) {
n_bytes += 4;
(void) packet_get_int();
break;
} else {
/*
* SSH2:
* Opcodes 1 to 159 are defined to have
* a uint32 argument.
* Opcodes 160 to 255 are undefined and
* cause parsing to stop.
*/
if (opcode > 0 && opcode < 160) {
n_bytes += 4;
(void) packet_get_int();
break;
} else {
logit("parse_tty_modes: unknown opcode %d",
opcode);
goto set;
}
logit("parse_tty_modes: unknown opcode %d",
opcode);
goto set;
}
}
}