summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarkus Friedl <markus@cvs.openbsd.org>1999-10-16 20:47:16 +0000
committerMarkus Friedl <markus@cvs.openbsd.org>1999-10-16 20:47:16 +0000
commitc958c63d9d19682f64d8f4afa27ee93c636d6d9c (patch)
treecca46041616c6e4462af69ba859c993ea2b77c55
parent40b8bc6e356154ab8d0260f30cb7db324b3675de (diff)
support for SSH protocol 1.5 which is poorly documented, the RFC.troff lies.
interops (x11,agent,etc) with 1.2.27 and protocol 1.3
-rw-r--r--usr.bin/ssh/channels.c166
-rw-r--r--usr.bin/ssh/channels.h38
-rw-r--r--usr.bin/ssh/compat.c8
-rw-r--r--usr.bin/ssh/compat.h5
-rw-r--r--usr.bin/ssh/nchan.c98
-rw-r--r--usr.bin/ssh/nchan.h78
-rw-r--r--usr.bin/ssh/ssh-agent.14
-rw-r--r--usr.bin/ssh/ssh.14
-rw-r--r--usr.bin/ssh/ssh.h11
-rw-r--r--usr.bin/ssh/ssh/Makefile3
-rw-r--r--usr.bin/ssh/sshconnect.c12
-rw-r--r--usr.bin/ssh/sshd.c26
-rw-r--r--usr.bin/ssh/sshd/Makefile3
13 files changed, 379 insertions, 77 deletions
diff --git a/usr.bin/ssh/channels.c b/usr.bin/ssh/channels.c
index a0eb88f6c91..6637011ebdf 100644
--- a/usr.bin/ssh/channels.c
+++ b/usr.bin/ssh/channels.c
@@ -16,7 +16,7 @@ arbitrary tcp/ip connections, and the authentication agent connection.
*/
#include "includes.h"
-RCSID("$Id: channels.c,v 1.13 1999/10/14 18:17:42 markus Exp $");
+RCSID("$Id: channels.c,v 1.14 1999/10/16 20:47:13 markus Exp $");
#include "ssh.h"
#include "packet.h"
@@ -26,42 +26,16 @@ RCSID("$Id: channels.c,v 1.13 1999/10/14 18:17:42 markus Exp $");
#include "uidswap.h"
#include "servconf.h"
+#include "channels.h"
+#include "nchan.h"
+#include "compat.h"
+
/* Maximum number of fake X11 displays to try. */
#define MAX_DISPLAYS 1000
-/* Definitions for channel types. */
-#define SSH_CHANNEL_FREE 0 /* This channel is free (unused). */
-#define SSH_CHANNEL_X11_LISTENER 1 /* Listening for inet X11 conn. */
-#define SSH_CHANNEL_PORT_LISTENER 2 /* Listening on a port. */
-#define SSH_CHANNEL_OPENING 3 /* waiting for confirmation */
-#define SSH_CHANNEL_OPEN 4 /* normal open two-way channel */
-#define SSH_CHANNEL_CLOSED 5 /* waiting for close confirmation */
-/* SSH_CHANNEL_AUTH_FD 6 authentication fd */
-#define SSH_CHANNEL_AUTH_SOCKET 7 /* authentication socket */
-/* SSH_CHANNEL_AUTH_SOCKET_FD 8 connection to auth socket */
-#define SSH_CHANNEL_X11_OPEN 9 /* reading first X11 packet */
-#define SSH_CHANNEL_INPUT_DRAINING 10 /* sending remaining data to conn */
-#define SSH_CHANNEL_OUTPUT_DRAINING 11 /* sending remaining data to app */
-
/* Max len of agent socket */
#define MAX_SOCKET_NAME 100
-/* Data structure for channel data. This is iniailized in channel_allocate
- and cleared in channel_free. */
-
-typedef struct
-{
- int type;
- int sock;
- int remote_id;
- Buffer input;
- Buffer output;
- char path[200]; /* path for unix domain sockets, or host name for forwards */
- int host_port; /* port to connect for forwards */
- int listening_port; /* port being listened for forwards */
- char *remote_name;
-} Channel;
-
/* Pointer to an array containing all allocated channels. The array is
dynamically extended as needed. */
static Channel *channels = NULL;
@@ -160,8 +134,10 @@ int channel_allocate(int type, int sock, char *remote_name)
/* Found a free slot. Initialize the fields and return its number. */
buffer_init(&channels[i].input);
buffer_init(&channels[i].output);
+ channels[i].self = i;
channels[i].type = type;
channels[i].sock = sock;
+ channels[i].flags = 0;
channels[i].remote_id = -1;
channels[i].remote_name = remote_name;
return i;
@@ -178,8 +154,10 @@ int channel_allocate(int type, int sock, char *remote_name)
available. Initialize and return its number. */
buffer_init(&channels[old_channels].input);
buffer_init(&channels[old_channels].output);
+ channels[old_channels].self = old_channels;
channels[old_channels].type = type;
channels[old_channels].sock = sock;
+ channels[old_channels].flags = 0;
channels[old_channels].remote_id = -1;
channels[old_channels].remote_name = remote_name;
return old_channels;
@@ -191,7 +169,8 @@ void channel_free(int channel)
{
assert(channel >= 0 && channel < channels_alloc &&
channels[channel].type != SSH_CHANNEL_FREE);
- shutdown(channels[channel].sock, SHUT_RDWR);
+ if(compat13)
+ shutdown(channels[channel].sock, SHUT_RDWR);
close(channels[channel].sock);
buffer_free(&channels[channel].input);
buffer_free(&channels[channel].output);
@@ -226,13 +205,32 @@ void channel_prepare_select(fd_set *readset, fd_set *writeset)
break;
case SSH_CHANNEL_OPEN:
- if (buffer_len(&ch->input) < 32768)
- FD_SET(ch->sock, readset);
- if (buffer_len(&ch->output) > 0)
- FD_SET(ch->sock, writeset);
- break;
+ if(compat13){
+ if (buffer_len(&ch->input) < 32768)
+ FD_SET(ch->sock, readset);
+ if (buffer_len(&ch->output) > 0)
+ FD_SET(ch->sock, writeset);
+ break;
+ }
+ /* test whether sockets are 'alive' for read/write */
+ if (!(ch->flags & CHAN_SHUT_RD))
+ if (buffer_len(&ch->input) < 32768)
+ FD_SET(ch->sock, readset);
+ if (!(ch->flags & CHAN_SHUT_WR)){
+ if (buffer_len(&ch->output) > 0){
+ FD_SET(ch->sock, writeset);
+ }else if(ch->flags & CHAN_IEOF_RCVD){
+ /* if output-buffer empty AND IEOF received,
+ we won't get more data for writing */
+ chan_shutdown_write(ch);
+ chan_send_oclose(ch);
+ }
+ }
+ break;
case SSH_CHANNEL_INPUT_DRAINING:
+ if (!compat13)
+ fatal("cannot happen: IN_DRAIN");
if (buffer_len(&ch->input) == 0)
{
packet_start(SSH_MSG_CHANNEL_CLOSE);
@@ -245,6 +243,8 @@ void channel_prepare_select(fd_set *readset, fd_set *writeset)
break;
case SSH_CHANNEL_OUTPUT_DRAINING:
+ if (!compat13)
+ fatal("cannot happen: OUT_DRAIN");
if (buffer_len(&ch->output) == 0)
{
/* debug("Freeing channel %d after output drain.", i); */
@@ -327,12 +327,19 @@ void channel_prepare_select(fd_set *readset, fd_set *writeset)
log("X11 connection rejected because of wrong authentication.\r\n");
buffer_clear(&ch->input);
buffer_clear(&ch->output);
- close(ch->sock);
- ch->sock = -1;
- ch->type = SSH_CHANNEL_CLOSED;
- packet_start(SSH_MSG_CHANNEL_CLOSE);
- packet_put_int(ch->remote_id);
- packet_send();
+ if (compat13) {
+ close(ch->sock);
+ ch->sock = -1;
+ ch->type = SSH_CHANNEL_CLOSED;
+ packet_start(SSH_MSG_CHANNEL_CLOSE);
+ packet_put_int(ch->remote_id);
+ packet_send();
+ }else{
+ chan_shutdown_read(ch); /* shutdown, since close() does not update ch->flags */
+ chan_send_ieof(ch); /* no need to wait for output-buffer */
+ chan_shutdown_write(ch);
+ chan_send_oclose(ch);
+ }
break;
case SSH_CHANNEL_FREE:
@@ -441,15 +448,24 @@ void channel_after_select(fd_set *readset, fd_set *writeset)
/* This is an open two-way communication channel. It is not of
interest to us at this point what kind of data is being
transmitted. */
- /* Read available incoming data and append it to buffer. */
+
+ /* Read available incoming data and append it to buffer;
+ shutdown socket, if read or write failes */
if (FD_ISSET(ch->sock, readset))
{
len = read(ch->sock, buf, sizeof(buf));
if (len <= 0)
{
- buffer_consume(&ch->output, buffer_len(&ch->output));
- ch->type = SSH_CHANNEL_INPUT_DRAINING;
- debug("Channel %d status set to input draining.", i);
+ if (compat13) {
+ buffer_consume(&ch->output, buffer_len(&ch->output));
+ ch->type = SSH_CHANNEL_INPUT_DRAINING;
+ debug("Channel %d status set to input draining.", i);
+ }else{
+ buffer_consume(&ch->output, buffer_len(&ch->output));
+ chan_shutdown_read(ch);
+ /* we have to wait until the input-buffer has been
+ sent to our peer before we can send IEOF */
+ }
break;
}
buffer_append(&ch->input, buf, len);
@@ -461,16 +477,25 @@ void channel_after_select(fd_set *readset, fd_set *writeset)
buffer_len(&ch->output));
if (len <= 0)
{
- buffer_consume(&ch->output, buffer_len(&ch->output));
- debug("Channel %d status set to input draining.", i);
- ch->type = SSH_CHANNEL_INPUT_DRAINING;
+ if (compat13) {
+ buffer_consume(&ch->output, buffer_len(&ch->output));
+ debug("Channel %d status set to input draining.", i);
+ ch->type = SSH_CHANNEL_INPUT_DRAINING;
+ }else{
+ buffer_consume(&ch->output, buffer_len(&ch->output));
+ chan_shutdown_write(ch);
+ chan_send_oclose(ch);
+ }
break;
}
buffer_consume(&ch->output, len);
}
+ chan_del_if_dead(ch);
break;
case SSH_CHANNEL_OUTPUT_DRAINING:
+ if (!compat13)
+ fatal("cannot happen: OUT_DRAIN");
/* Send buffered output data to the socket. */
if (FD_ISSET(ch->sock, writeset) && buffer_len(&ch->output) > 0)
{
@@ -528,6 +553,14 @@ void channel_output_poll()
packet_send();
buffer_consume(&ch->input, len);
}
+ else if(ch->flags & CHAN_SHUT_RD)
+ {
+ if (compat13)
+ fatal("cannot happen: CHAN_SHUT_RD set for proto 1.3");
+ /* input-buffer is empty and read-socket shutdown:
+ tell peer, that we will not send more data: send IEOF */
+ chan_send_ieof(ch);
+ }
}
}
@@ -570,7 +603,7 @@ int channel_not_very_much_buffered_data()
for (i = 0; i < channels_alloc; i++)
{
ch = &channels[i];
- switch (channels[i].type)
+ switch (ch->type)
{
case SSH_CHANNEL_X11_LISTENER:
case SSH_CHANNEL_PORT_LISTENER:
@@ -593,7 +626,7 @@ int channel_not_very_much_buffered_data()
return 1;
}
-/* This is called after receiving CHANNEL_CLOSE. */
+/* This is called after receiving CHANNEL_CLOSE/IEOF. */
void channel_input_close()
{
@@ -605,6 +638,12 @@ void channel_input_close()
channels[channel].type == SSH_CHANNEL_FREE)
packet_disconnect("Received data for nonexistent channel %d.", channel);
+ if(!compat13){
+ /* proto version 1.5 overloads CLOSE with IEOF */
+ chan_rcvd_ieof(&channels[channel]);
+ return;
+ }
+
/* Send a confirmation that we have closed the channel and no more data is
coming for it. */
packet_start(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION);
@@ -628,7 +667,7 @@ void channel_input_close()
}
}
-/* This is called after receiving CHANNEL_CLOSE_CONFIRMATION. */
+/* This is called after receiving CHANNEL_CLOSE_CONFIRMATION/OCLOSE. */
void channel_input_close_confirmation()
{
@@ -639,6 +678,13 @@ void channel_input_close_confirmation()
if (channel < 0 || channel >= channels_alloc)
packet_disconnect("Received close confirmation for out-of-range channel %d.",
channel);
+
+ if(!compat13){
+ /* proto version 1.5 overloads CLOSE_CONFIRMATION with OCLOSE */
+ chan_rcvd_oclose(&channels[channel]);
+ return;
+ }
+
if (channels[channel].type != SSH_CHANNEL_CLOSED)
packet_disconnect("Received close confirmation for non-closed channel %d (type %d).",
channel, channels[channel].type);
@@ -748,8 +794,11 @@ int channel_still_open()
case SSH_CHANNEL_OPENING:
case SSH_CHANNEL_OPEN:
case SSH_CHANNEL_X11_OPEN:
+ return 1;
case SSH_CHANNEL_INPUT_DRAINING:
case SSH_CHANNEL_OUTPUT_DRAINING:
+ if (!compat13)
+ fatal("cannot happen: OUT_DRAIN");
return 1;
default:
fatal("channel_still_open: bad channel type %d", channels[i].type);
@@ -771,8 +820,9 @@ char *channel_open_message()
buffer_init(&buffer);
sprintf(buf, "The following connections are open:\r\n");
buffer_append(&buffer, buf, strlen(buf));
- for (i = 0; i < channels_alloc; i++)
- switch (channels[i].type)
+ for (i = 0; i < channels_alloc; i++){
+ Channel *c=&channels[i];
+ switch (c->type)
{
case SSH_CHANNEL_FREE:
case SSH_CHANNEL_X11_LISTENER:
@@ -785,13 +835,15 @@ char *channel_open_message()
case SSH_CHANNEL_X11_OPEN:
case SSH_CHANNEL_INPUT_DRAINING:
case SSH_CHANNEL_OUTPUT_DRAINING:
- sprintf(buf, " %.300s\r\n", channels[i].remote_name);
+ snprintf(buf, sizeof buf, " #%d/%d %.300s\r\n",
+ c->self,c->type,c->remote_name);
buffer_append(&buffer, buf, strlen(buf));
continue;
default:
- fatal("channel_still_open: bad channel type %d", channels[i].type);
+ fatal("channel_still_open: bad channel type %d", c->type);
/*NOTREACHED*/
}
+ }
buffer_append(&buffer, "\0", 1);
cp = xstrdup(buffer_ptr(&buffer));
buffer_free(&buffer);
diff --git a/usr.bin/ssh/channels.h b/usr.bin/ssh/channels.h
new file mode 100644
index 00000000000..d56892825ff
--- /dev/null
+++ b/usr.bin/ssh/channels.h
@@ -0,0 +1,38 @@
+#ifndef CHANNELS_H
+#define CHANNELS_H
+
+/* Definitions for channel types. */
+#define SSH_CHANNEL_FREE 0 /* This channel is free (unused). */
+#define SSH_CHANNEL_X11_LISTENER 1 /* Listening for inet X11 conn. */
+#define SSH_CHANNEL_PORT_LISTENER 2 /* Listening on a port. */
+#define SSH_CHANNEL_OPENING 3 /* waiting for confirmation */
+#define SSH_CHANNEL_OPEN 4 /* normal open two-way channel */
+#define SSH_CHANNEL_CLOSED 5 /* waiting for close confirmation */
+/* SSH_CHANNEL_AUTH_FD 6 authentication fd */
+#define SSH_CHANNEL_AUTH_SOCKET 7 /* authentication socket */
+/* SSH_CHANNEL_AUTH_SOCKET_FD 8 connection to auth socket */
+#define SSH_CHANNEL_X11_OPEN 9 /* reading first X11 packet */
+#define SSH_CHANNEL_INPUT_DRAINING 10 /* sending remaining data to conn */
+#define SSH_CHANNEL_OUTPUT_DRAINING 11 /* sending remaining data to app */
+
+
+/* Data structure for channel data. This is iniailized in channel_allocate
+ and cleared in channel_free. */
+
+typedef struct
+{
+ int type; /* channel type/state */
+ int self; /* my own channel identifier */
+ int remote_id; /* channel identifier for remote peer */
+ /* peer can be reached over encrypted connection, via packet-sent */
+ int flags; /* flags for close in proto 1.5 */
+ int sock; /* data socket, linked to this channel */
+ Buffer input; /* data read from socket, to be sent over encrypted connection */
+ Buffer output; /* data received over encrypted connection for send on socket */
+ char path[200]; /* path for unix domain sockets, or host name for forwards */
+ int listening_port; /* port being listened for forwards */
+ int host_port; /* remote port to connect for forwards */
+ char *remote_name; /* remote hostname */
+} Channel;
+
+#endif
diff --git a/usr.bin/ssh/compat.c b/usr.bin/ssh/compat.c
new file mode 100644
index 00000000000..a003fc6e8c8
--- /dev/null
+++ b/usr.bin/ssh/compat.c
@@ -0,0 +1,8 @@
+#include "includes.h"
+#include "ssh.h"
+
+int compat13=0;
+void enable_compat13(void){
+ log("Enabling compatibility mode for protocol 1.3");
+ compat13=1;
+}
diff --git a/usr.bin/ssh/compat.h b/usr.bin/ssh/compat.h
new file mode 100644
index 00000000000..ee77fbae923
--- /dev/null
+++ b/usr.bin/ssh/compat.h
@@ -0,0 +1,5 @@
+#ifndef COMPAT_H
+#define COMPAT_H
+void enable_compat13(void);
+extern int compat13;
+#endif
diff --git a/usr.bin/ssh/nchan.c b/usr.bin/ssh/nchan.c
new file mode 100644
index 00000000000..1ee66e111bb
--- /dev/null
+++ b/usr.bin/ssh/nchan.c
@@ -0,0 +1,98 @@
+#include "includes.h"
+#include "ssh.h"
+
+#include "buffer.h"
+#include "channels.h"
+#include "packet.h"
+#include "nchan.h"
+
+
+void
+dump_chan(Channel *c){
+ debug("chan %d type %d flags 0x%x", c->self, c->type, c->flags);
+}
+void
+chan_rcvd_ieof(Channel *c){
+ dump_chan(c);
+ if(c->flags & CHAN_IEOF_RCVD){
+ debug("chan_rcvd_ieof twice: %d",c->self);
+ return;
+ }
+ debug("rcvd_CHAN_IEOF %d",c->self);
+ c->flags |= CHAN_IEOF_RCVD;
+ /* cannot clear input buffer. remaining data has to be sent to client */
+ chan_del_if_dead(c);
+}
+void
+chan_rcvd_oclose(Channel *c){
+ dump_chan(c);
+ if(c->flags & CHAN_OCLOSE_RCVD){
+ debug("chan_rcvd_oclose twice: %d",c->self);
+ return;
+ }
+ debug("rcvd_CHAN_OCLOSE %d",c->self);
+ c->flags |= CHAN_OCLOSE_RCVD;
+ /* our peer can no longer consume, so there is not need to read */
+ chan_shutdown_read(c);
+ buffer_consume(&c->output, buffer_len(&c->output));
+ /* Note: for type==OPEN IEOF is sent by channel_output_poll() */
+ chan_del_if_dead(c);
+}
+void
+chan_send_ieof(Channel *c){
+ if(c->flags & CHAN_IEOF_SENT){
+ debug("send_chan_ieof twice %d", c->self);
+ return;
+ }
+ debug("send_CHAN_IEOF %d", c->self);
+ packet_start(CHAN_IEOF);
+ packet_put_int(c->remote_id);
+ packet_send();
+ c->flags |= CHAN_IEOF_SENT;
+ dump_chan(c);
+}
+void
+chan_send_oclose(Channel *c){
+ if(c->flags & CHAN_OCLOSE_SENT){
+ debug("send_chan_oclose twice %d", c->self);
+ return;
+ }
+ debug("send_CHAN_OCLOSE %d", c->self);
+ packet_start(CHAN_OCLOSE);
+ packet_put_int(c->remote_id);
+ packet_send();
+ c->flags |= CHAN_OCLOSE_SENT;
+ dump_chan(c);
+}
+void
+chan_shutdown_write(Channel *c){
+ if(c->flags & CHAN_SHUT_WR){
+ debug("chan_shutdown_write twice %d",c->self);
+ return;
+ }
+ debug("chan_shutdown_write %d", c->self);
+ if(shutdown(c->sock, SHUT_WR)<0)
+ error("chan_shutdown_write failed %.100s", strerror(errno));
+ c->flags |= CHAN_SHUT_WR;
+ /* clear output buffer, since there is noone going to read the data
+ we just closed the output-socket */
+ // buffer_consume(&c->output, buffer_len(&c->output));
+}
+void
+chan_shutdown_read(Channel *c){
+ if(c->flags & CHAN_SHUT_RD){
+ debug("chan_shutdown_read twice %d",c->self);
+ return;
+ }
+ debug("chan_shutdown_read %d", c->self);
+ if(shutdown(c->sock, SHUT_RD)<0)
+ error("chan_shutdown_read failed %.100s", strerror(errno));
+ c->flags |= CHAN_SHUT_RD;
+}
+void
+chan_del_if_dead(Channel *c){
+ if(c->flags == CHAN_CLOSED){
+ debug("channel %d closing",c->self);
+ channel_free(c->self);
+ }
+}
diff --git a/usr.bin/ssh/nchan.h b/usr.bin/ssh/nchan.h
new file mode 100644
index 00000000000..b83cf2de035
--- /dev/null
+++ b/usr.bin/ssh/nchan.h
@@ -0,0 +1,78 @@
+#ifndef NCHAN_H
+#define NCHAN_H
+
+
+/*
+ SSH Protocol 1.5 aka New Channel Protocol
+ Thanks to Martina, Axel and everyone who left Erlangen, leaving me bored.
+ Written by Markus Friedl in October 1999
+
+ Protocol versions 1.3 and 1.5 differ in the handshake protocol used for the
+ tear down of channels:
+
+ 1.3: strict request-ack-protocol:
+ CLOSE ->
+ <- CLOSE_CONFIRM
+
+ 1.5: uses variations of:
+ IEOF ->
+ <- OCLOSE
+ <- IEOF
+ OCLOSE ->
+
+ See the debugging output from 'ssh -v' and 'sshd -d' in ssh-1.2.27, for example.
+
+ Details: (for Channel data structure see channels.h)
+
+ the output_buffer gets data received from the remote peer and is written to the socket,
+ the input_buffer gets data from the socket and is sent to remote peer.
+ the socket represents the local object communicating with an object reachable via the peer
+
+ PEER A PEER B
+
+ read(sock, input_buffer) < 0;
+ shutdown_read();
+ flush(input_buffer) =: DATA
+ send(DATA) -> rcvd(DATA)
+ write(sock, output_buffer:=DATA);
+ send(IEOF) -> rcvd(IEOF)
+ shutdown_write() if:
+ a) write fails
+ b) rcvd_IEOF==true && output_buffer==empty
+ <- send(OCLOSE)
+ rcvd(OCLOSE) destroy channel
+ shutdown_read() if not already
+ destroy channel
+
+ Note that each side can close the channel only if 2 messages
+ have been sent and received and the associated socket has been shutdown, see below:
+*/
+
+
+enum {
+ /* ssh-proto-1.5 overloads message-types */
+ CHAN_IEOF = SSH_MSG_CHANNEL_CLOSE, /* no more data from sender */
+ CHAN_OCLOSE = SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, /* all received data has been output */
+
+ /* channel close flags */
+ CHAN_IEOF_SENT = 0x01,
+ CHAN_IEOF_RCVD = 0x02,
+ CHAN_OCLOSE_SENT = 0x04,
+ CHAN_OCLOSE_RCVD = 0x08,
+ CHAN_SHUT_RD = 0x10,
+ CHAN_SHUT_WR = 0x20,
+
+ /* a channel can be removed if ALL the following flags are set: */
+ CHAN_CLOSED = CHAN_IEOF_SENT | CHAN_IEOF_RCVD |
+ CHAN_OCLOSE_SENT | CHAN_OCLOSE_RCVD |
+ CHAN_SHUT_RD | CHAN_SHUT_WR
+};
+
+void chan_del_if_dead(Channel *c);
+void chan_rcvd_ieof(Channel *c);
+void chan_rcvd_oclose(Channel *c);
+void chan_send_ieof(Channel *c);
+void chan_send_oclose(Channel *c);
+void chan_shutdown_read(Channel *c);
+void chan_shutdown_write(Channel *c);
+#endif
diff --git a/usr.bin/ssh/ssh-agent.1 b/usr.bin/ssh/ssh-agent.1
index c69517d8492..a764d31b5c0 100644
--- a/usr.bin/ssh/ssh-agent.1
+++ b/usr.bin/ssh/ssh-agent.1
@@ -9,7 +9,7 @@
.\"
.\" Created: Sat Apr 23 20:10:43 1995 ylo
.\"
-.\" $Id: ssh-agent.1,v 1.4 1999/10/14 18:17:42 markus Exp $
+.\" $Id: ssh-agent.1,v 1.5 1999/10/16 20:47:14 markus Exp $
.\"
.Dd September 25, 1999
.Dt SSH-AGENT 1
@@ -62,7 +62,7 @@ A connection to the agent is inherited by child programs:
A unix-domain socket is created
.Pq Pa /tmp/ssh-XXXX/agent.<pid> ,
and the name of this socket is stored in the
-.Ev SSH_AUTH_SOCKET
+.Ev SSH_AUTH_SOCK
environment
variable. The socket is made accessible only to the current user.
This method is easily abused by root or another instance of the same
diff --git a/usr.bin/ssh/ssh.1 b/usr.bin/ssh/ssh.1
index ab7da01c501..3a56212740f 100644
--- a/usr.bin/ssh/ssh.1
+++ b/usr.bin/ssh/ssh.1
@@ -9,7 +9,7 @@
.\"
.\" Created: Sat Apr 22 21:55:14 1995 ylo
.\"
-.\" $Id: ssh.1,v 1.17 1999/10/14 18:17:42 markus Exp $
+.\" $Id: ssh.1,v 1.18 1999/10/16 20:47:14 markus Exp $
.\"
.Dd September 25, 1999
.Dt SSH 1
@@ -745,7 +745,7 @@ Set to the default
.Ev PATH ,
as specified when compiling
.Nm ssh .
-.It Ev SSH_AUTH_SOCKET
+.It Ev SSH_AUTH_SOCK
indicates the path of a unix-domain socket used to communicate with the
agent.
.It Ev SSH_CLIENT
diff --git a/usr.bin/ssh/ssh.h b/usr.bin/ssh/ssh.h
index 239aa640fcb..35aaadc0218 100644
--- a/usr.bin/ssh/ssh.h
+++ b/usr.bin/ssh/ssh.h
@@ -13,7 +13,7 @@ Generic header file for ssh.
*/
-/* RCSID("$Id: ssh.h,v 1.12 1999/10/16 19:23:35 provos Exp $"); */
+/* RCSID("$Id: ssh.h,v 1.13 1999/10/16 20:47:14 markus Exp $"); */
#ifndef SSH_H
#define SSH_H
@@ -45,7 +45,7 @@ Generic header file for ssh.
/* Minor protocol version. Different version indicates minor incompatibility
that does not prevent interoperation. */
-#define PROTOCOL_MINOR 3
+#define PROTOCOL_MINOR 5
/* Name for the service. The port named by this service overrides the default
port if present. */
@@ -118,7 +118,7 @@ only by root, whereas ssh_config should be world-readable. */
/* Name of the environment variable containing the pathname of the
authentication socket. */
-#define SSH_AUTHSOCKET_ENV_NAME "SSH_AUTH_SOCKET"
+#define SSH_AUTHSOCKET_ENV_NAME "SSH_AUTH_SOCK"
/* Force host key length and server key length to differ by at least this
many bits. This is to make double encryption with rsaref work. */
@@ -140,6 +140,7 @@ only by root, whereas ssh_config should be world-readable. */
/* 5 is TIS */
#define SSH_AUTH_KERBEROS 6
#define SSH_PASS_KERBEROS_TGT 7
+ /* 8 to 15 are reserved */
#define SSH_PASS_AFS_TOKEN 21
/* Protocol flags. These are bit masks. */
@@ -189,6 +190,10 @@ only by root, whereas ssh_config should be world-readable. */
#define SSH_CMSG_AUTH_RHOSTS_RSA 35 /* user,mod (s,mpi) */
#define SSH_MSG_DEBUG 36 /* string */
#define SSH_CMSG_REQUEST_COMPRESSION 37 /* level 1-9 (int) */
+#define SSH_CMSG_MAX_PACKET_SIZE 38 /* size 4k-1024k (int) */
+#define SSH_CMSG_AUTH_TIS 39 /* this is proto-1.5, but we ignore TIS */
+#define SSH_SMSG_AUTH_TIS_CHALLENGE 40
+#define SSH_CMSG_AUTH_TIS_RESPONSE 41
#define SSH_CMSG_AUTH_KERBEROS 42 /* (KTEXT) */
#define SSH_SMSG_AUTH_KERBEROS_RESPONSE 43 /* (KTEXT) */
diff --git a/usr.bin/ssh/ssh/Makefile b/usr.bin/ssh/ssh/Makefile
index 658af46cd0a..7e32758ed6f 100644
--- a/usr.bin/ssh/ssh/Makefile
+++ b/usr.bin/ssh/ssh/Makefile
@@ -18,7 +18,8 @@ MLINKS= ssh.1 slogin.1
SRCS= ssh.c sshconnect.c log-client.c readconf.c hostfile.c readpass.c \
tildexpand.c uidswap.c clientloop.c canohost.c rsa.c buffer.c \
packet.c xmalloc.c ttymodes.c channels.c bufaux.c authfd.c \
- authfile.c crc32.c match.c mpaux.c cipher.c compress.c deattack.c
+ authfile.c crc32.c match.c mpaux.c cipher.c compress.c deattack.c\
+ nchan.c compat.c
.include <bsd.own.mk> # for AFS
diff --git a/usr.bin/ssh/sshconnect.c b/usr.bin/ssh/sshconnect.c
index 7e5840ef2b9..e24987ca589 100644
--- a/usr.bin/ssh/sshconnect.c
+++ b/usr.bin/ssh/sshconnect.c
@@ -15,7 +15,7 @@ login (authentication) dialog.
*/
#include "includes.h"
-RCSID("$Id: sshconnect.c,v 1.20 1999/10/16 19:23:35 provos Exp $");
+RCSID("$Id: sshconnect.c,v 1.21 1999/10/16 20:47:14 markus Exp $");
#include <ssl/bn.h>
#include "xmalloc.h"
@@ -26,6 +26,7 @@ RCSID("$Id: sshconnect.c,v 1.20 1999/10/16 19:23:35 provos Exp $");
#include "cipher.h"
#include "mpaux.h"
#include "uidswap.h"
+#include "compat.h"
#include <md5.h>
@@ -915,12 +916,15 @@ void ssh_exchange_identification()
debug("Remote protocol version %d.%d, remote software version %.100s",
remote_major, remote_minor, remote_version);
- if (options.forward_agent && strcmp(remote_version, SSH_VERSION) != 0)
- {
- log("Agent forwarding disabled, remote version is not '%s'.",
+
+ if (remote_major == 1 && remote_minor == 3) {
+ enable_compat13();
+ if (options.forward_agent && strcmp(remote_version, SSH_VERSION) != 0) {
+ log("Agent forwarding disabled, remote version '%s' is not compatible.",
SSH_VERSION);
options.forward_agent = 0;
}
+ }
#if 0
/* Removed for now, to permit compatibility with latter versions. The server
will reject our version and disconnect if it doesn't support it. */
diff --git a/usr.bin/ssh/sshd.c b/usr.bin/ssh/sshd.c
index 9ae8070e03f..85af4d2432a 100644
--- a/usr.bin/ssh/sshd.c
+++ b/usr.bin/ssh/sshd.c
@@ -18,7 +18,7 @@ agent connections.
*/
#include "includes.h"
-RCSID("$Id: sshd.c,v 1.32 1999/10/14 18:54:45 markus Exp $");
+RCSID("$Id: sshd.c,v 1.33 1999/10/16 20:47:14 markus Exp $");
#include "xmalloc.h"
#include "rsa.h"
@@ -30,6 +30,7 @@ RCSID("$Id: sshd.c,v 1.32 1999/10/14 18:54:45 markus Exp $");
#include "mpaux.h"
#include "servconf.h"
#include "uidswap.h"
+#include "compat.h"
#ifdef LIBWRAP
#include <tcpd.h>
@@ -715,12 +716,14 @@ main(int ac, char **av)
if (remote_major == 1 && remote_minor == 0)
packet_disconnect("Your ssh version is too old and is no longer supported. Please install a newer version.");
- if (strcmp(remote_version, SSH_VERSION) != 0)
- {
- debug("Agent forwarding disabled, remote version is not '%s'.",
- SSH_VERSION);
- no_agent_forwarding_flag = 1;
- }
+ if (remote_major == 1 && remote_minor == 3) {
+ enable_compat13();
+ if (strcmp(remote_version, SSH_VERSION) != 0) {
+ debug("Agent forwarding disabled, remote version '%s' is not compatible.",
+ SSH_VERSION);
+ no_agent_forwarding_flag = 1;
+ }
+ }
/* Check whether logins are permitted from this host. */
if (options.num_allow_hosts > 0)
@@ -1375,6 +1378,11 @@ do_authentication(char *user, int privileged_port)
xfree(password);
break;
+ case SSH_CMSG_AUTH_TIS:
+ /* TIS Authentication is unsupported */
+ log("TIS authentication disabled.");
+ break;
+
default:
/* Any unknown messages will be ignored (and failure returned)
during authentication. */
@@ -1640,6 +1648,10 @@ void do_authenticated(struct passwd *pw)
xfree(command);
return;
+ case SSH_CMSG_MAX_PACKET_SIZE:
+ debug("The server does not support limiting packet size.");
+ goto fail;
+
default:
/* Any unknown messages in this phase are ignored, and a failure
message is returned. */
diff --git a/usr.bin/ssh/sshd/Makefile b/usr.bin/ssh/sshd/Makefile
index f2d01164527..d24bd810c8f 100644
--- a/usr.bin/ssh/sshd/Makefile
+++ b/usr.bin/ssh/sshd/Makefile
@@ -10,7 +10,8 @@ SRCS= sshd.c auth-rhosts.c auth-passwd.c auth-rsa.c auth-rh-rsa.c \
pty.c log-server.c login.c hostfile.c canohost.c servconf.c \
tildexpand.c uidswap.c serverloop.c rsa.c buffer.c packet.c \
xmalloc.c ttymodes.c channels.c bufaux.c authfd.c authfile.c \
- crc32.c match.c mpaux.c cipher.c compress.c deattack.c
+ crc32.c match.c mpaux.c cipher.c compress.c deattack.c \
+ nchan.c compat.c
.include <bsd.own.mk> # for KERBEROS and AFS