diff options
author | Kevin Steves <stevesk@cvs.openbsd.org> | 2001-04-14 16:33:21 +0000 |
---|---|---|
committer | Kevin Steves <stevesk@cvs.openbsd.org> | 2001-04-14 16:33:21 +0000 |
commit | f38e8ebb4d051ef9b25d767d54567fdc712a6a67 (patch) | |
tree | 493e9c83b7b855518498c03b186480c4582a7977 | |
parent | f9e9c12e9fea79bc7c95093f1e2b5a84e0bcf82c (diff) |
protocol 2 tty modes support; ok markus@
-rw-r--r-- | usr.bin/ssh/clientloop.c | 56 | ||||
-rw-r--r-- | usr.bin/ssh/packet.h | 6 | ||||
-rw-r--r-- | usr.bin/ssh/session.c | 13 | ||||
-rw-r--r-- | usr.bin/ssh/ssh.c | 9 | ||||
-rw-r--r-- | usr.bin/ssh/ssh/Makefile | 4 | ||||
-rw-r--r-- | usr.bin/ssh/sshtty.c | 96 | ||||
-rw-r--r-- | usr.bin/ssh/sshtty.h | 65 | ||||
-rw-r--r-- | usr.bin/ssh/ttymodes.c | 231 | ||||
-rw-r--r-- | usr.bin/ssh/ttymodes.h | 39 |
9 files changed, 388 insertions, 131 deletions
diff --git a/usr.bin/ssh/clientloop.c b/usr.bin/ssh/clientloop.c index 94d2ec60bb0..24ea0dec0e1 100644 --- a/usr.bin/ssh/clientloop.c +++ b/usr.bin/ssh/clientloop.c @@ -59,7 +59,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: clientloop.c,v 1.61 2001/04/08 11:27:33 markus Exp $"); +RCSID("$OpenBSD: clientloop.c,v 1.62 2001/04/14 16:33:20 stevesk Exp $"); #include "ssh.h" #include "ssh1.h" @@ -79,6 +79,7 @@ RCSID("$OpenBSD: clientloop.c,v 1.61 2001/04/08 11:27:33 markus Exp $"); #include "clientloop.h" #include "authfd.h" #include "atomicio.h" +#include "sshtty.h" /* import options */ extern Options options; @@ -101,15 +102,6 @@ extern char *host; */ static volatile int received_window_change_signal = 0; -/* Terminal modes, as saved by enter_raw_mode. */ -static struct termios saved_tio; - -/* - * Flag indicating whether we are in raw mode. This is used by - * enter_raw_mode and leave_raw_mode. - */ -static int in_raw_mode = 0; - /* Flag indicating whether the user\'s terminal is in non-blocking mode. */ static int in_non_blocking_mode = 0; @@ -136,46 +128,6 @@ int session_ident = -1; /*XXX*/ extern Kex *xxx_kex; -/* Returns the user\'s terminal to normal mode if it had been put in raw mode. */ - -void -leave_raw_mode(void) -{ - if (!in_raw_mode) - return; - in_raw_mode = 0; - if (tcsetattr(fileno(stdin), TCSADRAIN, &saved_tio) < 0) - perror("tcsetattr"); - - fatal_remove_cleanup((void (*) (void *)) leave_raw_mode, NULL); -} - -/* Puts the user\'s terminal in raw mode. */ - -void -enter_raw_mode(void) -{ - struct termios tio; - - if (tcgetattr(fileno(stdin), &tio) < 0) - perror("tcgetattr"); - saved_tio = tio; - tio.c_iflag |= IGNPAR; - tio.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF); - tio.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL); -#ifdef IEXTEN - tio.c_lflag &= ~IEXTEN; -#endif /* IEXTEN */ - tio.c_oflag &= ~OPOST; - tio.c_cc[VMIN] = 1; - tio.c_cc[VTIME] = 0; - if (tcsetattr(fileno(stdin), TCSADRAIN, &tio) < 0) - perror("tcsetattr"); - in_raw_mode = 1; - - fatal_add_cleanup((void (*) (void *)) leave_raw_mode, NULL); -} - /* Restores stdin to blocking mode. */ void @@ -218,7 +170,7 @@ window_change_handler(int sig) void signal_handler(int sig) { - if (in_raw_mode) + if (in_raw_mode()) leave_raw_mode(); if (in_non_blocking_mode) leave_non_blocking(); @@ -796,7 +748,7 @@ client_channel_closed(int id, void *arg) error("client_channel_closed: id %d != session_ident %d", id, session_ident); session_closed = 1; - if (in_raw_mode) + if (in_raw_mode()) leave_raw_mode(); } diff --git a/usr.bin/ssh/packet.h b/usr.bin/ssh/packet.h index e5432714e90..0f5e7104997 100644 --- a/usr.bin/ssh/packet.h +++ b/usr.bin/ssh/packet.h @@ -11,7 +11,7 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* RCSID("$OpenBSD: packet.h,v 1.21 2001/02/28 21:27:47 markus Exp $"); */ +/* RCSID("$OpenBSD: packet.h,v 1.22 2001/04/14 16:33:20 stevesk Exp $"); */ #ifndef PACKET_H #define PACKET_H @@ -178,8 +178,8 @@ extern int max_packet_size; int packet_set_maxsize(int s); #define packet_get_maxsize() max_packet_size -/* Stores tty modes from the fd into current packet. */ -void tty_make_modes(int fd); +/* Stores tty modes from the fd or tiop into current packet. */ +void tty_make_modes(int fd, struct termios *tiop); /* Parses tty modes for the fd from the current packet. */ void tty_parse_modes(int fd, int *n_bytes_ptr); diff --git a/usr.bin/ssh/session.c b/usr.bin/ssh/session.c index 03252789231..38a6b94fd0d 100644 --- a/usr.bin/ssh/session.c +++ b/usr.bin/ssh/session.c @@ -33,7 +33,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: session.c,v 1.71 2001/04/06 21:00:12 markus Exp $"); +RCSID("$OpenBSD: session.c,v 1.72 2001/04/14 16:33:20 stevesk Exp $"); #include "ssh.h" #include "ssh1.h" @@ -1265,7 +1265,7 @@ int session_pty_req(Session *s) { u_int len; - char *term_modes; /* encoded terminal modes */ + int n_bytes; if (no_pty_flag) return 0; @@ -1276,8 +1276,6 @@ session_pty_req(Session *s) s->row = packet_get_int(); s->xpixel = packet_get_int(); s->ypixel = packet_get_int(); - term_modes = packet_get_string(&len); - packet_done(); if (strcmp(s->term, "") == 0) { xfree(s->term); @@ -1290,7 +1288,6 @@ session_pty_req(Session *s) s->ptyfd = -1; s->ttyfd = -1; error("session_pty_req: session %d alloc failed", s->self); - xfree(term_modes); return 0; } debug("session_pty_req: session %d alloc %s", s->self, s->tty); @@ -1303,10 +1300,12 @@ session_pty_req(Session *s) /* Get window size from the packet. */ pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel); + /* Get tty modes from the packet. */ + tty_parse_modes(s->ttyfd, &n_bytes); + packet_done(); + session_proctitle(s); - /* XXX parse and set terminal modes */ - xfree(term_modes); return 1; } diff --git a/usr.bin/ssh/ssh.c b/usr.bin/ssh/ssh.c index 512a5af0dbc..470a4d41259 100644 --- a/usr.bin/ssh/ssh.c +++ b/usr.bin/ssh/ssh.c @@ -39,7 +39,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: ssh.c,v 1.114 2001/04/13 01:26:17 stevesk Exp $"); +RCSID("$OpenBSD: ssh.c,v 1.115 2001/04/14 16:33:20 stevesk Exp $"); #include <openssl/evp.h> #include <openssl/err.h> @@ -67,6 +67,7 @@ RCSID("$OpenBSD: ssh.c,v 1.114 2001/04/13 01:26:17 stevesk Exp $"); #include "misc.h" #include "kex.h" #include "mac.h" +#include "sshtty.h" extern char *__progname; @@ -858,7 +859,7 @@ ssh_session(void) packet_put_int(ws.ws_ypixel); /* Store tty modes in the packet. */ - tty_make_modes(fileno(stdin)); + tty_make_modes(fileno(stdin), NULL); /* Send the packet, and wait for it to leave. */ packet_send(); @@ -962,6 +963,7 @@ ssh_session2_callback(int id, void *arg) { int len; int interactive = 0; + struct termios tio; debug("client_init id %d arg %ld", id, (long)arg); @@ -981,7 +983,8 @@ ssh_session2_callback(int id, void *arg) packet_put_int(ws.ws_row); packet_put_int(ws.ws_xpixel); packet_put_int(ws.ws_ypixel); - packet_put_cstring(""); /* XXX: encode terminal modes */ + tio = get_saved_tio(); + tty_make_modes(/*ignored*/ 0, &tio); packet_send(); interactive = 1; /* XXX wait for reply */ diff --git a/usr.bin/ssh/ssh/Makefile b/usr.bin/ssh/ssh/Makefile index 85d8cbcf64a..2cf80e10f82 100644 --- a/usr.bin/ssh/ssh/Makefile +++ b/usr.bin/ssh/ssh/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.29 2001/03/04 00:51:25 markus Exp $ +# $OpenBSD: Makefile,v 1.30 2001/04/14 16:33:20 stevesk Exp $ .PATH: ${.CURDIR}/.. @@ -12,7 +12,7 @@ MAN= ssh.1 LINKS= ${BINDIR}/ssh ${BINDIR}/slogin MLINKS= ssh.1 slogin.1 -SRCS= ssh.c readconf.c clientloop.c \ +SRCS= ssh.c readconf.c clientloop.c sshtty.c \ sshconnect.c sshconnect1.c sshconnect2.c .include <bsd.own.mk> # for AFS diff --git a/usr.bin/ssh/sshtty.c b/usr.bin/ssh/sshtty.c new file mode 100644 index 00000000000..78498908fc6 --- /dev/null +++ b/usr.bin/ssh/sshtty.c @@ -0,0 +1,96 @@ +/* $OpenBSD: sshtty.c,v 1.1 2001/04/14 16:33:20 stevesk Exp $ */ +/* + * Author: Tatu Ylonen <ylo@cs.hut.fi> + * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland + * All rights reserved + * + * As far as I am concerned, the code I have written for this software + * can be used freely for any purpose. Any derived versions of this + * software must be clearly marked as such, and if the derived work is + * incompatible with the protocol description in the RFC file, it must be + * called by a name other than "ssh" or "Secure Shell". + */ +/* + * Copyright (c) 2001 Markus Friedl. All rights reserved. + * Copyright (c) 2001 Kevin Steves. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" + +#include "sshtty.h" +#include "log.h" + +static struct termios _saved_tio; +static int _in_raw_mode = 0; + +int +in_raw_mode(void) +{ + return _in_raw_mode; +} + +struct termios +get_saved_tio(void) +{ + return _saved_tio; +} + +void +leave_raw_mode(void) +{ + if (!_in_raw_mode) + return; + if (tcsetattr(fileno(stdin), TCSADRAIN, &_saved_tio) == -1) + perror("tcsetattr"); + else + _in_raw_mode = 0; + + fatal_remove_cleanup((void (*) (void *)) leave_raw_mode, NULL); +} + +void +enter_raw_mode(void) +{ + struct termios tio; + + if (tcgetattr(fileno(stdin), &tio) == -1) { + perror("tcgetattr"); + return; + } + _saved_tio = tio; + tio.c_iflag |= IGNPAR; + tio.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF); + tio.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL); +#ifdef IEXTEN + tio.c_lflag &= ~IEXTEN; +#endif + tio.c_oflag &= ~OPOST; + tio.c_cc[VMIN] = 1; + tio.c_cc[VTIME] = 0; + if (tcsetattr(fileno(stdin), TCSADRAIN, &tio) == -1) + perror("tcsetattr"); + else + _in_raw_mode = 1; + + fatal_add_cleanup((void (*) (void *)) leave_raw_mode, NULL); +} diff --git a/usr.bin/ssh/sshtty.h b/usr.bin/ssh/sshtty.h new file mode 100644 index 00000000000..e29385e3522 --- /dev/null +++ b/usr.bin/ssh/sshtty.h @@ -0,0 +1,65 @@ +/* $OpenBSD: sshtty.h,v 1.1 2001/04/14 16:33:20 stevesk Exp $ */ +/* + * Author: Tatu Ylonen <ylo@cs.hut.fi> + * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland + * All rights reserved + * + * As far as I am concerned, the code I have written for this software + * can be used freely for any purpose. Any derived versions of this + * software must be clearly marked as such, and if the derived work is + * incompatible with the protocol description in the RFC file, it must be + * called by a name other than "ssh" or "Secure Shell". + */ +/* + * Copyright (c) 2001 Markus Friedl. All rights reserved. + * Copyright (c) 2001 Kevin Steves. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SSHTTY_H +#define SSHTTY_H + +#include <termios.h> + +/* + * Accessor function indicating whether we are in raw mode. Set by + * enter_raw_mode() and leave_raw_mode(). + */ +int in_raw_mode(void); + +/* + * Return terminal modes, as saved by enter_raw_mode(). + */ +struct termios get_saved_tio(void); + +/* + * Returns the user's terminal to normal mode if it had been + * put in raw mode. + */ +void leave_raw_mode(void); + +/* + * Puts the user's terminal in raw mode. + */ +void enter_raw_mode(void); + +#endif diff --git a/usr.bin/ssh/ttymodes.c b/usr.bin/ssh/ttymodes.c index 65caf2ff852..9ce3fbcc47e 100644 --- a/usr.bin/ssh/ttymodes.c +++ b/usr.bin/ssh/ttymodes.c @@ -2,10 +2,6 @@ * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * All rights reserved - * Encoding and decoding of terminal modes in a portable way. - * Much of the format is defined in ttymodes.h; it is included multiple times - * into this file with the appropriate macro definitions to generate the - * suitable code. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this @@ -14,16 +10,56 @@ * called by a name other than "ssh" or "Secure Shell". */ +/* + * SSH2 tty modes support by Kevin Steves. + * Copyright (c) 2001 Kevin Steves. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Encoding and decoding of terminal modes in a portable way. + * Much of the format is defined in ttymodes.h; it is included multiple times + * into this file with the appropriate macro definitions to generate the + * suitable code. + */ + #include "includes.h" -RCSID("$OpenBSD: ttymodes.c,v 1.11 2001/03/10 15:02:05 stevesk Exp $"); +RCSID("$OpenBSD: ttymodes.c,v 1.12 2001/04/14 16:33:20 stevesk Exp $"); #include "packet.h" #include "log.h" #include "ssh1.h" +#include "compat.h" +#include "buffer.h" +#include "bufaux.h" -#define TTY_OP_END 0 -#define TTY_OP_ISPEED 192 /* int follows */ -#define TTY_OP_OSPEED 193 /* int follows */ +#define TTY_OP_END 0 +/* + * uint32 (u_int) follows speed in SSH1 and SSH2 + */ +#define TTY_OP_ISPEED_PROTO1 192 +#define TTY_OP_OSPEED_PROTO1 193 +#define TTY_OP_ISPEED_PROTO2 128 +#define TTY_OP_OSPEED_PROTO2 129 /* * Converts POSIX speed_t to a baud rate. The values of the @@ -122,7 +158,7 @@ static speed_t baud_to_speed(int baud) { switch (baud) { - case 0: + case 0: return B0; case 50: return B50; @@ -206,41 +242,72 @@ baud_to_speed(int baud) /* * Encodes terminal modes for the terminal referenced by fd - * in a portable manner, and appends the modes to a packet + * or tiop in a portable manner, and appends the modes to a packet * being constructed. */ void -tty_make_modes(int fd) +tty_make_modes(int fd, struct termios *tiop) { struct termios tio; int baud; + Buffer buf; + int tty_op_ospeed, tty_op_ispeed; + void (*put_arg)(Buffer *, u_int); - if (tcgetattr(fd, &tio) < 0) { - packet_put_char(TTY_OP_END); - log("tcgetattr: %.100s", strerror(errno)); - return; + 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; } + + if (tiop == NULL) { + if (tcgetattr(fd, &tio) == -1) { + log("tcgetattr: %.100s", strerror(errno)); + goto end; + } + } else + tio = *tiop; + /* Store input and output baud rates. */ baud = speed_to_baud(cfgetospeed(&tio)); - packet_put_char(TTY_OP_OSPEED); - packet_put_int(baud); + debug2("tty_make_modes: ospeed %d", baud); + buffer_put_char(&buf, tty_op_ospeed); + buffer_put_int(&buf, baud); baud = speed_to_baud(cfgetispeed(&tio)); - packet_put_char(TTY_OP_ISPEED); - packet_put_int(baud); + debug2("tty_make_modes: ispeed %d", baud); + buffer_put_char(&buf, tty_op_ispeed); + buffer_put_int(&buf, baud); /* Store values of mode flags. */ #define TTYCHAR(NAME, OP) \ - packet_put_char(OP); packet_put_char(tio.c_cc[NAME]); + debug2("tty_make_modes: %d %d", OP, tio.c_cc[NAME]); \ + buffer_put_char(&buf, OP); \ + put_arg(&buf, tio.c_cc[NAME]); + #define TTYMODE(NAME, FIELD, OP) \ - packet_put_char(OP); packet_put_char((tio.FIELD & NAME) != 0); + debug2("tty_make_modes: %d %d", OP, ((tio.FIELD & NAME) != 0)); \ + buffer_put_char(&buf, OP); \ + put_arg(&buf, ((tio.FIELD & NAME) != 0)); #include "ttymodes.h" #undef TTYCHAR #undef TTYMODE +end: /* Mark end of mode data. */ - packet_put_char(TTY_OP_END); + 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)); + buffer_free(&buf); + return; } /* @@ -254,14 +321,30 @@ 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, arg_size; + + if (compat20) { + *n_bytes_ptr = packet_get_int(); + debug2("tty_parse_modes: SSH2 n_bytes %d", *n_bytes_ptr); + if (*n_bytes_ptr == 0) + return; + get_arg = packet_get_int; + arg_size = 4; + } else { + get_arg = packet_get_char; + arg_size = 1; + } /* * Get old attributes for the terminal. We will modify these * flags. I am hoping that if there are any machine-specific * modes, they will initially have reasonable values. */ - if (tcgetattr(fd, &tio) < 0) + if (tcgetattr(fd, &tio) == -1) { + log("tcgetattr: %.100s", strerror(errno)); failure = -1; + } for (;;) { n_bytes += 1; @@ -270,32 +353,40 @@ tty_parse_modes(int fd, int *n_bytes_ptr) case TTY_OP_END: goto set; - case TTY_OP_ISPEED: + /* XXX: future conflict possible */ + case TTY_OP_ISPEED_PROTO1: + case TTY_OP_ISPEED_PROTO2: n_bytes += 4; baud = packet_get_int(); - if (failure != -1 && cfsetispeed(&tio, baud_to_speed(baud)) < 0) + debug2("tty_parse_modes: ispeed %d", baud); + if (failure != -1 && cfsetispeed(&tio, baud_to_speed(baud)) == -1) error("cfsetispeed failed for %d", baud); break; - case TTY_OP_OSPEED: + /* XXX: future conflict possible */ + case TTY_OP_OSPEED_PROTO1: + case TTY_OP_OSPEED_PROTO2: n_bytes += 4; baud = packet_get_int(); - if (failure != -1 && cfsetospeed(&tio, baud_to_speed(baud)) < 0) + debug2("tty_parse_modes: ospeed %d", baud); + if (failure != -1 && cfsetospeed(&tio, baud_to_speed(baud)) == -1) error("cfsetospeed failed for %d", baud); break; -#define TTYCHAR(NAME, OP) \ - case OP: \ - n_bytes += 1; \ - tio.c_cc[NAME] = packet_get_char(); \ +#define TTYCHAR(NAME, OP) \ + case OP: \ + n_bytes += arg_size; \ + tio.c_cc[NAME] = get_arg(); \ + debug2("tty_parse_modes: %d %d", OP, tio.c_cc[NAME]); \ break; -#define TTYMODE(NAME, FIELD, OP) \ - case OP: \ - n_bytes += 1; \ - if (packet_get_char()) \ - tio.FIELD |= NAME; \ - else \ - tio.FIELD &= ~NAME; \ +#define TTYMODE(NAME, FIELD, OP) \ + case OP: \ + n_bytes += arg_size; \ + if ((arg = get_arg())) \ + tio.FIELD |= NAME; \ + else \ + tio.FIELD &= ~NAME; \ + debug2("tty_parse_modes: %d %d", OP, arg); \ break; #include "ttymodes.h" @@ -306,48 +397,66 @@ tty_parse_modes(int fd, int *n_bytes_ptr) default: debug("Ignoring unsupported tty mode opcode %d (0x%x)", opcode, opcode); - /* - * Opcodes 0 to 127 are defined to have - * a one-byte argument. - */ - if (opcode >= 0 && opcode < 128) { - n_bytes += 1; - (void) packet_get_char(); - break; + 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. + */ + log("parse_tty_modes: unknown opcode %d", opcode); + packet_integrity_check(0, 1, SSH_CMSG_REQUEST_PTY); + goto set; + } } else { /* - * Opcodes 128 to 159 are defined to have - * an integer argument. + * SSH2: + * Opcodes 0 to 159 are defined to have + * a uint32 argument. + * Opcodes 160 to 255 are undefined and + * cause parsing to stop. */ - if (opcode >= 128 && opcode < 160) { + if (opcode > 0 && opcode < 160) { n_bytes += 4; (void) packet_get_int(); break; + } else { + log("parse_tty_modes: unknown opcode %d", opcode); + goto set; } - } - /* - * 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. - */ - log("parse_tty_modes: unknown opcode %d", opcode); - packet_integrity_check(0, 1, SSH_CMSG_REQUEST_PTY); - goto set; + } } } set: if (*n_bytes_ptr != n_bytes) { *n_bytes_ptr = n_bytes; + log("parse_tty_modes: n_bytes_ptr != n_bytes: %d %d", + *n_bytes_ptr, n_bytes); return; /* Don't process bytes passed */ } if (failure == -1) return; /* Packet parsed ok but tty stuff failed */ /* Set the new modes for the terminal. */ - if (tcsetattr(fd, TCSANOW, &tio) < 0) + if (tcsetattr(fd, TCSANOW, &tio) == -1) log("Setting tty modes failed: %.100s", strerror(errno)); return; } diff --git a/usr.bin/ssh/ttymodes.h b/usr.bin/ssh/ttymodes.h index 860fd0a9cc6..ad980e98cfe 100644 --- a/usr.bin/ssh/ttymodes.h +++ b/usr.bin/ssh/ttymodes.h @@ -1,6 +1,6 @@ +/* RCSID("$OpenBSD: ttymodes.h,v 1.11 2001/04/14 16:33:20 stevesk Exp $"); */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> - * SGTTY stuff contributed by Janne Snabb <snabb@niksula.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * All rights reserved * @@ -11,14 +11,47 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* RCSID("$OpenBSD: ttymodes.h,v 1.10 2001/03/10 15:02:05 stevesk Exp $"); */ +/* + * SSH2 tty modes support by Kevin Steves. + * Copyright (c) 2001 Kevin Steves. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ -/* The tty mode description is a stream of bytes. The stream consists of +/* + * SSH1: + * The tty mode description is a stream of bytes. The stream consists of * opcode-arguments pairs. It is terminated by opcode TTY_OP_END (0). * Opcodes 1-127 have one-byte arguments. Opcodes 128-159 have integer * arguments. Opcodes 160-255 are not yet defined, and cause parsing to * stop (they should only be used after any other data). * + * SSH2: + * Differences between SSH1 and SSH2 terminal mode encoding include: + * 1. Encoded terminal modes are represented as a string, and a stream + * of bytes within that string. + * 2. Opcode arguments are uint32 (1-159); 160-255 remain undefined. + * 3. The values for TTY_OP_ISPEED and TTY_OP_OSPEED are different; + * 128 and 129 vs. 192 and 193 respectively. + * * The client puts in the stream any modes it knows about, and the * server ignores any modes it does not know about. This allows some degree * of machine-independence, at least between systems that use a posix-like |