diff options
author | djm@openbsd.org <djm@openbsd.org> | 2018-12-27 03:25:24 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2018-12-27 14:38:22 +1100 |
commit | 0a843d9a0e805f14653a555f5c7a8ba99d62c12d (patch) | |
tree | 481f36e9fd1918be5449e369a97c086a1a8d2432 /packet.c | |
parent | 434b587afe41c19391821e7392005068fda76248 (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.c | 42 |
1 files changed, 20 insertions, 22 deletions
@@ -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) | |||
272 | int | 277 | int |
273 | ssh_packet_is_rekeying(struct ssh *ssh) | 278 | ssh_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 | |||
2123 | ssh_packet_set_server(struct ssh *ssh) | 2127 | ssh_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 | ||
2128 | void | 2133 | void |
@@ -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; |