summaryrefslogtreecommitdiff
path: root/packet.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2018-12-27 03:25:24 +0000
committerDamien Miller <djm@mindrot.org>2018-12-27 14:38:22 +1100
commit0a843d9a0e805f14653a555f5c7a8ba99d62c12d (patch)
tree481f36e9fd1918be5449e369a97c086a1a8d2432 /packet.c
parent434b587afe41c19391821e7392005068fda76248 (diff)
upstream: move client/server SSH-* banners to buffers under
ssh->kex and factor out the banner exchange. This eliminates some common code from the client and server. Also be more strict about handling \r characters - these should only be accepted immediately before \n (pointed out by Jann Horn). Inspired by a patch from Markus Schmidt. (lots of) feedback and ok markus@ OpenBSD-Commit-ID: 1cc7885487a6754f63641d7d3279b0941890275b
Diffstat (limited to 'packet.c')
-rw-r--r--packet.c42
1 files changed, 20 insertions, 22 deletions
diff --git a/packet.c b/packet.c
index dcf35e6e6..e7e6d27a7 100644
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: packet.c,v 1.277 2018/07/16 03:09:13 djm Exp $ */ 1/* $OpenBSD: packet.c,v 1.278 2018/12/27 03:25:25 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -58,6 +58,7 @@
58#include <string.h> 58#include <string.h>
59#include <unistd.h> 59#include <unistd.h>
60#include <limits.h> 60#include <limits.h>
61#include <poll.h>
61#include <signal.h> 62#include <signal.h>
62#include <time.h> 63#include <time.h>
63 64
@@ -228,6 +229,7 @@ ssh_alloc_session_state(void)
228 229
229 if ((ssh = calloc(1, sizeof(*ssh))) == NULL || 230 if ((ssh = calloc(1, sizeof(*ssh))) == NULL ||
230 (state = calloc(1, sizeof(*state))) == NULL || 231 (state = calloc(1, sizeof(*state))) == NULL ||
232 (ssh->kex = kex_new()) == NULL ||
231 (state->input = sshbuf_new()) == NULL || 233 (state->input = sshbuf_new()) == NULL ||
232 (state->output = sshbuf_new()) == NULL || 234 (state->output = sshbuf_new()) == NULL ||
233 (state->outgoing_packet = sshbuf_new()) == NULL || 235 (state->outgoing_packet = sshbuf_new()) == NULL ||
@@ -250,6 +252,10 @@ ssh_alloc_session_state(void)
250 ssh->state = state; 252 ssh->state = state;
251 return ssh; 253 return ssh;
252 fail: 254 fail:
255 if (ssh) {
256 kex_free(ssh->kex);
257 free(ssh);
258 }
253 if (state) { 259 if (state) {
254 sshbuf_free(state->input); 260 sshbuf_free(state->input);
255 sshbuf_free(state->output); 261 sshbuf_free(state->output);
@@ -257,7 +263,6 @@ ssh_alloc_session_state(void)
257 sshbuf_free(state->outgoing_packet); 263 sshbuf_free(state->outgoing_packet);
258 free(state); 264 free(state);
259 } 265 }
260 free(ssh);
261 return NULL; 266 return NULL;
262} 267}
263 268
@@ -272,8 +277,7 @@ ssh_packet_set_input_hook(struct ssh *ssh, ssh_packet_hook_fn *hook, void *ctx)
272int 277int
273ssh_packet_is_rekeying(struct ssh *ssh) 278ssh_packet_is_rekeying(struct ssh *ssh)
274{ 279{
275 return ssh->state->rekeying || 280 return ssh->state->rekeying || ssh->kex->done == 0;
276 (ssh->kex != NULL && ssh->kex->done == 0);
277} 281}
278 282
279/* 283/*
@@ -932,7 +936,7 @@ ssh_packet_need_rekeying(struct ssh *ssh, u_int outbound_packet_len)
932 return 0; 936 return 0;
933 937
934 /* Haven't keyed yet or KEX in progress. */ 938 /* Haven't keyed yet or KEX in progress. */
935 if (ssh->kex == NULL || ssh_packet_is_rekeying(ssh)) 939 if (ssh_packet_is_rekeying(ssh))
936 return 0; 940 return 0;
937 941
938 /* Peer can't rekey */ 942 /* Peer can't rekey */
@@ -2123,6 +2127,7 @@ void
2123ssh_packet_set_server(struct ssh *ssh) 2127ssh_packet_set_server(struct ssh *ssh)
2124{ 2128{
2125 ssh->state->server_side = 1; 2129 ssh->state->server_side = 1;
2130 ssh->kex->server = 1; /* XXX unify? */
2126} 2131}
2127 2132
2128void 2133void
@@ -2175,9 +2180,9 @@ kex_to_blob(struct sshbuf *m, struct kex *kex)
2175 (r = sshbuf_put_u32(m, kex->kex_type)) != 0 || 2180 (r = sshbuf_put_u32(m, kex->kex_type)) != 0 ||
2176 (r = sshbuf_put_stringb(m, kex->my)) != 0 || 2181 (r = sshbuf_put_stringb(m, kex->my)) != 0 ||
2177 (r = sshbuf_put_stringb(m, kex->peer)) != 0 || 2182 (r = sshbuf_put_stringb(m, kex->peer)) != 0 ||
2178 (r = sshbuf_put_u32(m, kex->flags)) != 0 || 2183 (r = sshbuf_put_stringb(m, kex->client_version)) != 0 ||
2179 (r = sshbuf_put_cstring(m, kex->client_version_string)) != 0 || 2184 (r = sshbuf_put_stringb(m, kex->server_version)) != 0 ||
2180 (r = sshbuf_put_cstring(m, kex->server_version_string)) != 0) 2185 (r = sshbuf_put_u32(m, kex->flags)) != 0)
2181 return r; 2186 return r;
2182 return 0; 2187 return 0;
2183} 2188}
@@ -2327,12 +2332,8 @@ kex_from_blob(struct sshbuf *m, struct kex **kexp)
2327 struct kex *kex; 2332 struct kex *kex;
2328 int r; 2333 int r;
2329 2334
2330 if ((kex = calloc(1, sizeof(struct kex))) == NULL || 2335 if ((kex = kex_new()) == NULL)
2331 (kex->my = sshbuf_new()) == NULL || 2336 return SSH_ERR_ALLOC_FAIL;
2332 (kex->peer = sshbuf_new()) == NULL) {
2333 r = SSH_ERR_ALLOC_FAIL;
2334 goto out;
2335 }
2336 if ((r = sshbuf_get_string(m, &kex->session_id, &kex->session_id_len)) != 0 || 2337 if ((r = sshbuf_get_string(m, &kex->session_id, &kex->session_id_len)) != 0 ||
2337 (r = sshbuf_get_u32(m, &kex->we_need)) != 0 || 2338 (r = sshbuf_get_u32(m, &kex->we_need)) != 0 ||
2338 (r = sshbuf_get_cstring(m, &kex->hostkey_alg, NULL)) != 0 || 2339 (r = sshbuf_get_cstring(m, &kex->hostkey_alg, NULL)) != 0 ||
@@ -2341,23 +2342,20 @@ kex_from_blob(struct sshbuf *m, struct kex **kexp)
2341 (r = sshbuf_get_u32(m, &kex->kex_type)) != 0 || 2342 (r = sshbuf_get_u32(m, &kex->kex_type)) != 0 ||
2342 (r = sshbuf_get_stringb(m, kex->my)) != 0 || 2343 (r = sshbuf_get_stringb(m, kex->my)) != 0 ||
2343 (r = sshbuf_get_stringb(m, kex->peer)) != 0 || 2344 (r = sshbuf_get_stringb(m, kex->peer)) != 0 ||
2344 (r = sshbuf_get_u32(m, &kex->flags)) != 0 || 2345 (r = sshbuf_get_stringb(m, kex->client_version)) != 0 ||
2345 (r = sshbuf_get_cstring(m, &kex->client_version_string, NULL)) != 0 || 2346 (r = sshbuf_get_stringb(m, kex->server_version)) != 0 ||
2346 (r = sshbuf_get_cstring(m, &kex->server_version_string, NULL)) != 0) 2347 (r = sshbuf_get_u32(m, &kex->flags)) != 0)
2347 goto out; 2348 goto out;
2348 kex->server = 1; 2349 kex->server = 1;
2349 kex->done = 1; 2350 kex->done = 1;
2350 r = 0; 2351 r = 0;
2351 out: 2352 out:
2352 if (r != 0 || kexp == NULL) { 2353 if (r != 0 || kexp == NULL) {
2353 if (kex != NULL) { 2354 kex_free(kex);
2354 sshbuf_free(kex->my);
2355 sshbuf_free(kex->peer);
2356 free(kex);
2357 }
2358 if (kexp != NULL) 2355 if (kexp != NULL)
2359 *kexp = NULL; 2356 *kexp = NULL;
2360 } else { 2357 } else {
2358 kex_free(*kexp);
2361 *kexp = kex; 2359 *kexp = kex;
2362 } 2360 }
2363 return r; 2361 return r;