diff options
author | markus@openbsd.org <markus@openbsd.org> | 2018-07-09 21:03:30 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2018-07-10 15:14:26 +1000 |
commit | cecee2d607099a7bba0a84803e2325d15be4277b (patch) | |
tree | e5f685fb39c9d8512235334afc4b26e8461bfc36 /clientloop.c | |
parent | ff55f4ad898137d4703e7a2bcc81167dfe8e9324 (diff) |
upstream: client: switch to sshbuf API; ok djm@
OpenBSD-Commit-ID: 60cb0356114acc7625ab85105f6f6a7cd44a8d05
Diffstat (limited to 'clientloop.c')
-rw-r--r-- | clientloop.c | 202 |
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); |