diff options
-rw-r--r-- | usr.bin/ssh/channels.c | 166 | ||||
-rw-r--r-- | usr.bin/ssh/channels.h | 38 | ||||
-rw-r--r-- | usr.bin/ssh/compat.c | 8 | ||||
-rw-r--r-- | usr.bin/ssh/compat.h | 5 | ||||
-rw-r--r-- | usr.bin/ssh/nchan.c | 98 | ||||
-rw-r--r-- | usr.bin/ssh/nchan.h | 78 | ||||
-rw-r--r-- | usr.bin/ssh/ssh-agent.1 | 4 | ||||
-rw-r--r-- | usr.bin/ssh/ssh.1 | 4 | ||||
-rw-r--r-- | usr.bin/ssh/ssh.h | 11 | ||||
-rw-r--r-- | usr.bin/ssh/ssh/Makefile | 3 | ||||
-rw-r--r-- | usr.bin/ssh/sshconnect.c | 12 | ||||
-rw-r--r-- | usr.bin/ssh/sshd.c | 26 | ||||
-rw-r--r-- | usr.bin/ssh/sshd/Makefile | 3 |
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 |