aboutsummaryrefslogtreecommitdiff
path: root/packet.c
diff options
context:
space:
mode:
Diffstat (limited to 'packet.c')
-rw-r--r--packet.c94
1 files changed, 58 insertions, 36 deletions
diff --git a/packet.c b/packet.c
index dcf35e6e626a..36e352b4466d 100644
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.c,v 1.277 2018/07/16 03:09:13 djm Exp $ */
+/* $OpenBSD: packet.c,v 1.283 2019/03/01 03:29:32 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -58,6 +58,7 @@
#include <string.h>
#include <unistd.h>
#include <limits.h>
+#include <poll.h>
#include <signal.h>
#include <time.h>
@@ -228,6 +229,7 @@ ssh_alloc_session_state(void)
if ((ssh = calloc(1, sizeof(*ssh))) == NULL ||
(state = calloc(1, sizeof(*state))) == NULL ||
+ (ssh->kex = kex_new()) == NULL ||
(state->input = sshbuf_new()) == NULL ||
(state->output = sshbuf_new()) == NULL ||
(state->outgoing_packet = sshbuf_new()) == NULL ||
@@ -250,6 +252,10 @@ ssh_alloc_session_state(void)
ssh->state = state;
return ssh;
fail:
+ if (ssh) {
+ kex_free(ssh->kex);
+ free(ssh);
+ }
if (state) {
sshbuf_free(state->input);
sshbuf_free(state->output);
@@ -257,7 +263,6 @@ ssh_alloc_session_state(void)
sshbuf_free(state->outgoing_packet);
free(state);
}
- free(ssh);
return NULL;
}
@@ -272,8 +277,7 @@ ssh_packet_set_input_hook(struct ssh *ssh, ssh_packet_hook_fn *hook, void *ctx)
int
ssh_packet_is_rekeying(struct ssh *ssh)
{
- return ssh->state->rekeying ||
- (ssh->kex != NULL && ssh->kex->done == 0);
+ return ssh->state->rekeying || ssh->kex->done == 0;
}
/*
@@ -837,6 +841,7 @@ ssh_set_newkeys(struct ssh *ssh, int mode)
u_int64_t *max_blocks;
const char *wmsg;
int r, crypt_type;
+ const char *dir = mode == MODE_OUT ? "out" : "in";
debug2("set_newkeys: mode %d", mode);
@@ -852,14 +857,12 @@ ssh_set_newkeys(struct ssh *ssh, int mode)
max_blocks = &state->max_blocks_in;
}
if (state->newkeys[mode] != NULL) {
- debug("set_newkeys: rekeying, input %llu bytes %llu blocks, "
- "output %llu bytes %llu blocks",
+ debug("%s: rekeying %s, input %llu bytes %llu blocks, "
+ "output %llu bytes %llu blocks", __func__, dir,
(unsigned long long)state->p_read.bytes,
(unsigned long long)state->p_read.blocks,
(unsigned long long)state->p_send.bytes,
(unsigned long long)state->p_send.blocks);
- cipher_free(*ccp);
- *ccp = NULL;
kex_free_newkeys(state->newkeys[mode]);
state->newkeys[mode] = NULL;
}
@@ -877,7 +880,9 @@ ssh_set_newkeys(struct ssh *ssh, int mode)
return r;
}
mac->enabled = 1;
- DBG(debug("cipher_init_context: %d", mode));
+ DBG(debug("%s: cipher_init_context: %s", __func__, dir));
+ cipher_free(*ccp);
+ *ccp = NULL;
if ((r = cipher_init(ccp, enc->cipher, enc->key, enc->key_len,
enc->iv, enc->iv_len, crypt_type)) != 0)
return r;
@@ -916,7 +921,8 @@ ssh_set_newkeys(struct ssh *ssh, int mode)
if (state->rekey_limit)
*max_blocks = MINIMUM(*max_blocks,
state->rekey_limit / enc->block_size);
- debug("rekey after %llu blocks", (unsigned long long)*max_blocks);
+ debug("rekey %s after %llu blocks", dir,
+ (unsigned long long)*max_blocks);
return 0;
}
@@ -932,7 +938,7 @@ ssh_packet_need_rekeying(struct ssh *ssh, u_int outbound_packet_len)
return 0;
/* Haven't keyed yet or KEX in progress. */
- if (ssh->kex == NULL || ssh_packet_is_rekeying(ssh))
+ if (ssh_packet_is_rekeying(ssh))
return 0;
/* Peer can't rekey */
@@ -1805,10 +1811,10 @@ sshpkt_fmt_connection_id(struct ssh *ssh, char *s, size_t l)
/*
* Pretty-print connection-terminating errors and exit.
*/
-void
-sshpkt_fatal(struct ssh *ssh, const char *tag, int r)
+static void
+sshpkt_vfatal(struct ssh *ssh, int r, const char *fmt, va_list ap)
{
- char remote_id[512];
+ char *tag = NULL, remote_id[512];
sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id));
@@ -1842,6 +1848,11 @@ sshpkt_fatal(struct ssh *ssh, const char *tag, int r)
}
/* FALLTHROUGH */
default:
+ if (vasprintf(&tag, fmt, ap) == -1) {
+ ssh_packet_clear_keys(ssh);
+ logdie("%s: could not allocate failure message",
+ __func__);
+ }
ssh_packet_clear_keys(ssh);
logdie("%s%sConnection %s %s: %s",
tag != NULL ? tag : "", tag != NULL ? ": " : "",
@@ -1850,6 +1861,18 @@ sshpkt_fatal(struct ssh *ssh, const char *tag, int r)
}
}
+void
+sshpkt_fatal(struct ssh *ssh, int r, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ sshpkt_vfatal(ssh, r, fmt, ap);
+ /* NOTREACHED */
+ va_end(ap);
+ logdie("%s: should have exited", __func__);
+}
+
/*
* Logs the error plus constructs and sends a disconnect packet, closes the
* connection, and exits. This function never returns. The error message
@@ -1885,10 +1908,10 @@ ssh_packet_disconnect(struct ssh *ssh, const char *fmt,...)
* for it to get sent.
*/
if ((r = sshpkt_disconnect(ssh, "%s", buf)) != 0)
- sshpkt_fatal(ssh, __func__, r);
+ sshpkt_fatal(ssh, r, "%s", __func__);
if ((r = ssh_packet_write_wait(ssh)) != 0)
- sshpkt_fatal(ssh, __func__, r);
+ sshpkt_fatal(ssh, r, "%s", __func__);
/* Close the connection. */
ssh_packet_close(ssh);
@@ -2123,6 +2146,7 @@ void
ssh_packet_set_server(struct ssh *ssh)
{
ssh->state->server_side = 1;
+ ssh->kex->server = 1; /* XXX unify? */
}
void
@@ -2175,9 +2199,9 @@ kex_to_blob(struct sshbuf *m, struct kex *kex)
(r = sshbuf_put_u32(m, kex->kex_type)) != 0 ||
(r = sshbuf_put_stringb(m, kex->my)) != 0 ||
(r = sshbuf_put_stringb(m, kex->peer)) != 0 ||
- (r = sshbuf_put_u32(m, kex->flags)) != 0 ||
- (r = sshbuf_put_cstring(m, kex->client_version_string)) != 0 ||
- (r = sshbuf_put_cstring(m, kex->server_version_string)) != 0)
+ (r = sshbuf_put_stringb(m, kex->client_version)) != 0 ||
+ (r = sshbuf_put_stringb(m, kex->server_version)) != 0 ||
+ (r = sshbuf_put_u32(m, kex->flags)) != 0)
return r;
return 0;
}
@@ -2327,12 +2351,8 @@ kex_from_blob(struct sshbuf *m, struct kex **kexp)
struct kex *kex;
int r;
- if ((kex = calloc(1, sizeof(struct kex))) == NULL ||
- (kex->my = sshbuf_new()) == NULL ||
- (kex->peer = sshbuf_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
+ if ((kex = kex_new()) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
if ((r = sshbuf_get_string(m, &kex->session_id, &kex->session_id_len)) != 0 ||
(r = sshbuf_get_u32(m, &kex->we_need)) != 0 ||
(r = sshbuf_get_cstring(m, &kex->hostkey_alg, NULL)) != 0 ||
@@ -2341,23 +2361,20 @@ kex_from_blob(struct sshbuf *m, struct kex **kexp)
(r = sshbuf_get_u32(m, &kex->kex_type)) != 0 ||
(r = sshbuf_get_stringb(m, kex->my)) != 0 ||
(r = sshbuf_get_stringb(m, kex->peer)) != 0 ||
- (r = sshbuf_get_u32(m, &kex->flags)) != 0 ||
- (r = sshbuf_get_cstring(m, &kex->client_version_string, NULL)) != 0 ||
- (r = sshbuf_get_cstring(m, &kex->server_version_string, NULL)) != 0)
+ (r = sshbuf_get_stringb(m, kex->client_version)) != 0 ||
+ (r = sshbuf_get_stringb(m, kex->server_version)) != 0 ||
+ (r = sshbuf_get_u32(m, &kex->flags)) != 0)
goto out;
kex->server = 1;
kex->done = 1;
r = 0;
out:
if (r != 0 || kexp == NULL) {
- if (kex != NULL) {
- sshbuf_free(kex->my);
- sshbuf_free(kex->peer);
- free(kex);
- }
+ kex_free(kex);
if (kexp != NULL)
*kexp = NULL;
} else {
+ kex_free(*kexp);
*kexp = kex;
}
return r;
@@ -2468,6 +2485,12 @@ sshpkt_put_stringb(struct ssh *ssh, const struct sshbuf *v)
return sshbuf_put_stringb(ssh->state->outgoing_packet, v);
}
+int
+sshpkt_getb_froms(struct ssh *ssh, struct sshbuf **valp)
+{
+ return sshbuf_froms(ssh->state->incoming_packet, valp);
+}
+
#ifdef WITH_OPENSSL
#ifdef OPENSSL_HAS_ECC
int
@@ -2544,11 +2567,10 @@ sshpkt_get_ec(struct ssh *ssh, EC_POINT *v, const EC_GROUP *g)
}
#endif /* OPENSSL_HAS_ECC */
-
int
-sshpkt_get_bignum2(struct ssh *ssh, BIGNUM *v)
+sshpkt_get_bignum2(struct ssh *ssh, BIGNUM **valp)
{
- return sshbuf_get_bignum2(ssh->state->incoming_packet, v);
+ return sshbuf_get_bignum2(ssh->state->incoming_packet, valp);
}
#endif /* WITH_OPENSSL */