summaryrefslogtreecommitdiff
path: root/ttymodes.c
diff options
context:
space:
mode:
Diffstat (limited to 'ttymodes.c')
-rw-r--r--ttymodes.c224
1 files changed, 95 insertions, 129 deletions
diff --git a/ttymodes.c b/ttymodes.c
index 6f51b8a7..f0c2a5d3 100644
--- a/ttymodes.c
+++ b/ttymodes.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ttymodes.c,v 1.29 2008/11/02 00:16:16 stevesk Exp $ */
+/* $OpenBSD: ttymodes.c,v 1.34 2018/07/09 21:20:26 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -54,18 +54,16 @@
#include "packet.h"
#include "log.h"
-#include "ssh1.h"
#include "compat.h"
-#include "buffer.h"
+#include "sshbuf.h"
+#include "ssherr.h"
#define TTY_OP_END 0
/*
- * uint32 (u_int) follows speed in SSH1 and SSH2
+ * uint32 (u_int) follows speed.
*/
-#define TTY_OP_ISPEED_PROTO1 192
-#define TTY_OP_OSPEED_PROTO1 193
-#define TTY_OP_ISPEED_PROTO2 128
-#define TTY_OP_OSPEED_PROTO2 129
+#define TTY_OP_ISPEED 128
+#define TTY_OP_OSPEED 129
/*
* Converts POSIX speed_t to a baud rate. The values of the
@@ -278,28 +276,18 @@ special_char_decode(u_int c)
* being constructed.
*/
void
-tty_make_modes(int fd, struct termios *tiop)
+ssh_tty_make_modes(struct ssh *ssh, 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);
-
- 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;
- }
+ struct sshbuf *buf;
+ int r, ibaud, obaud;
+
+ if ((buf = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
if (tiop == NULL) {
if (fd == -1) {
- debug("tty_make_modes: no fd or tio");
+ debug("%s: no fd or tio", __func__);
goto end;
}
if (tcgetattr(fd, &tio) == -1) {
@@ -310,21 +298,29 @@ tty_make_modes(int fd, struct termios *tiop)
tio = *tiop;
/* Store input and output baud rates. */
- baud = speed_to_baud(cfgetospeed(&tio));
- buffer_put_char(&buf, tty_op_ospeed);
- buffer_put_int(&buf, baud);
- baud = speed_to_baud(cfgetispeed(&tio));
- buffer_put_char(&buf, tty_op_ispeed);
- buffer_put_int(&buf, baud);
+ obaud = speed_to_baud(cfgetospeed(&tio));
+ ibaud = speed_to_baud(cfgetispeed(&tio));
+ if ((r = sshbuf_put_u8(buf, TTY_OP_OSPEED)) != 0 ||
+ (r = sshbuf_put_u32(buf, obaud)) != 0 ||
+ (r = sshbuf_put_u8(buf, TTY_OP_ISPEED)) != 0 ||
+ (r = sshbuf_put_u32(buf, ibaud)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
/* Store values of mode flags. */
#define TTYCHAR(NAME, OP) \
- buffer_put_char(&buf, OP); \
- put_arg(&buf, special_char_encode(tio.c_cc[NAME]));
+ if ((r = sshbuf_put_u8(buf, OP)) != 0 || \
+ (r = sshbuf_put_u32(buf, \
+ special_char_encode(tio.c_cc[NAME]))) != 0) \
+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); \
+
+#define SSH_TTYMODE_IUTF8 42 /* for SSH_BUG_UTF8TTYMODE */
#define TTYMODE(NAME, FIELD, OP) \
- buffer_put_char(&buf, OP); \
- put_arg(&buf, ((tio.FIELD & NAME) != 0));
+ if (OP == SSH_TTYMODE_IUTF8 && (datafellows & SSH_BUG_UTF8TTYMODE)) { \
+ debug3("%s: SSH_BUG_UTF8TTYMODE", __func__); \
+ } else if ((r = sshbuf_put_u8(buf, OP)) != 0 || \
+ (r = sshbuf_put_u32(buf, ((tio.FIELD & NAME) != 0))) != 0) \
+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); \
#include "ttymodes.h"
@@ -333,12 +329,10 @@ 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));
- buffer_free(&buf);
+ if ((r = sshbuf_put_u8(buf, TTY_OP_END)) != 0 ||
+ (r = sshpkt_put_stringb(ssh, buf)) != 0)
+ fatal("%s: packet error: %s", __func__, ssh_err(r));
+ sshbuf_free(buf);
}
/*
@@ -346,24 +340,23 @@ end:
* manner from a packet being read.
*/
void
-tty_parse_modes(int fd, int *n_bytes_ptr)
+ssh_tty_parse_modes(struct ssh *ssh, int fd)
{
struct termios tio;
- 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;
+ struct sshbuf *buf;
+ const u_char *data;
+ u_char opcode;
+ u_int baud, u;
+ int r, failure = 0;
+ size_t len;
+
+ if ((r = sshpkt_get_string_direct(ssh, &data, &len)) != 0)
+ fatal("%s: packet error: %s", __func__, ssh_err(r));
+ if (len == 0)
+ return;
+ if ((buf = sshbuf_from(data, len)) == NULL) {
+ error("%s: sshbuf_from failed", __func__);
+ return;
}
/*
@@ -376,46 +369,48 @@ tty_parse_modes(int fd, int *n_bytes_ptr)
failure = -1;
}
- for (;;) {
- n_bytes += 1;
- opcode = packet_get_char();
+ while (sshbuf_len(buf) > 0) {
+ if ((r = sshbuf_get_u8(buf, &opcode)) != 0)
+ fatal("%s: packet error: %s", __func__, ssh_err(r));
switch (opcode) {
case TTY_OP_END:
goto set;
- /* XXX: future conflict possible */
- case TTY_OP_ISPEED_PROTO1:
- case TTY_OP_ISPEED_PROTO2:
- n_bytes += 4;
- baud = packet_get_int();
+ case TTY_OP_ISPEED:
+ if ((r = sshbuf_get_u32(buf, &baud)) != 0)
+ fatal("%s: packet error: %s",
+ __func__, ssh_err(r));
if (failure != -1 &&
cfsetispeed(&tio, baud_to_speed(baud)) == -1)
error("cfsetispeed failed for %d", baud);
break;
- /* XXX: future conflict possible */
- case TTY_OP_OSPEED_PROTO1:
- case TTY_OP_OSPEED_PROTO2:
- n_bytes += 4;
- baud = packet_get_int();
+ case TTY_OP_OSPEED:
+ if ((r = sshbuf_get_u32(buf, &baud)) != 0)
+ fatal("%s: packet error: %s",
+ __func__, ssh_err(r));
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 += arg_size; \
- tio.c_cc[NAME] = special_char_decode(get_arg()); \
- break;
+ case OP: \
+ if ((r = sshbuf_get_u32(buf, &u)) != 0) \
+ fatal("%s: packet error: %s", __func__, \
+ ssh_err(r)); \
+ tio.c_cc[NAME] = special_char_decode(u); \
+ break;
#define TTYMODE(NAME, FIELD, OP) \
- case OP: \
- n_bytes += arg_size; \
- if (get_arg()) \
- tio.FIELD |= NAME; \
- else \
- tio.FIELD &= ~NAME; \
- break;
+ case OP: \
+ if ((r = sshbuf_get_u32(buf, &u)) != 0) \
+ fatal("%s: packet error: %s", __func__, \
+ ssh_err(r)); \
+ if (u) \
+ tio.FIELD |= NAME; \
+ else \
+ tio.FIELD &= ~NAME; \
+ break;
#include "ttymodes.h"
@@ -425,60 +420,31 @@ 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) {
+ if ((r = sshbuf_get_u32(buf, NULL)) != 0)
+ fatal("%s: packet error: %s", __func__,
+ ssh_err(r));
+ 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("%s: unknown opcode %d", __func__,
+ opcode);
+ goto set;
}
}
}
set:
- if (*n_bytes_ptr != n_bytes) {
- *n_bytes_ptr = n_bytes;
- logit("parse_tty_modes: n_bytes_ptr != n_bytes: %d %d",
- *n_bytes_ptr, n_bytes);
+ len = sshbuf_len(buf);
+ sshbuf_free(buf);
+ if (len > 0) {
+ logit("%s: %zu bytes left", __func__, len);
return; /* Don't process bytes passed */
}
if (failure == -1)