diff --git a/ssh/servconf.c b/ssh/servconf.c index a9398b4..edf6e29 100644 --- a/ssh/servconf.c +++ b/ssh/servconf.c @@ -32,7 +32,7 @@ #include "xmalloc.h" #include "ssh.h" #include "log.h" -#include "buffer.h" +#include "sshbuf.h" #include "servconf.h" #include "compat.h" #include "pathnames.h" @@ -52,7 +52,7 @@ static void add_one_listen_addr(ServerOptions *, char *, int); /* Use of privilege separation or not */ extern int use_privsep; -extern Buffer cfg; +extern struct sshbuf *cfg; /* Initializes the server options to their default values. */ @@ -1480,7 +1480,7 @@ process_server_config_line(ServerOptions *options, char *line, /* Reads the server configuration file. */ void -load_server_config(const char *filename, Buffer *conf) +load_server_config(const char *filename, struct sshbuf *conf) { char line[4096], *cp; FILE *f; @@ -1519,7 +1519,7 @@ parse_server_match_config(ServerOptions *options, ServerOptions mo; initialize_server_options(&mo); - parse_server_config(&mo, "reprocess config", &cfg, connectinfo); + parse_server_config(&mo, "reprocess config", cfg, connectinfo); copy_set_server_options(options, &mo, 0); } @@ -1637,8 +1637,8 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) #undef M_CP_STRARRAYOPT void -parse_server_config(ServerOptions *options, const char *filename, Buffer *conf, - struct connection_info *connectinfo) +parse_server_config(ServerOptions *options, const char *filename, + struct sshbuf *conf, struct connection_info *connectinfo) { int active, linenum, bad_options = 0; char *cp, *obuf, *cbuf; diff --git a/ssh/serverloop.c b/ssh/serverloop.c index 518518e..54b4af8 100644 --- a/ssh/serverloop.c +++ b/ssh/serverloop.c @@ -57,7 +57,7 @@ #define PACKET_SKIP_COMPAT #define PACKET_SKIP_COMPAT2 #include "packet.h" -#include "buffer.h" +#include "sshbuf.h" #include "log.h" #include "servconf.h" #include "sshpty.h" @@ -83,17 +83,17 @@ extern ServerOptions options; extern Authctxt *the_authctxt; extern int use_privsep; -static Buffer stdin_buffer; /* Buffer for stdin data. */ -static Buffer stdout_buffer; /* Buffer for stdout data. */ -static Buffer stderr_buffer; /* Buffer for stderr data. */ +static struct sshbuf *stdin_buffer; /* Buffer for stdin data. */ +static struct sshbuf *stdout_buffer; /* Buffer for stdout data. */ +static struct sshbuf *stderr_buffer; /* Buffer for stderr data. */ static int fdin; /* Descriptor for stdin (for writing) */ static int fdout; /* Descriptor for stdout (for reading); May be same number as fdin. */ static int fderr; /* Descriptor for stderr. May be -1. */ -static long stdin_bytes = 0; /* Number of bytes written to stdin. */ -static long stdout_bytes = 0; /* Number of stdout bytes sent to client. */ -static long stderr_bytes = 0; /* Number of stderr bytes sent to client. */ -static long fdout_bytes = 0; /* Number of stdout bytes read from program. */ +static size_t stdin_bytes = 0; /* Number of bytes written to stdin. */ +static size_t stdout_bytes = 0; /* Number of stdout bytes sent to client. */ +static size_t stderr_bytes = 0; /* Number of stderr bytes sent to client. */ +static size_t fdout_bytes = 0; /* Number of stdout bytes read from program. */ static int stdin_eof = 0; /* EOF message received from client. */ static int fdout_eof = 0; /* EOF encountered reading from fdout. */ static int fderr_eof = 0; /* EOF encountered readung from fderr. */ @@ -187,13 +187,13 @@ sigterm_handler(int sig) static void make_packets_from_stderr_data(struct ssh *ssh) { - u_int len; + size_t len; int r; /* Send buffered stderr data to the client. */ - while (buffer_len(&stderr_buffer) > 0 && + while (sshbuf_len(stderr_buffer) > 0 && ssh_packet_not_very_much_data_to_write(ssh)) { - len = buffer_len(&stderr_buffer); + len = sshbuf_len(stderr_buffer); if (ssh_packet_is_interactive(ssh)) { if (len > 512) len = 512; @@ -203,11 +203,12 @@ make_packets_from_stderr_data(struct ssh *ssh) len = ssh_packet_get_maxsize(ssh); } if ((r = sshpkt_start(ssh, SSH_SMSG_STDERR_DATA)) != 0 || - (r = sshpkt_put_string(ssh, buffer_ptr(&stderr_buffer), + (r = sshpkt_put_string(ssh, sshbuf_ptr(stderr_buffer), len)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal("%s: %s", __func__, ssh_err(r)); - buffer_consume(&stderr_buffer, len); + if ((r = sshbuf_consume(stderr_buffer, len)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); stderr_bytes += len; } } @@ -219,13 +220,13 @@ make_packets_from_stderr_data(struct ssh *ssh) static void make_packets_from_stdout_data(struct ssh *ssh) { - u_int len; + size_t len; int r; /* Send buffered stdout data to the client. */ - while (buffer_len(&stdout_buffer) > 0 && + while (sshbuf_len(stdout_buffer) > 0 && ssh_packet_not_very_much_data_to_write(ssh)) { - len = buffer_len(&stdout_buffer); + len = sshbuf_len(stdout_buffer); if (ssh_packet_is_interactive(ssh)) { if (len > 512) len = 512; @@ -235,11 +236,12 @@ make_packets_from_stdout_data(struct ssh *ssh) len = ssh_packet_get_maxsize(ssh); } if ((r = sshpkt_start(ssh, SSH_SMSG_STDOUT_DATA)) != 0 || - (r = sshpkt_put_string(ssh, buffer_ptr(&stdout_buffer), + (r = sshpkt_put_string(ssh, sshbuf_ptr(stdout_buffer), len)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal("%s: %s", __func__, ssh_err(r)); - buffer_consume(&stdout_buffer, len); + if ((r = sshbuf_consume(stdout_buffer, len)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); stdout_bytes += len; } } @@ -320,7 +322,7 @@ wait_until_can_do_something(struct ssh *ssh, fd_set **readsetp, fd_set **writese * Read packets from the client unless we have too much * buffered stdin or channel data. */ - if (buffer_len(&stdin_buffer) < buffer_high && + if (sshbuf_len(stdin_buffer) < buffer_high && channel_not_very_much_buffered_data()) FD_SET(connection_in, *readsetp); /* @@ -337,7 +339,7 @@ wait_until_can_do_something(struct ssh *ssh, fd_set **readsetp, fd_set **writese * If we have buffered data, try to write some of that data * to the program. */ - if (fdin != -1 && buffer_len(&stdin_buffer) > 0) + if (fdin != -1 && sshbuf_len(stdin_buffer) > 0) FD_SET(fdin, *writesetp); } notify_prepare(*readsetp); @@ -386,7 +388,7 @@ wait_until_can_do_something(struct ssh *ssh, fd_set **readsetp, fd_set **writese static void process_input(struct ssh *ssh, fd_set *readset) { - int len; + int len, r; char buf[16384]; /* Read and buffer any input data from the client. */ @@ -425,7 +427,9 @@ process_input(struct ssh *ssh, fd_set *readset) } else if (len <= 0) { fdout_eof = 1; } else { - buffer_append(&stdout_buffer, buf, len); + if ((r = sshbuf_put(stdout_buffer, buf, len)) != 0) + fatal("%s: buffer error: %s", + __func__, ssh_err(r)); fdout_bytes += len; } } @@ -437,7 +441,9 @@ process_input(struct ssh *ssh, fd_set *readset) } else if (len <= 0) { fderr_eof = 1; } else { - buffer_append(&stderr_buffer, buf, len); + if ((r = sshbuf_put(stderr_buffer, buf, len)) != 0) + fatal("%s: buffer error: %s", + __func__, ssh_err(r)); } } } @@ -455,8 +461,8 @@ process_output(struct ssh *ssh, fd_set *writeset) /* Write buffered data to program stdin. */ if (!compat20 && fdin != -1 && FD_ISSET(fdin, writeset)) { - data = buffer_ptr(&stdin_buffer); - dlen = buffer_len(&stdin_buffer); + data = sshbuf_ptr(stdin_buffer); + dlen = sshbuf_len(stdin_buffer); len = write(fdin, data, dlen); if (len < 0 && (errno == EINTR || errno == EAGAIN)) { /* do nothing */ @@ -480,7 +486,9 @@ process_output(struct ssh *ssh, fd_set *writeset) fatal("%s: %s", __func__, ssh_err(r)); } /* Consume the data from the buffer. */ - buffer_consume(&stdin_buffer, len); + if ((r = sshbuf_consume(stdin_buffer, len)) != 0) + fatal("%s: buffer error: %s", __func__, + ssh_err(r)); /* Update the count of bytes written to the program. */ stdin_bytes += len; } @@ -500,23 +508,23 @@ drain_output(struct ssh *ssh) int r; /* Send any buffered stdout data to the client. */ - if (buffer_len(&stdout_buffer) > 0) { + if (sshbuf_len(stdout_buffer) > 0) { if ((r = sshpkt_start(ssh, SSH_SMSG_STDOUT_DATA)) != 0 || - (r = sshpkt_put_string(ssh, buffer_ptr(&stdout_buffer), - buffer_len(&stdout_buffer))) != 0 || + (r = sshpkt_put_string(ssh, sshbuf_ptr(stdout_buffer), + sshbuf_len(stdout_buffer))) != 0 || (r = sshpkt_send(ssh)) != 0) fatal("%s: %s", __func__, ssh_err(r)); /* Update the count of sent bytes. */ - stdout_bytes += buffer_len(&stdout_buffer); + stdout_bytes += sshbuf_len(stdout_buffer); } /* Send any buffered stderr data to the client. */ - if (buffer_len(&stderr_buffer) > 0) { + if (sshbuf_len(stderr_buffer) > 0) { if ((r = sshpkt_start(ssh, SSH_SMSG_STDERR_DATA)) != 0 || - (r = sshpkt_put_string(ssh, buffer_ptr(&stderr_buffer), - buffer_len(&stderr_buffer))) != 0 || + (r = sshpkt_put_string(ssh, sshbuf_ptr(stderr_buffer), + sshbuf_len(stderr_buffer))) != 0 || (r = sshpkt_send(ssh)) != 0) /* Update the count of sent bytes. */ - stderr_bytes += buffer_len(&stderr_buffer); + stderr_bytes += sshbuf_len(stderr_buffer); } /* Wait until all buffered data has been written to the client. */ ssh_packet_write_wait(ssh); @@ -603,9 +611,12 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) #endif /* Initialize Initialize buffers. */ - buffer_init(&stdin_buffer); - buffer_init(&stdout_buffer); - buffer_init(&stderr_buffer); + if ((stdin_buffer = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if ((stdout_buffer = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if ((stderr_buffer = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); /* * If we have no separate fderr (which is the case when we have a pty @@ -628,7 +639,7 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) * If we have received eof, and there is no more pending * input data, cause a real eof by closing fdin. */ - if (stdin_eof && fdin != -1 && buffer_len(&stdin_buffer) == 0) { + if (stdin_eof && fdin != -1 && sshbuf_len(stdin_buffer) == 0) { if (fdin != fdout) close(fdin); else @@ -646,7 +657,7 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) * wake up readers from a pty after each separate character. */ max_time_milliseconds = 0; - stdout_buffer_bytes = buffer_len(&stdout_buffer); + stdout_buffer_bytes = sshbuf_len(stdout_buffer); if (stdout_buffer_bytes != 0 && stdout_buffer_bytes < 256 && stdout_buffer_bytes != previous_stdout_buffer_bytes) { /* try again after a while */ @@ -655,7 +666,7 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) /* Send it now. */ make_packets_from_stdout_data(ssh); } - previous_stdout_buffer_bytes = buffer_len(&stdout_buffer); + previous_stdout_buffer_bytes = sshbuf_len(stdout_buffer); /* Send channel data to the client. */ if (ssh_packet_not_very_much_data_to_write(ssh)) @@ -667,18 +678,21 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) * client, and there is no pending buffered data. */ if (fdout_eof && fderr_eof && !ssh_packet_have_data_to_write(ssh) && - buffer_len(&stdout_buffer) == 0 && buffer_len(&stderr_buffer) == 0) { + sshbuf_len(stdout_buffer) == 0 && sshbuf_len(stderr_buffer) == 0) { if (!channel_still_open()) break; if (!waiting_termination) { const char *s = "Waiting for forwarded connections to terminate...\r\n"; - char *cp; - waiting_termination = 1; - buffer_append(&stderr_buffer, s, strlen(s)); + char *cp = channel_open_message(); + waiting_termination = 1; /* Display list of open channels. */ - cp = channel_open_message(); - buffer_append(&stderr_buffer, cp, strlen(cp)); + if ((r = sshbuf_put(stderr_buffer, + s, strlen(s))) != 0 || + (r = sshbuf_put(stderr_buffer, + s, strlen(s))) != 0) + fatal("%s: buffer error: %s", + __func__, ssh_err(r)); xfree(cp); } } @@ -721,9 +735,9 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) stdin_bytes, fdout_bytes, stdout_bytes, stderr_bytes); /* Free and clear the buffers. */ - buffer_free(&stdin_buffer); - buffer_free(&stdout_buffer); - buffer_free(&stderr_buffer); + sshbuf_free(stdin_buffer); + sshbuf_free(stdout_buffer); + sshbuf_free(stderr_buffer); /* Close the file descriptors. */ if (fdout != -1) @@ -907,9 +921,9 @@ server_input_stdin_data(int type, u_int32_t seq, struct ssh *ssh) if (fdin == -1) return 0; if ((r = sshpkt_get_string(ssh, &data, &data_len)) != 0 || - (r = sshpkt_get_end(ssh)) != 0) + (r = sshpkt_get_end(ssh)) != 0 || + (r = sshbuf_put(stdin_buffer, data, data_len)) != 0) goto out; - buffer_append(&stdin_buffer, data, data_len); r = 0; out: if (data) { diff --git a/ssh/ssh-keygen.c b/ssh/ssh-keygen.c index b3b46a3..5fb925a 100644 --- a/ssh/ssh-keygen.c +++ b/ssh/ssh-keygen.c @@ -33,7 +33,7 @@ #include "rsa.h" #include "authfile.h" #include "uuencode.h" -#include "buffer.h" +#include "sshbuf.h" #include "pathnames.h" #include "log.h" #include "misc.h" @@ -361,51 +361,61 @@ do_convert_to(struct passwd *pw) exit(0); } +/* XXX isn't this just the bignum1 encoding? */ static void -buffer_get_bignum_bits(Buffer *b, BIGNUM *value) +buffer_get_bignum_bits(struct sshbuf *b, BIGNUM *value) { - u_int bignum_bits = buffer_get_int(b); - u_int bytes = (bignum_bits + 7) / 8; + u_int bytes, bignum_bits; + int r; - if (buffer_len(b) < bytes) - fatal("buffer_get_bignum_bits: input buffer too small: " - "need %d have %d", bytes, buffer_len(b)); - if (BN_bin2bn(buffer_ptr(b), bytes, value) == NULL) - fatal("buffer_get_bignum_bits: BN_bin2bn failed"); - buffer_consume(b, bytes); + if ((r = sshbuf_get_u32(b, &bignum_bits)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + bytes = (bignum_bits + 7) / 8; + if (sshbuf_len(b) < bytes) + fatal("%s: input buffer too small: need %d have %zu", + __func__, bytes, sshbuf_len(b)); + if (BN_bin2bn(sshbuf_ptr(b), bytes, value) == NULL) + fatal("%s: BN_bin2bn failed", __func__); + if ((r = sshbuf_consume(b, bytes)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); } static struct sshkey * do_convert_private_ssh2_from_blob(u_char *blob, u_int blen) { - Buffer b; + struct sshbuf *b; struct sshkey *key = NULL; char *type, *cipher; - u_char *sig = NULL, data[] = "abcde12345"; - int r, magic, rlen, ktype, i1, i2, i3, i4; + u_char e1, e2, e3, *sig = NULL, data[] = "abcde12345"; + int r, rlen, ktype; + u_int magic, i1, i2, i3, i4; size_t slen; u_long e; - buffer_init(&b); - buffer_append(&b, blob, blen); + if ((b = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if ((r = sshbuf_put(b, blob, blen)) != 0 || + (r = sshbuf_get_u32(b, &magic)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); - magic = buffer_get_int(&b); if (magic != SSH_COM_PRIVATE_KEY_MAGIC) { - error("bad magic 0x%x != 0x%x", magic, SSH_COM_PRIVATE_KEY_MAGIC); - buffer_free(&b); + error("bad magic 0x%x != 0x%x", magic, + SSH_COM_PRIVATE_KEY_MAGIC); + sshbuf_free(b); return NULL; } - i1 = buffer_get_int(&b); - type = buffer_get_string(&b, NULL); - cipher = buffer_get_string(&b, NULL); - i2 = buffer_get_int(&b); - i3 = buffer_get_int(&b); - i4 = buffer_get_int(&b); + if ((r = sshbuf_get_u32(b, &i1)) != 0 || + (r = sshbuf_get_cstring(b, &type, NULL)) != 0 || + (r = sshbuf_get_cstring(b, &cipher, NULL)) != 0 || + (r = sshbuf_get_u32(b, &i2)) != 0 || + (r = sshbuf_get_u32(b, &i3)) != 0 || + (r = sshbuf_get_u32(b, &i4)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); debug("ignore (%d %d %d %d)", i1, i2, i3, i4); if (strcmp(cipher, "none") != 0) { error("unsupported cipher %s", cipher); xfree(cipher); - buffer_free(&b); + sshbuf_free(b); xfree(type); return NULL; } @@ -416,7 +426,7 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen) } else if (strstr(type, "rsa")) { ktype = KEY_RSA; } else { - buffer_free(&b); + sshbuf_free(b); xfree(type); return NULL; } @@ -426,42 +436,46 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen) switch (key->type) { case KEY_DSA: - buffer_get_bignum_bits(&b, key->dsa->p); - buffer_get_bignum_bits(&b, key->dsa->g); - buffer_get_bignum_bits(&b, key->dsa->q); - buffer_get_bignum_bits(&b, key->dsa->pub_key); - buffer_get_bignum_bits(&b, key->dsa->priv_key); + buffer_get_bignum_bits(b, key->dsa->p); + buffer_get_bignum_bits(b, key->dsa->g); + buffer_get_bignum_bits(b, key->dsa->q); + buffer_get_bignum_bits(b, key->dsa->pub_key); + buffer_get_bignum_bits(b, key->dsa->priv_key); break; case KEY_RSA: - e = buffer_get_char(&b); + if ((r = sshbuf_get_u8(b, &e1)) != 0 || + (e1 < 30 && (r = sshbuf_get_u8(b, &e2)) != 0) || + (e1 < 30 && (r = sshbuf_get_u8(b, &e3)) != 0)) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + e = e1; debug("e %lx", e); if (e < 30) { e <<= 8; - e += buffer_get_char(&b); + e += e2; debug("e %lx", e); e <<= 8; - e += buffer_get_char(&b); + e += e3; debug("e %lx", e); } if (!BN_set_word(key->rsa->e, e)) { - buffer_free(&b); + sshbuf_free(b); sshkey_free(key); return NULL; } - buffer_get_bignum_bits(&b, key->rsa->d); - buffer_get_bignum_bits(&b, key->rsa->n); - buffer_get_bignum_bits(&b, key->rsa->iqmp); - buffer_get_bignum_bits(&b, key->rsa->q); - buffer_get_bignum_bits(&b, key->rsa->p); + buffer_get_bignum_bits(b, key->rsa->d); + buffer_get_bignum_bits(b, key->rsa->n); + buffer_get_bignum_bits(b, key->rsa->iqmp); + buffer_get_bignum_bits(b, key->rsa->q); + buffer_get_bignum_bits(b, key->rsa->p); if ((r = rsa_generate_additional_parameters(key->rsa)) != 0) fatal("generate RSA parameters failed: %s", ssh_err(r)); break; } - rlen = buffer_len(&b); + rlen = sshbuf_len(b); if (rlen != 0) error("do_convert_private_ssh2_from_blob: " "remaining bytes in key blob %d", rlen); - buffer_free(&b); + sshbuf_free(b); /* try the key */ if (sshkey_sign(key, &sig, &slen, data, sizeof(data), 0) != 0 || @@ -1453,34 +1467,39 @@ fmt_validity(u_int64_t valid_from, u_int64_t valid_to) } static void -add_flag_option(Buffer *c, const char *name) +add_flag_option(struct sshbuf *c, const char *name) { + int r; + debug3("%s: %s", __func__, name); - buffer_put_cstring(c, name); - buffer_put_string(c, NULL, 0); + if ((r = sshbuf_put_cstring(c, name)) != 0 || + (r = sshbuf_put_string(c, NULL, 0)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); } static void -add_string_option(Buffer *c, const char *name, const char *value) +add_string_option(struct sshbuf *c, const char *name, const char *value) { - Buffer b; + struct sshbuf *b; + int r; debug3("%s: %s=%s", __func__, name, value); - buffer_init(&b); - buffer_put_cstring(&b, value); + if ((b = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if ((r = sshbuf_put_cstring(b, value)) != 0 || + (r = sshbuf_put_cstring(c, name)) != 0 || + (r = sshbuf_put_stringb(c, b)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); - buffer_put_cstring(c, name); - buffer_put_string(c, buffer_ptr(&b), buffer_len(&b)); - - buffer_free(&b); + sshbuf_free(b); } #define OPTIONS_CRITICAL 1 #define OPTIONS_EXTENSIONS 2 static void -prepare_options_buf(Buffer *c, int which) +prepare_options_buf(struct sshbuf *c, int which) { - buffer_clear(c); + sshbuf_reset(c); if ((which & OPTIONS_CRITICAL) != 0 && certflags_command != NULL) add_string_option(c, "force-command", certflags_command); @@ -1797,21 +1816,23 @@ add_cert_option(char *opt) } static void -show_options(const Buffer *optbuf, int v00, int in_critical) +show_options(const struct sshbuf *optbuf, int v00, int in_critical) { - u_char *name, *data; - const u_char *odata; - u_int dlen; - Buffer options, option; + char *name, *data; + struct sshbuf *options, *option; + int r; - buffer_init(&options); - buffer_append(&options, buffer_ptr(optbuf), buffer_len(optbuf)); + if ((options = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if ((r = sshbuf_putb(options, optbuf)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); - buffer_init(&option); - while (buffer_len(&options) != 0) { - name = buffer_get_string(&options, NULL); - odata = buffer_get_string_ptr(&options, &dlen); - buffer_append(&option, odata, dlen); + if ((option = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + while (sshbuf_len(options) != 0) { + if ((r = sshbuf_get_cstring(options, &name, NULL)) != 0 || + (r = sshbuf_get_stringb(options, option)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); printf(" %s", name); if ((v00 || !in_critical) && (strcmp(name, "permit-X11-forwarding") == 0 || @@ -1823,20 +1844,22 @@ show_options(const Buffer *optbuf, int v00, int in_critical) else if ((v00 || in_critical) && (strcmp(name, "force-command") == 0 || strcmp(name, "source-address") == 0)) { - data = buffer_get_string(&option, NULL); + if ((r = sshbuf_get_cstring(option, &data, NULL)) != 0) + fatal("%s: buffer error: %s", + __func__, ssh_err(r)); printf(" %s\n", data); xfree(data); } else { - printf(" UNKNOWN OPTION (len %u)\n", - buffer_len(&option)); - buffer_clear(&option); + printf(" UNKNOWN OPTION (len %zu)\n", + sshbuf_len(option)); + sshbuf_reset(option); } xfree(name); - if (buffer_len(&option) != 0) + if (sshbuf_len(option) != 0) fatal("Option corrupt: extra data at end"); } - buffer_free(&option); - buffer_free(&options); + sshbuf_free(option); + sshbuf_free(options); } static void @@ -1886,7 +1909,7 @@ do_show_cert(struct passwd *pw) printf("\n"); } printf(" Critical Options: "); - if (buffer_len(key->cert->critical) == 0) + if (sshbuf_len(key->cert->critical) == 0) printf("(none)\n"); else { printf("\n"); @@ -1894,7 +1917,7 @@ do_show_cert(struct passwd *pw) } if (!v00) { printf(" Extensions: "); - if (buffer_len(key->cert->extensions) == 0) + if (sshbuf_len(key->cert->extensions) == 0) printf("(none)\n"); else { printf("\n"); diff --git a/ssh/ssh-pkcs11-helper.c b/ssh/ssh-pkcs11-helper.c index 5e9045d..6689abe 100644 --- a/ssh/ssh-pkcs11-helper.c +++ b/ssh/ssh-pkcs11-helper.c @@ -26,7 +26,6 @@ #include "xmalloc.h" #include "sshbuf.h" -#include "buffer.h" #include "log.h" #include "misc.h" #include "key.h" @@ -46,13 +45,9 @@ TAILQ_HEAD(, pkcs11_keyinfo) pkcs11_keylist; #define MAX_MSG_LENGTH 10240 /*XXX*/ -/* helper */ -#define get_int() buffer_get_int(&iqueue); -#define get_string(lenp) buffer_get_string(&iqueue, lenp); - /* input and output queue */ -Buffer iqueue; -Buffer oqueue; +struct sshbuf *iqueue; +struct sshbuf *oqueue; static void add_key(struct sshkey *k, char *name) @@ -96,13 +91,12 @@ lookup_key(struct sshkey *k) } static void -send_msg(Buffer *m) +send_msg(struct sshbuf *m) { - int mlen = buffer_len(m); + int r; - buffer_put_int(&oqueue, mlen); - buffer_append(&oqueue, buffer_ptr(m), mlen); - buffer_consume(m, mlen); + if ((r = sshbuf_put_stringb(oqueue, m)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); } static void @@ -113,20 +107,24 @@ process_add(void) int r, i, nkeys; u_char *blob; size_t blen; - Buffer msg; + struct sshbuf *msg; - buffer_init(&msg); - name = get_string(NULL); - pin = get_string(NULL); + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 || + (r = sshbuf_get_cstring(iqueue, &pin, NULL)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); if ((nkeys = pkcs11_add_provider(name, pin, &keys)) > 0) { - buffer_put_char(&msg, SSH2_AGENT_IDENTITIES_ANSWER); - buffer_put_int(&msg, nkeys); + if ((r = sshbuf_put_u8(msg, + SSH2_AGENT_IDENTITIES_ANSWER)) != 0 || + (r = sshbuf_put_u32(msg, nkeys)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); for (i = 0; i < nkeys; i++) { if ((r = sshkey_to_blob(keys[i], &blob, &blen)) != 0) fatal("%s: sshkey_to_blob: %s", __func__, ssh_err(r)); - if ((r = sshbuf_put_string(&msg, blob, blen)) != 0 || - (r = sshbuf_put_cstring(&msg, name)) != 0) + if ((r = sshbuf_put_string(msg, blob, blen)) != 0 || + (r = sshbuf_put_cstring(msg, name)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); xfree(blob); @@ -134,46 +132,50 @@ process_add(void) } xfree(keys); } else { - buffer_put_char(&msg, SSH_AGENT_FAILURE); + if ((r = sshbuf_put_u8(msg, SSH_AGENT_FAILURE)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); } xfree(pin); xfree(name); - send_msg(&msg); - buffer_free(&msg); + send_msg(msg); + sshbuf_free(msg); } static void process_del(void) { char *name, *pin; - Buffer msg; + struct sshbuf *msg; + int r; - buffer_init(&msg); - name = get_string(NULL); - pin = get_string(NULL); + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 || + (r = sshbuf_get_cstring(iqueue, &pin, NULL)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); del_keys_by_name(name); - if (pkcs11_del_provider(name) == 0) - buffer_put_char(&msg, SSH_AGENT_SUCCESS); - else - buffer_put_char(&msg, SSH_AGENT_FAILURE); + if ((r = sshbuf_put_u8(msg, pkcs11_del_provider(name) == 0 ? + SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); xfree(pin); xfree(name); - send_msg(&msg); - buffer_free(&msg); + send_msg(msg); + sshbuf_free(msg); } static void process_sign(void) { u_char *blob, *data, *signature = NULL; - u_int blen, dlen, slen = 0; + size_t blen, dlen, slen = 0; int r, ok = -1, ret; struct sshkey *key, *found; - Buffer msg; + struct sshbuf *msg; - blob = get_string(&blen); - data = get_string(&dlen); - (void)get_int(); /* XXX ignore flags */ + if ((r = sshbuf_get_string(iqueue, &blob, &blen)) != 0 || + (r = sshbuf_get_string(iqueue, &data, &dlen)) != 0 || + (r = sshbuf_get_u32(iqueue, NULL)) != 0) /* ignore flags */ + fatal("%s: buffer error: %s", __func__, ssh_err(r)); if ((r = sshkey_from_blob(blob, blen, &key)) != 0) error("%s: sshkey_from_blob: %s", __func__, ssh_err(r)); @@ -189,19 +191,22 @@ process_sign(void) } sshkey_free(key); } - buffer_init(&msg); + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); if (ok == 0) { - buffer_put_char(&msg, SSH2_AGENT_SIGN_RESPONSE); - buffer_put_string(&msg, signature, slen); + if ((r = sshbuf_put_u8(msg, SSH2_AGENT_SIGN_RESPONSE)) != 0 || + (r = sshbuf_put_string(msg, signature, slen)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); } else { - buffer_put_char(&msg, SSH_AGENT_FAILURE); + if ((r = sshbuf_put_u8(msg, SSH2_AGENT_FAILURE)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); } xfree(data); xfree(blob); if (signature != NULL) xfree(signature); - send_msg(&msg); - buffer_free(&msg); + send_msg(msg); + sshbuf_free(msg); } static void @@ -210,13 +215,14 @@ process(void) u_int msg_len; u_int buf_len; u_int consumed; - u_int type; + u_char type; u_char *cp; + int r; - buf_len = buffer_len(&iqueue); + buf_len = sshbuf_len(iqueue); if (buf_len < 5) return; /* Incomplete message. */ - cp = buffer_ptr(&iqueue); + cp = sshbuf_ptr(iqueue); msg_len = get_u32(cp); if (msg_len > MAX_MSG_LENGTH) { error("bad message len %d", msg_len); @@ -224,9 +230,10 @@ process(void) } if (buf_len < msg_len + 4) return; - buffer_consume(&iqueue, 4); + if ((r = sshbuf_consume(iqueue, 4)) != 0 || + (r = sshbuf_get_u8(iqueue, &type)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); buf_len -= 4; - type = buffer_get_char(&iqueue); switch (type) { case SSH_AGENTC_ADD_SMARTCARD_KEY: debug("process_add"); @@ -245,17 +252,19 @@ process(void) break; } /* discard the remaining bytes from the current packet */ - if (buf_len < buffer_len(&iqueue)) { + if (buf_len < sshbuf_len(iqueue)) { error("iqueue grew unexpectedly"); cleanup_exit(255); } - consumed = buf_len - buffer_len(&iqueue); + consumed = buf_len - sshbuf_len(iqueue); if (msg_len < consumed) { error("msg_len %d < consumed %d", msg_len, consumed); cleanup_exit(255); } - if (msg_len > consumed) - buffer_consume(&iqueue, msg_len - consumed); + if (msg_len > consumed) { + if ((r = sshbuf_consume(iqueue, msg_len - consumed)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + } } void @@ -269,7 +278,7 @@ int main(int argc, char **argv) { fd_set *rset, *wset; - int in, out, max, log_stderr = 0; + int r, in, out, max, log_stderr = 0; ssize_t len, olen, set_size; SyslogFacility log_facility = SYSLOG_FACILITY_AUTH; LogLevel log_level = SYSLOG_LEVEL_ERROR; @@ -291,8 +300,10 @@ main(int argc, char **argv) if (out > max) max = out; - buffer_init(&iqueue); - buffer_init(&oqueue); + if ((iqueue = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if ((oqueue = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask); rset = (fd_set *)xmalloc(set_size); @@ -307,11 +318,13 @@ main(int argc, char **argv) * the worst-case length packet it can generate, * otherwise apply backpressure by stopping reads. */ - if (buffer_check_alloc(&iqueue, sizeof(buf)) && - buffer_check_alloc(&oqueue, MAX_MSG_LENGTH)) + if ((r = sshbuf_check_reserve(iqueue, sizeof(buf))) == 0 && + (r = sshbuf_check_reserve(oqueue, MAX_MSG_LENGTH)) == 0) FD_SET(in, rset); + else if (r != SSH_ERR_NO_BUFFER_SPACE) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); - olen = buffer_len(&oqueue); + olen = sshbuf_len(oqueue); if (olen > 0) FD_SET(out, wset); @@ -331,18 +344,20 @@ main(int argc, char **argv) } else if (len < 0) { error("read: %s", strerror(errno)); cleanup_exit(1); - } else { - buffer_append(&iqueue, buf, len); + } else if ((r = sshbuf_put(iqueue, buf, len)) != 0) { + fatal("%s: buffer error: %s", + __func__, ssh_err(r)); } } /* send oqueue to stdout */ if (FD_ISSET(out, wset)) { - len = write(out, buffer_ptr(&oqueue), olen); + len = write(out, sshbuf_ptr(oqueue), olen); if (len < 0) { error("write: %s", strerror(errno)); cleanup_exit(1); - } else { - buffer_consume(&oqueue, len); + } else if ((r = sshbuf_consume(oqueue, len)) != 0) { + fatal("%s: buffer error: %s", + __func__, ssh_err(r)); } } @@ -351,7 +366,9 @@ main(int argc, char **argv) * into the output buffer, otherwise stop processing input * and let the output queue drain. */ - if (buffer_check_alloc(&oqueue, MAX_MSG_LENGTH)) + if ((r = sshbuf_check_reserve(oqueue, MAX_MSG_LENGTH)) == 0) process(); + else if (r != SSH_ERR_NO_BUFFER_SPACE) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); } } diff --git a/ssh/sshd.c b/ssh/sshd.c index 14f9387..5880ce1 100644 --- a/ssh/sshd.c +++ b/ssh/sshd.c @@ -77,7 +77,7 @@ #define PACKET_SKIP_COMPAT2 #include "packet.h" #include "log.h" -#include "buffer.h" +#include "sshbuf.h" #include "servconf.h" #include "uidswap.h" #include "compat.h" @@ -228,7 +228,7 @@ int privsep_is_preauth = 1; Authctxt *the_authctxt = NULL; /* sshd_config buffer */ -Buffer cfg; +struct sshbuf *cfg; /* message to be displayed after login */ struct sshbuf *loginmsg = NULL; @@ -743,13 +743,13 @@ privsep_postauth(struct ssh *ssh) static char * list_hostkey_types(void) { - Buffer b; - const char *p; + struct sshbuf *b; char *ret; - int i; + int r, i; struct sshkey *key; - buffer_init(&b); + if ((b = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); for (i = 0; i < options.num_host_key_files; i++) { key = sensitive_data.host_keys[i]; if (key == NULL) @@ -758,10 +758,11 @@ list_hostkey_types(void) case KEY_RSA: case KEY_DSA: case KEY_ECDSA: - if (buffer_len(&b) > 0) - buffer_append(&b, ",", 1); - p = sshkey_ssh_name(key); - buffer_append(&b, p, strlen(p)); + if ((r = sshbuf_putf(b, "%s%s", + sshbuf_len(b) > 0 ? "," : "", + sshkey_ssh_name(key))) != 0) + fatal("%s: buffer error: %s", + __func__, ssh_err(r)); break; } /* If the private key has a cert peer, then list that too */ @@ -774,16 +775,18 @@ list_hostkey_types(void) case KEY_RSA_CERT: case KEY_DSA_CERT: case KEY_ECDSA_CERT: - if (buffer_len(&b) > 0) - buffer_append(&b, ",", 1); - p = sshkey_ssh_name(key); - buffer_append(&b, p, strlen(p)); + if ((r = sshbuf_putf(b, "%s%s", + sshbuf_len(b) > 0 ? "," : "", + sshkey_ssh_name(key))) != 0) + fatal("%s: buffer error: %s", + __func__, ssh_err(r)); break; } } - buffer_append(&b, "\0", 1); - ret = xstrdup(buffer_ptr(&b)); - buffer_free(&b); + if ((r = sshbuf_put_u8(b, 0)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + ret = xstrdup(sshbuf_ptr(b)); + sshbuf_free(b); debug("list_hostkey_types: %s", ret); return ret; } @@ -893,12 +896,13 @@ usage(void) } static void -send_rexec_state(int fd, Buffer *conf) +send_rexec_state(int fd, struct sshbuf *conf) { - Buffer m; + struct sshbuf *m; + int r; - debug3("%s: entering fd = %d config len %d", __func__, fd, - buffer_len(conf)); + debug3("%s: entering fd = %d config len %zu", __func__, fd, + sshbuf_len(conf)); /* * Protocol from reexec master to child: @@ -911,68 +915,90 @@ send_rexec_state(int fd, Buffer *conf) * bignum p " * bignum q " */ - buffer_init(&m); - buffer_put_cstring(&m, buffer_ptr(conf)); + if ((m = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + /* servconf.c:load_server_config() ensures a \0 at the end of cfg */ + if ((r = sshbuf_put_cstring(m, sshbuf_ptr(conf))) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (sensitive_data.server_key != NULL && sensitive_data.server_key->type == KEY_RSA1) { - buffer_put_int(&m, 1); - buffer_put_bignum(&m, sensitive_data.server_key->rsa->e); - buffer_put_bignum(&m, sensitive_data.server_key->rsa->n); - buffer_put_bignum(&m, sensitive_data.server_key->rsa->d); - buffer_put_bignum(&m, sensitive_data.server_key->rsa->iqmp); - buffer_put_bignum(&m, sensitive_data.server_key->rsa->p); - buffer_put_bignum(&m, sensitive_data.server_key->rsa->q); - } else - buffer_put_int(&m, 0); + if ((r = sshbuf_put_u32(m, 1)) != 0 || + (r = sshbuf_put_bignum1(m, + sensitive_data.server_key->rsa->e)) != 0 || + (r = sshbuf_put_bignum1(m, + sensitive_data.server_key->rsa->n)) != 0 || + (r = sshbuf_put_bignum1(m, + sensitive_data.server_key->rsa->d)) != 0 || + (r = sshbuf_put_bignum1(m, + sensitive_data.server_key->rsa->iqmp)) != 0 || + (r = sshbuf_put_bignum1(m, + sensitive_data.server_key->rsa->p)) != 0 || + (r = sshbuf_put_bignum1(m, + sensitive_data.server_key->rsa->q)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + } else if ((r = sshbuf_put_u32(m, 0)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); - if (ssh_msg_send(fd, 0, &m) == -1) + if (ssh_msg_send(fd, 0, m) == -1) fatal("%s: ssh_msg_send failed", __func__); - buffer_free(&m); + sshbuf_free(m); debug3("%s: done", __func__); } static void -recv_rexec_state(int fd, Buffer *conf) +recv_rexec_state(int fd, struct sshbuf *conf) { - Buffer m; + struct sshbuf *m; char *cp; - u_int len; + size_t len; int r; + u_char ver; + u_int key_follows; debug3("%s: entering fd = %d", __func__, fd); - buffer_init(&m); + if ((m = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); - if (ssh_msg_recv(fd, &m) == -1) + if (ssh_msg_recv(fd, m) == -1) fatal("%s: ssh_msg_recv failed", __func__); - if (buffer_get_char(&m) != 0) + if ((r = sshbuf_get_u8(m, &ver)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + if (ver != 0) fatal("%s: rexec version mismatch", __func__); - - cp = buffer_get_string(&m, &len); - if (conf != NULL) - buffer_append(conf, cp, len + 1); + if ((r = sshbuf_get_cstring(m, &cp, &len)) != 0 || + (conf != NULL && (r = sshbuf_put(conf, cp, len + 1)) != 0) || + (r = sshbuf_get_u32(m, &key_follows)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); xfree(cp); - if (buffer_get_int(&m)) { + if (key_follows) { if (sensitive_data.server_key != NULL) sshkey_free(sensitive_data.server_key); sensitive_data.server_key = sshkey_new_private(KEY_RSA1); if (sensitive_data.server_key == NULL) fatal("%s: sshkey_new_private failed", __func__); - buffer_get_bignum(&m, sensitive_data.server_key->rsa->e); - buffer_get_bignum(&m, sensitive_data.server_key->rsa->n); - buffer_get_bignum(&m, sensitive_data.server_key->rsa->d); - buffer_get_bignum(&m, sensitive_data.server_key->rsa->iqmp); - buffer_get_bignum(&m, sensitive_data.server_key->rsa->p); - buffer_get_bignum(&m, sensitive_data.server_key->rsa->q); + if ((r = sshbuf_get_bignum1(m, + sensitive_data.server_key->rsa->e)) != 0 || + (r = sshbuf_get_bignum1(m, + sensitive_data.server_key->rsa->n)) != 0 || + (r = sshbuf_get_bignum1(m, + sensitive_data.server_key->rsa->d)) != 0 || + (r = sshbuf_get_bignum1(m, + sensitive_data.server_key->rsa->iqmp)) != 0 || + (r = sshbuf_get_bignum1(m, + sensitive_data.server_key->rsa->p)) != 0 || + (r = sshbuf_get_bignum1(m, + sensitive_data.server_key->rsa->q)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); if ((r = rsa_generate_additional_parameters( sensitive_data.server_key->rsa)) != 0) fatal("generate RSA parameters failed: %s", ssh_err(r)); } - buffer_free(&m); + sshbuf_free(m); debug3("%s: done", __func__); } @@ -1218,8 +1244,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) startup_pipe = -1; pid = getpid(); if (rexec_flag) { - send_rexec_state(config_s[0], - &cfg); + send_rexec_state(config_s[0], cfg); close(config_s[0]); } break; @@ -1262,7 +1287,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) close(startup_p[1]); if (rexec_flag) { - send_rexec_state(config_s[0], &cfg); + send_rexec_state(config_s[0], cfg); close(config_s[0]); close(config_s[1]); } @@ -1482,14 +1507,15 @@ main(int ac, char **av) "test mode (-T)"); /* Fetch our configuration */ - buffer_init(&cfg); + if ((cfg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); if (rexeced_flag) - recv_rexec_state(REEXEC_CONFIG_PASS_FD, &cfg); + recv_rexec_state(REEXEC_CONFIG_PASS_FD, cfg); else - load_server_config(config_file_name, &cfg); + load_server_config(config_file_name, cfg); parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name, - &cfg, NULL); + cfg, NULL); /* Fill in default values for those options not explicitly set. */ fill_default_server_options(&options);