version 1.33, 2018/02/16 04:43:11 |
version 1.34, 2018/07/09 21:20:26 |
|
|
#include "packet.h" |
#include "packet.h" |
#include "log.h" |
#include "log.h" |
#include "compat.h" |
#include "compat.h" |
#include "buffer.h" |
#include "sshbuf.h" |
#include "compat.h" |
#include "ssherr.h" |
|
|
#define TTY_OP_END 0 |
#define TTY_OP_END 0 |
/* |
/* |
|
|
* being constructed. |
* being constructed. |
*/ |
*/ |
void |
void |
tty_make_modes(int fd, struct termios *tiop) |
ssh_tty_make_modes(struct ssh *ssh, int fd, struct termios *tiop) |
{ |
{ |
struct termios tio; |
struct termios tio; |
int baud; |
struct sshbuf *buf; |
Buffer buf; |
int r, ibaud, obaud; |
|
|
buffer_init(&buf); |
if ((buf = sshbuf_new()) == NULL) |
|
fatal("%s: sshbuf_new failed", __func__); |
|
|
if (tiop == NULL) { |
if (tiop == NULL) { |
if (fd == -1) { |
if (fd == -1) { |
debug("tty_make_modes: no fd or tio"); |
debug("%s: no fd or tio", __func__); |
goto end; |
goto end; |
} |
} |
if (tcgetattr(fd, &tio) == -1) { |
if (tcgetattr(fd, &tio) == -1) { |
|
|
tio = *tiop; |
tio = *tiop; |
|
|
/* Store input and output baud rates. */ |
/* Store input and output baud rates. */ |
baud = speed_to_baud(cfgetospeed(&tio)); |
obaud = speed_to_baud(cfgetospeed(&tio)); |
buffer_put_char(&buf, TTY_OP_OSPEED); |
ibaud = speed_to_baud(cfgetispeed(&tio)); |
buffer_put_int(&buf, baud); |
if ((r = sshbuf_put_u8(buf, TTY_OP_OSPEED)) != 0 || |
baud = speed_to_baud(cfgetispeed(&tio)); |
(r = sshbuf_put_u32(buf, obaud)) != 0 || |
buffer_put_char(&buf, TTY_OP_ISPEED); |
(r = sshbuf_put_u8(buf, TTY_OP_ISPEED)) != 0 || |
buffer_put_int(&buf, baud); |
(r = sshbuf_put_u32(buf, ibaud)) != 0) |
|
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
|
|
/* Store values of mode flags. */ |
/* Store values of mode flags. */ |
#define TTYCHAR(NAME, OP) \ |
#define TTYCHAR(NAME, OP) \ |
buffer_put_char(&buf, OP); \ |
if ((r = sshbuf_put_u8(buf, OP)) != 0 || \ |
buffer_put_int(&buf, tio.c_cc[NAME]); |
(r = sshbuf_put_u32(buf, tio.c_cc[NAME])) != 0) \ |
|
fatal("%s: buffer error: %s", __func__, ssh_err(r)); \ |
|
|
#define SSH_TTYMODE_IUTF8 42 /* for SSH_BUG_UTF8TTYMODE */ |
#define SSH_TTYMODE_IUTF8 42 /* for SSH_BUG_UTF8TTYMODE */ |
|
|
#define TTYMODE(NAME, FIELD, OP) \ |
#define TTYMODE(NAME, FIELD, OP) \ |
if (OP == SSH_TTYMODE_IUTF8 && (datafellows & SSH_BUG_UTF8TTYMODE)) { \ |
if (OP == SSH_TTYMODE_IUTF8 && (datafellows & SSH_BUG_UTF8TTYMODE)) { \ |
debug3("%s: SSH_BUG_UTF8TTYMODE", __func__); \ |
debug3("%s: SSH_BUG_UTF8TTYMODE", __func__); \ |
} else { \ |
} else if ((r = sshbuf_put_u8(buf, OP)) != 0 || \ |
buffer_put_char(&buf, OP); \ |
(r = sshbuf_put_u32(buf, ((tio.FIELD & NAME) != 0))) != 0) \ |
buffer_put_int(&buf, ((tio.FIELD & NAME) != 0)); \ |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); \ |
} |
|
|
|
#include "ttymodes.h" |
#include "ttymodes.h" |
|
|
|
|
|
|
end: |
end: |
/* Mark end of mode data. */ |
/* Mark end of mode data. */ |
buffer_put_char(&buf, TTY_OP_END); |
if ((r = sshbuf_put_u8(buf, TTY_OP_END)) != 0 || |
packet_put_string(buffer_ptr(&buf), buffer_len(&buf)); |
(r = sshpkt_put_stringb(ssh, buf)) != 0) |
buffer_free(&buf); |
fatal("%s: packet error: %s", __func__, ssh_err(r)); |
|
sshbuf_free(buf); |
} |
} |
|
|
/* |
/* |
|
|
* manner from a packet being read. |
* manner from a packet being read. |
*/ |
*/ |
void |
void |
tty_parse_modes(int fd, int *n_bytes_ptr) |
ssh_tty_parse_modes(struct ssh *ssh, int fd) |
{ |
{ |
struct termios tio; |
struct termios tio; |
int opcode, baud; |
struct sshbuf *buf; |
int n_bytes = 0; |
const u_char *data; |
int failure = 0; |
u_char opcode; |
|
u_int baud, u; |
|
int r, failure = 0; |
|
size_t len; |
|
|
*n_bytes_ptr = packet_get_int(); |
if ((r = sshpkt_get_string_direct(ssh, &data, &len)) != 0) |
if (*n_bytes_ptr == 0) |
fatal("%s: packet error: %s", __func__, ssh_err(r)); |
|
if (len == 0) |
return; |
return; |
|
if ((buf = sshbuf_from(data, len)) == NULL) { |
|
error("%s: sshbuf_from failed", __func__); |
|
return; |
|
} |
|
|
/* |
/* |
* Get old attributes for the terminal. We will modify these |
* Get old attributes for the terminal. We will modify these |
|
|
failure = -1; |
failure = -1; |
} |
} |
|
|
for (;;) { |
while (sshbuf_len(buf) > 0) { |
n_bytes += 1; |
if ((r = sshbuf_get_u8(buf, &opcode)) != 0) |
opcode = packet_get_char(); |
fatal("%s: packet error: %s", __func__, ssh_err(r)); |
switch (opcode) { |
switch (opcode) { |
case TTY_OP_END: |
case TTY_OP_END: |
goto set; |
goto set; |
|
|
case TTY_OP_ISPEED: |
case TTY_OP_ISPEED: |
n_bytes += 4; |
if ((r = sshbuf_get_u32(buf, &baud)) != 0) |
baud = packet_get_int(); |
fatal("%s: packet error: %s", |
|
__func__, ssh_err(r)); |
if (failure != -1 && |
if (failure != -1 && |
cfsetispeed(&tio, baud_to_speed(baud)) == -1) |
cfsetispeed(&tio, baud_to_speed(baud)) == -1) |
error("cfsetispeed failed for %d", baud); |
error("cfsetispeed failed for %d", baud); |
break; |
break; |
|
|
case TTY_OP_OSPEED: |
case TTY_OP_OSPEED: |
n_bytes += 4; |
if ((r = sshbuf_get_u32(buf, &baud)) != 0) |
baud = packet_get_int(); |
fatal("%s: packet error: %s", |
|
__func__, ssh_err(r)); |
if (failure != -1 && |
if (failure != -1 && |
cfsetospeed(&tio, baud_to_speed(baud)) == -1) |
cfsetospeed(&tio, baud_to_speed(baud)) == -1) |
error("cfsetospeed failed for %d", baud); |
error("cfsetospeed failed for %d", baud); |
break; |
break; |
|
|
#define TTYCHAR(NAME, OP) \ |
#define TTYCHAR(NAME, OP) \ |
case OP: \ |
case OP: \ |
n_bytes += 4; \ |
if ((r = sshbuf_get_u32(buf, &u)) != 0) \ |
tio.c_cc[NAME] = packet_get_int(); \ |
fatal("%s: packet error: %s", __func__, \ |
break; |
ssh_err(r)); \ |
|
tio.c_cc[NAME] = u; \ |
|
break; |
#define TTYMODE(NAME, FIELD, OP) \ |
#define TTYMODE(NAME, FIELD, OP) \ |
case OP: \ |
case OP: \ |
n_bytes += 4; \ |
if ((r = sshbuf_get_u32(buf, &u)) != 0) \ |
if (packet_get_int()) \ |
fatal("%s: packet error: %s", __func__, \ |
tio.FIELD |= NAME; \ |
ssh_err(r)); \ |
else \ |
if (u) \ |
tio.FIELD &= ~NAME; \ |
tio.FIELD |= NAME; \ |
break; |
else \ |
|
tio.FIELD &= ~NAME; \ |
|
break; |
|
|
#include "ttymodes.h" |
#include "ttymodes.h" |
|
|
|
|
* to stop. |
* to stop. |
*/ |
*/ |
if (opcode > 0 && opcode < 160) { |
if (opcode > 0 && opcode < 160) { |
n_bytes += 4; |
if ((r = sshbuf_get_u32(buf, NULL)) != 0) |
(void) packet_get_int(); |
fatal("%s: packet error: %s", __func__, |
|
ssh_err(r)); |
break; |
break; |
} else { |
} else { |
logit("parse_tty_modes: unknown opcode %d", |
logit("%s: unknown opcode %d", __func__, |
opcode); |
opcode); |
goto set; |
goto set; |
} |
} |
|
|
} |
} |
|
|
set: |
set: |
if (*n_bytes_ptr != n_bytes) { |
len = sshbuf_len(buf); |
*n_bytes_ptr = n_bytes; |
sshbuf_free(buf); |
logit("parse_tty_modes: n_bytes_ptr != n_bytes: %d %d", |
if (len > 0) { |
*n_bytes_ptr, n_bytes); |
logit("%s: %zu bytes left", __func__, len); |
return; /* Don't process bytes passed */ |
return; /* Don't process bytes passed */ |
} |
} |
if (failure == -1) |
if (failure == -1) |