summaryrefslogtreecommitdiffstats
path: root/clientloop.c
diff options
context:
space:
mode:
authormarkus@openbsd.org <markus@openbsd.org>2018-07-09 21:03:30 +0000
committerDamien Miller <djm@mindrot.org>2018-07-10 15:14:26 +1000
commitcecee2d607099a7bba0a84803e2325d15be4277b (patch)
treee5f685fb39c9d8512235334afc4b26e8461bfc36 /clientloop.c
parentff55f4ad898137d4703e7a2bcc81167dfe8e9324 (diff)
upstream: client: switch to sshbuf API; ok djm@
Diffstat (limited to 'clientloop.c')
-rw-r--r--clientloop.c202
1 files changed, 113 insertions, 89 deletions
diff --git a/clientloop.c b/clientloop.c
index 9a5865b2..8da5d914 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clientloop.c,v 1.314 2018/06/26 02:02:36 djm Exp $ */
+/* $OpenBSD: clientloop.c,v 1.315 2018/07/09 21:03:30 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -91,7 +91,7 @@
#include "ssh.h"
#include "ssh2.h"
#include "packet.h"
-#include "buffer.h"
+#include "sshbuf.h"
#include "compat.h"
#include "channels.h"
#include "dispatch.h"
@@ -153,7 +153,7 @@ static time_t control_persist_exit_time = 0;
volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */
static int last_was_cr; /* Last character was a newline. */
static int exit_status; /* Used to store the command exit status. */
-static Buffer stderr_buffer; /* Used for final exit message. */
+static struct sshbuf *stderr_buffer; /* Used for final exit message. */
static int connection_in; /* Connection to server (input). */
static int connection_out; /* Connection to server (output). */
static int need_rekeying; /* Set to non-zero if rekeying is requested. */
@@ -188,7 +188,7 @@ TAILQ_HEAD(global_confirms, global_confirm);
static struct global_confirms global_confirms =
TAILQ_HEAD_INITIALIZER(global_confirms);
-void ssh_process_session2_setup(int, int, int, Buffer *);
+void ssh_process_session2_setup(int, int, int, struct sshbuf *);
/* Restores stdin to blocking mode. */
@@ -493,7 +493,7 @@ client_wait_until_can_do_something(struct ssh *ssh,
struct timeval tv, *tvp;
int timeout_secs;
time_t minwait_secs = 0, server_alive_time = 0, now = monotime();
- int ret;
+ int r, ret;
/* Add any selections by the channel mechanism. */
channel_prepare_select(active_state, readsetp, writesetp, maxfdp,
@@ -546,8 +546,6 @@ client_wait_until_can_do_something(struct ssh *ssh,
ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
if (ret < 0) {
- char buf[100];
-
/*
* We have to clear the select masks, because we return.
* We have to return, because the mainloop checks for the flags
@@ -559,8 +557,9 @@ client_wait_until_can_do_something(struct ssh *ssh,
if (errno == EINTR)
return;
/* Note: we might still have data in the buffers. */
- snprintf(buf, sizeof buf, "select: %s\r\n", strerror(errno));
- buffer_append(&stderr_buffer, buf, strlen(buf));
+ if ((r = sshbuf_putf(stderr_buffer,
+ "select: %s\r\n", strerror(errno))) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
quit_pending = 1;
} else if (ret == 0) {
/*
@@ -574,15 +573,15 @@ client_wait_until_can_do_something(struct ssh *ssh,
}
static void
-client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
+client_suspend_self(struct sshbuf *bin, struct sshbuf *bout, struct sshbuf *berr)
{
/* Flush stdout and stderr buffers. */
- if (buffer_len(bout) > 0)
- atomicio(vwrite, fileno(stdout), buffer_ptr(bout),
- buffer_len(bout));
- if (buffer_len(berr) > 0)
- atomicio(vwrite, fileno(stderr), buffer_ptr(berr),
- buffer_len(berr));
+ if (sshbuf_len(bout) > 0)
+ atomicio(vwrite, fileno(stdout), sshbuf_mutable_ptr(bout),
+ sshbuf_len(bout));
+ if (sshbuf_len(berr) > 0)
+ atomicio(vwrite, fileno(stderr), sshbuf_mutable_ptr(berr),
+ sshbuf_len(berr));
leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
@@ -602,8 +601,8 @@ client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
static void
client_process_net_input(fd_set *readset)
{
- int len;
char buf[SSH_IOBUFSZ];
+ int r, len;
/*
* Read input from the server, and add any such data to the buffer of
@@ -617,10 +616,11 @@ client_process_net_input(fd_set *readset)
* Received EOF. The remote host has closed the
* connection.
*/
- snprintf(buf, sizeof buf,
+ if ((r = sshbuf_putf(stderr_buffer,
"Connection to %.300s closed by remote host.\r\n",
- host);
- buffer_append(&stderr_buffer, buf, strlen(buf));
+ host)) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
quit_pending = 1;
return;
}
@@ -637,10 +637,11 @@ client_process_net_input(fd_set *readset)
* An error has encountered. Perhaps there is a
* network problem.
*/
- snprintf(buf, sizeof buf,
+ if ((r = sshbuf_putf(stderr_buffer,
"Read from remote host %.300s: %.100s\r\n",
- host, strerror(errno));
- buffer_append(&stderr_buffer, buf, strlen(buf));
+ host, strerror(errno))) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
quit_pending = 1;
return;
}
@@ -653,7 +654,7 @@ client_status_confirm(struct ssh *ssh, int type, Channel *c, void *ctx)
{
struct channel_reply_ctx *cr = (struct channel_reply_ctx *)ctx;
char errmsg[256];
- int tochan;
+ int r, tochan;
/*
* If a TTY was explicitly requested, then a failure to allocate
@@ -688,7 +689,10 @@ client_status_confirm(struct ssh *ssh, int type, Channel *c, void *ctx)
* their stderr.
*/
if (tochan) {
- buffer_append(c->extended, errmsg, strlen(errmsg));
+ if ((r = sshbuf_put(c->extended, errmsg,
+ strlen(errmsg))) != 0)
+ fatal("%s: buffer error %s", __func__,
+ ssh_err(r));
} else
error("%s", errmsg);
if (cr->action == CONFIRM_TTY) {
@@ -892,14 +896,15 @@ static struct escape_help_text esc_txt[] = {
};
static void
-print_escape_help(Buffer *b, int escape_char, int mux_client, int using_stderr)
+print_escape_help(struct sshbuf *b, int escape_char, int mux_client,
+ int using_stderr)
{
unsigned int i, suppress_flags;
- char string[1024];
+ int r;
- snprintf(string, sizeof string, "%c?\r\n"
- "Supported escape sequences:\r\n", escape_char);
- buffer_append(b, string, strlen(string));
+ if ((r = sshbuf_putf(b,
+ "%c?\r\nSupported escape sequences:\r\n", escape_char)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
suppress_flags =
(mux_client ? SUPPRESS_MUXCLIENT : 0) |
@@ -909,16 +914,16 @@ print_escape_help(Buffer *b, int escape_char, int mux_client, int using_stderr)
for (i = 0; i < sizeof(esc_txt)/sizeof(esc_txt[0]); i++) {
if (esc_txt[i].flags & suppress_flags)
continue;
- snprintf(string, sizeof string, " %c%-3s - %s\r\n",
- escape_char, esc_txt[i].cmd, esc_txt[i].text);
- buffer_append(b, string, strlen(string));
+ if ((r = sshbuf_putf(b, " %c%-3s - %s\r\n",
+ escape_char, esc_txt[i].cmd, esc_txt[i].text)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
- snprintf(string, sizeof string,
+ if ((r = sshbuf_putf(b,
" %c%c - send the escape character by typing it twice\r\n"
"(Note that escapes are only recognized immediately after "
- "newline.)\r\n", escape_char, escape_char);
- buffer_append(b, string, strlen(string));
+ "newline.)\r\n", escape_char, escape_char)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
/*
@@ -926,12 +931,11 @@ print_escape_help(Buffer *b, int escape_char, int mux_client, int using_stderr)
*/
static int
process_escapes(struct ssh *ssh, Channel *c,
- Buffer *bin, Buffer *bout, Buffer *berr,
+ struct sshbuf *bin, struct sshbuf *bout, struct sshbuf *berr,
char *buf, int len)
{
- char string[1024];
pid_t pid;
- int bytes = 0;
+ int r, bytes = 0;
u_int i;
u_char ch;
char *s;
@@ -957,10 +961,10 @@ process_escapes(struct ssh *ssh, Channel *c,
switch (ch) {
case '.':
/* Terminate the connection. */
- snprintf(string, sizeof string, "%c.\r\n",
- efc->escape_char);
- buffer_append(berr, string, strlen(string));
-
+ if ((r = sshbuf_putf(berr, "%c.\r\n",
+ efc->escape_char)) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
if (c && c->ctl_chan != -1) {
chan_read_failed(ssh, c);
chan_write_failed(ssh, c);
@@ -969,7 +973,7 @@ process_escapes(struct ssh *ssh, Channel *c,
c->self, NULL);
}
c->type = SSH_CHANNEL_ABANDONED;
- buffer_clear(c->input);
+ sshbuf_reset(c->input);
chan_ibuf_empty(ssh, c);
return 0;
} else
@@ -985,18 +989,20 @@ process_escapes(struct ssh *ssh, Channel *c,
snprintf(b, sizeof b, "^Z");
else
snprintf(b, sizeof b, "%c", ch);
- snprintf(string, sizeof string,
+ if ((r = sshbuf_putf(berr,
"%c%s escape not available to "
"multiplexed sessions\r\n",
- efc->escape_char, b);
- buffer_append(berr, string,
- strlen(string));
+ efc->escape_char, b)) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
continue;
}
/* Suspend the program. Inform the user */
- snprintf(string, sizeof string,
- "%c^Z [suspend ssh]\r\n", efc->escape_char);
- buffer_append(berr, string, strlen(string));
+ if ((r = sshbuf_putf(berr,
+ "%c^Z [suspend ssh]\r\n",
+ efc->escape_char)) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
/* Restore terminal modes and suspend. */
client_suspend_self(bin, bout, berr);
@@ -1005,12 +1011,15 @@ process_escapes(struct ssh *ssh, Channel *c,
continue;
case 'B':
- snprintf(string, sizeof string,
- "%cB\r\n", efc->escape_char);
- buffer_append(berr, string, strlen(string));
+ if ((r = sshbuf_putf(berr,
+ "%cB\r\n", efc->escape_char)) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
channel_request_start(ssh, c->self, "break", 0);
- packet_put_int(1000);
- packet_send();
+ if ((r = sshpkt_put_u32(ssh, 1000)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ fatal("%s: %s", __func__,
+ ssh_err(r));
continue;
case 'R':
@@ -1027,11 +1036,11 @@ process_escapes(struct ssh *ssh, Channel *c,
if (c && c->ctl_chan != -1)
goto noescape;
if (!log_is_on_stderr()) {
- snprintf(string, sizeof string,
+ if ((r = sshbuf_putf(berr,
"%c%c [Logging to syslog]\r\n",
- efc->escape_char, ch);
- buffer_append(berr, string,
- strlen(string));
+ efc->escape_char, ch)) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
continue;
}
if (ch == 'V' && options.log_level >
@@ -1040,11 +1049,12 @@ process_escapes(struct ssh *ssh, Channel *c,
if (ch == 'v' && options.log_level <
SYSLOG_LEVEL_DEBUG3)
log_change_level(++options.log_level);
- snprintf(string, sizeof string,
+ if ((r = sshbuf_putf(berr,
"%c%c [LogLevel %s]\r\n",
efc->escape_char, ch,
- log_level_name(options.log_level));
- buffer_append(berr, string, strlen(string));
+ log_level_name(options.log_level))) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
continue;
case '&':
@@ -1062,9 +1072,11 @@ process_escapes(struct ssh *ssh, Channel *c,
/* Stop listening for new connections. */
channel_stop_listening(ssh);
- snprintf(string, sizeof string,
- "%c& [backgrounded]\n", efc->escape_char);
- buffer_append(berr, string, strlen(string));
+ if ((r = sshbuf_putf(berr,
+ "%c& [backgrounded]\n", efc->escape_char))
+ != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
/* Fork into background. */
pid = fork();
@@ -1077,8 +1089,10 @@ process_escapes(struct ssh *ssh, Channel *c,
exit(0);
}
/* The child continues serving connections. */
- buffer_append(bin, "\004", 1);
/* fake EOF on stdin */
+ if ((r = sshbuf_put_u8(bin, 4)) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
return -1;
case '?':
print_escape_help(berr, efc->escape_char,
@@ -1087,11 +1101,14 @@ process_escapes(struct ssh *ssh, Channel *c,
continue;
case '#':
- snprintf(string, sizeof string, "%c#\r\n",
- efc->escape_char);
- buffer_append(berr, string, strlen(string));
+ if ((r = sshbuf_putf(berr, "%c#\r\n",
+ efc->escape_char)) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
s = channel_open_message(ssh);
- buffer_append(berr, s, strlen(s));
+ if ((r = sshbuf_put(berr, s, strlen(s))) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
free(s);
continue;
@@ -1103,7 +1120,10 @@ process_escapes(struct ssh *ssh, Channel *c,
default:
if (ch != efc->escape_char) {
- buffer_put_char(bin, efc->escape_char);
+ if ((r = sshbuf_put_u8(bin,
+ efc->escape_char)) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
bytes++;
}
/* Escaped characters fall through here */
@@ -1129,7 +1149,8 @@ process_escapes(struct ssh *ssh, Channel *c,
* and append it to the buffer.
*/
last_was_cr = (ch == '\r' || ch == '\n');
- buffer_put_char(bin, ch);
+ if ((r = sshbuf_put_u8(bin, ch)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
bytes++;
}
return bytes;
@@ -1253,8 +1274,9 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg,
quit_pending = 0;
- /* Initialize buffers. */
- buffer_init(&stderr_buffer);
+ /* Initialize buffer. */
+ if ((stderr_buffer = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
client_init_dispatch();
@@ -1411,24 +1433,25 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg,
* that the connection has been closed.
*/
if (have_pty && options.log_level != SYSLOG_LEVEL_QUIET) {
- snprintf(buf, sizeof buf,
- "Connection to %.64s closed.\r\n", host);
- buffer_append(&stderr_buffer, buf, strlen(buf));
+ if ((r = sshbuf_putf(stderr_buffer,
+ "Connection to %.64s closed.\r\n", host)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
/* Output any buffered data for stderr. */
- if (buffer_len(&stderr_buffer) > 0) {
+ if (sshbuf_len(stderr_buffer) > 0) {
len = atomicio(vwrite, fileno(stderr),
- buffer_ptr(&stderr_buffer), buffer_len(&stderr_buffer));
- if (len < 0 || (u_int)len != buffer_len(&stderr_buffer))
+ (u_char *)sshbuf_ptr(stderr_buffer),
+ sshbuf_len(stderr_buffer));
+ if (len < 0 || (u_int)len != sshbuf_len(stderr_buffer))
error("Write failed flushing stderr buffer.");
- else
- buffer_consume(&stderr_buffer, len);
+ else if ((r = sshbuf_consume(stderr_buffer, len)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
/* Clear and free any buffers. */
explicit_bzero(buf, sizeof(buf));
- buffer_free(&stderr_buffer);
+ sshbuf_free(stderr_buffer);
/* Report bytes transferred, and transfer rates. */
total_time = monotime_double() - start_time;
@@ -2156,7 +2179,8 @@ client_input_global_request(int type, u_int32_t seq, struct ssh *ssh)
void
client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem,
- const char *term, struct termios *tiop, int in_fd, Buffer *cmd, char **env)
+ const char *term, struct termios *tiop, int in_fd, struct sshbuf *cmd,
+ char **env)
{
int i, j, matched, len;
char *name, *val;
@@ -2242,23 +2266,23 @@ client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem,
free(name);
}
- len = buffer_len(cmd);
+ len = sshbuf_len(cmd);
if (len > 0) {
if (len > 900)
len = 900;
if (want_subsystem) {
debug("Sending subsystem: %.*s",
- len, (u_char*)buffer_ptr(cmd));
+ len, (const u_char*)sshbuf_ptr(cmd));
channel_request_start(ssh, id, "subsystem", 1);
client_expect_confirm(ssh, id, "subsystem",
CONFIRM_CLOSE);
} else {
debug("Sending command: %.*s",
- len, (u_char*)buffer_ptr(cmd));
+ len, (const u_char*)sshbuf_ptr(cmd));
channel_request_start(ssh, id, "exec", 1);
client_expect_confirm(ssh, id, "exec", CONFIRM_CLOSE);
}
- packet_put_string(buffer_ptr(cmd), buffer_len(cmd));
+ packet_put_string(sshbuf_ptr(cmd), sshbuf_len(cmd));
packet_send();
} else {
channel_request_start(ssh, id, "shell", 1);