diff options
author | Colin Watson <cjwatson@debian.org> | 2015-08-19 14:23:51 +0100 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2015-08-19 16:48:11 +0100 |
commit | 0f0841b2d28b7463267d4d91577e72e3340a1d3a (patch) | |
tree | ba55fcd2b6e2cc22b30f5afb561dbb3da4c8b6c7 /packet.c | |
parent | f2a5f5dae656759efb0b76c3d94890b65c197a02 (diff) | |
parent | 8698446b972003b63dfe5dcbdb86acfe986afb85 (diff) |
New upstream release (6.8p1).
Diffstat (limited to 'packet.c')
-rw-r--r-- | packet.c | 2857 |
1 files changed, 1832 insertions, 1025 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: packet.c,v 1.198 2014/07/15 15:54:14 millert Exp $ */ | 1 | /* $OpenBSD: packet.c,v 1.208 2015/02/13 18:57:00 markus 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 |
@@ -39,9 +39,9 @@ | |||
39 | 39 | ||
40 | #include "includes.h" | 40 | #include "includes.h" |
41 | 41 | ||
42 | #include <sys/param.h> /* MIN roundup */ | ||
42 | #include <sys/types.h> | 43 | #include <sys/types.h> |
43 | #include "openbsd-compat/sys-queue.h" | 44 | #include "openbsd-compat/sys-queue.h" |
44 | #include <sys/param.h> | ||
45 | #include <sys/socket.h> | 45 | #include <sys/socket.h> |
46 | #ifdef HAVE_SYS_TIME_H | 46 | #ifdef HAVE_SYS_TIME_H |
47 | # include <sys/time.h> | 47 | # include <sys/time.h> |
@@ -57,29 +57,35 @@ | |||
57 | #include <stdlib.h> | 57 | #include <stdlib.h> |
58 | #include <string.h> | 58 | #include <string.h> |
59 | #include <unistd.h> | 59 | #include <unistd.h> |
60 | #include <limits.h> | ||
60 | #include <signal.h> | 61 | #include <signal.h> |
61 | #include <time.h> | 62 | #include <time.h> |
62 | 63 | ||
64 | #include <zlib.h> | ||
65 | |||
66 | #include "buffer.h" /* typedefs XXX */ | ||
67 | #include "key.h" /* typedefs XXX */ | ||
68 | |||
63 | #include "xmalloc.h" | 69 | #include "xmalloc.h" |
64 | #include "buffer.h" | ||
65 | #include "packet.h" | ||
66 | #include "crc32.h" | 70 | #include "crc32.h" |
67 | #include "compress.h" | ||
68 | #include "deattack.h" | 71 | #include "deattack.h" |
69 | #include "compat.h" | 72 | #include "compat.h" |
70 | #include "ssh1.h" | 73 | #include "ssh1.h" |
71 | #include "ssh2.h" | 74 | #include "ssh2.h" |
72 | #include "cipher.h" | 75 | #include "cipher.h" |
73 | #include "key.h" | 76 | #include "sshkey.h" |
74 | #include "kex.h" | 77 | #include "kex.h" |
78 | #include "digest.h" | ||
75 | #include "mac.h" | 79 | #include "mac.h" |
76 | #include "log.h" | 80 | #include "log.h" |
77 | #include "canohost.h" | 81 | #include "canohost.h" |
78 | #include "misc.h" | 82 | #include "misc.h" |
79 | #include "channels.h" | 83 | #include "channels.h" |
80 | #include "ssh.h" | 84 | #include "ssh.h" |
81 | #include "ssherr.h" | 85 | #include "packet.h" |
82 | #include "roaming.h" | 86 | #include "roaming.h" |
87 | #include "ssherr.h" | ||
88 | #include "sshbuf.h" | ||
83 | 89 | ||
84 | #ifdef PACKET_DEBUG | 90 | #ifdef PACKET_DEBUG |
85 | #define DBG(x) x | 91 | #define DBG(x) x |
@@ -99,7 +105,7 @@ struct packet_state { | |||
99 | struct packet { | 105 | struct packet { |
100 | TAILQ_ENTRY(packet) next; | 106 | TAILQ_ENTRY(packet) next; |
101 | u_char type; | 107 | u_char type; |
102 | Buffer payload; | 108 | struct sshbuf *payload; |
103 | }; | 109 | }; |
104 | 110 | ||
105 | struct session_state { | 111 | struct session_state { |
@@ -116,26 +122,33 @@ struct session_state { | |||
116 | u_int remote_protocol_flags; | 122 | u_int remote_protocol_flags; |
117 | 123 | ||
118 | /* Encryption context for receiving data. Only used for decryption. */ | 124 | /* Encryption context for receiving data. Only used for decryption. */ |
119 | CipherContext receive_context; | 125 | struct sshcipher_ctx receive_context; |
120 | 126 | ||
121 | /* Encryption context for sending data. Only used for encryption. */ | 127 | /* Encryption context for sending data. Only used for encryption. */ |
122 | CipherContext send_context; | 128 | struct sshcipher_ctx send_context; |
123 | 129 | ||
124 | /* Buffer for raw input data from the socket. */ | 130 | /* Buffer for raw input data from the socket. */ |
125 | Buffer input; | 131 | struct sshbuf *input; |
126 | 132 | ||
127 | /* Buffer for raw output data going to the socket. */ | 133 | /* Buffer for raw output data going to the socket. */ |
128 | Buffer output; | 134 | struct sshbuf *output; |
129 | 135 | ||
130 | /* Buffer for the partial outgoing packet being constructed. */ | 136 | /* Buffer for the partial outgoing packet being constructed. */ |
131 | Buffer outgoing_packet; | 137 | struct sshbuf *outgoing_packet; |
132 | 138 | ||
133 | /* Buffer for the incoming packet currently being processed. */ | 139 | /* Buffer for the incoming packet currently being processed. */ |
134 | Buffer incoming_packet; | 140 | struct sshbuf *incoming_packet; |
135 | 141 | ||
136 | /* Scratch buffer for packet compression/decompression. */ | 142 | /* Scratch buffer for packet compression/decompression. */ |
137 | Buffer compression_buffer; | 143 | struct sshbuf *compression_buffer; |
138 | int compression_buffer_ready; | 144 | |
145 | /* Incoming/outgoing compression dictionaries */ | ||
146 | z_stream compression_in_stream; | ||
147 | z_stream compression_out_stream; | ||
148 | int compression_in_started; | ||
149 | int compression_out_started; | ||
150 | int compression_in_failures; | ||
151 | int compression_out_failures; | ||
139 | 152 | ||
140 | /* | 153 | /* |
141 | * Flag indicating whether packet compression/decompression is | 154 | * Flag indicating whether packet compression/decompression is |
@@ -164,7 +177,7 @@ struct session_state { | |||
164 | int packet_timeout_ms; | 177 | int packet_timeout_ms; |
165 | 178 | ||
166 | /* Session key information for Encryption and MAC */ | 179 | /* Session key information for Encryption and MAC */ |
167 | Newkeys *newkeys[MODE_MAX]; | 180 | struct newkeys *newkeys[MODE_MAX]; |
168 | struct packet_state p_read, p_send; | 181 | struct packet_state p_read, p_send; |
169 | 182 | ||
170 | /* Volume-based rekeying */ | 183 | /* Volume-based rekeying */ |
@@ -172,7 +185,7 @@ struct session_state { | |||
172 | u_int32_t rekey_limit; | 185 | u_int32_t rekey_limit; |
173 | 186 | ||
174 | /* Time-based rekeying */ | 187 | /* Time-based rekeying */ |
175 | time_t rekey_interval; /* how often in seconds */ | 188 | u_int32_t rekey_interval; /* how often in seconds */ |
176 | time_t rekey_time; /* time of last rekeying */ | 189 | time_t rekey_time; /* time of last rekeying */ |
177 | 190 | ||
178 | /* Session key for protocol v1 */ | 191 | /* Session key for protocol v1 */ |
@@ -184,7 +197,7 @@ struct session_state { | |||
184 | 197 | ||
185 | /* XXX discard incoming data after MAC error */ | 198 | /* XXX discard incoming data after MAC error */ |
186 | u_int packet_discard; | 199 | u_int packet_discard; |
187 | Mac *packet_discard_mac; | 200 | struct sshmac *packet_discard_mac; |
188 | 201 | ||
189 | /* Used in packet_read_poll2() */ | 202 | /* Used in packet_read_poll2() */ |
190 | u_int packlen; | 203 | u_int packlen; |
@@ -198,121 +211,177 @@ struct session_state { | |||
198 | /* Used in packet_set_maxsize */ | 211 | /* Used in packet_set_maxsize */ |
199 | int set_maxsize_called; | 212 | int set_maxsize_called; |
200 | 213 | ||
201 | TAILQ_HEAD(, packet) outgoing; | 214 | /* One-off warning about weak ciphers */ |
202 | }; | 215 | int cipher_warning_done; |
203 | 216 | ||
204 | static struct session_state *active_state, *backup_state; | 217 | /* SSH1 CRC compensation attack detector */ |
218 | struct deattack_ctx deattack; | ||
205 | 219 | ||
206 | static struct session_state * | 220 | TAILQ_HEAD(, packet) outgoing; |
207 | alloc_session_state(void) | 221 | }; |
208 | { | ||
209 | struct session_state *s = xcalloc(1, sizeof(*s)); | ||
210 | 222 | ||
211 | s->connection_in = -1; | 223 | struct ssh * |
212 | s->connection_out = -1; | 224 | ssh_alloc_session_state(void) |
213 | s->max_packet_size = 32768; | 225 | { |
214 | s->packet_timeout_ms = -1; | 226 | struct ssh *ssh = NULL; |
215 | return s; | 227 | struct session_state *state = NULL; |
228 | |||
229 | if ((ssh = calloc(1, sizeof(*ssh))) == NULL || | ||
230 | (state = calloc(1, sizeof(*state))) == NULL || | ||
231 | (state->input = sshbuf_new()) == NULL || | ||
232 | (state->output = sshbuf_new()) == NULL || | ||
233 | (state->outgoing_packet = sshbuf_new()) == NULL || | ||
234 | (state->incoming_packet = sshbuf_new()) == NULL) | ||
235 | goto fail; | ||
236 | TAILQ_INIT(&state->outgoing); | ||
237 | TAILQ_INIT(&ssh->private_keys); | ||
238 | TAILQ_INIT(&ssh->public_keys); | ||
239 | state->connection_in = -1; | ||
240 | state->connection_out = -1; | ||
241 | state->max_packet_size = 32768; | ||
242 | state->packet_timeout_ms = -1; | ||
243 | state->p_send.packets = state->p_read.packets = 0; | ||
244 | state->initialized = 1; | ||
245 | /* | ||
246 | * ssh_packet_send2() needs to queue packets until | ||
247 | * we've done the initial key exchange. | ||
248 | */ | ||
249 | state->rekeying = 1; | ||
250 | ssh->state = state; | ||
251 | return ssh; | ||
252 | fail: | ||
253 | if (state) { | ||
254 | sshbuf_free(state->input); | ||
255 | sshbuf_free(state->output); | ||
256 | sshbuf_free(state->incoming_packet); | ||
257 | sshbuf_free(state->outgoing_packet); | ||
258 | free(state); | ||
259 | } | ||
260 | free(ssh); | ||
261 | return NULL; | ||
216 | } | 262 | } |
217 | 263 | ||
218 | /* | 264 | /* |
219 | * Sets the descriptors used for communication. Disables encryption until | 265 | * Sets the descriptors used for communication. Disables encryption until |
220 | * packet_set_encryption_key is called. | 266 | * packet_set_encryption_key is called. |
221 | */ | 267 | */ |
222 | void | 268 | struct ssh * |
223 | packet_set_connection(int fd_in, int fd_out) | 269 | ssh_packet_set_connection(struct ssh *ssh, int fd_in, int fd_out) |
224 | { | 270 | { |
225 | const Cipher *none = cipher_by_name("none"); | 271 | struct session_state *state; |
272 | const struct sshcipher *none = cipher_by_name("none"); | ||
226 | int r; | 273 | int r; |
227 | 274 | ||
228 | if (none == NULL) | 275 | if (none == NULL) { |
229 | fatal("packet_set_connection: cannot load cipher 'none'"); | 276 | error("%s: cannot load cipher 'none'", __func__); |
230 | if (active_state == NULL) | 277 | return NULL; |
231 | active_state = alloc_session_state(); | 278 | } |
232 | active_state->connection_in = fd_in; | 279 | if (ssh == NULL) |
233 | active_state->connection_out = fd_out; | 280 | ssh = ssh_alloc_session_state(); |
234 | if ((r = cipher_init(&active_state->send_context, none, | 281 | if (ssh == NULL) { |
282 | error("%s: cound not allocate state", __func__); | ||
283 | return NULL; | ||
284 | } | ||
285 | state = ssh->state; | ||
286 | state->connection_in = fd_in; | ||
287 | state->connection_out = fd_out; | ||
288 | if ((r = cipher_init(&state->send_context, none, | ||
235 | (const u_char *)"", 0, NULL, 0, CIPHER_ENCRYPT)) != 0 || | 289 | (const u_char *)"", 0, NULL, 0, CIPHER_ENCRYPT)) != 0 || |
236 | (r = cipher_init(&active_state->receive_context, none, | 290 | (r = cipher_init(&state->receive_context, none, |
237 | (const u_char *)"", 0, NULL, 0, CIPHER_DECRYPT)) != 0) | 291 | (const u_char *)"", 0, NULL, 0, CIPHER_DECRYPT)) != 0) { |
238 | fatal("%s: cipher_init: %s", __func__, ssh_err(r)); | 292 | error("%s: cipher_init failed: %s", __func__, ssh_err(r)); |
239 | active_state->newkeys[MODE_IN] = active_state->newkeys[MODE_OUT] = NULL; | 293 | return NULL; |
240 | if (!active_state->initialized) { | ||
241 | active_state->initialized = 1; | ||
242 | buffer_init(&active_state->input); | ||
243 | buffer_init(&active_state->output); | ||
244 | buffer_init(&active_state->outgoing_packet); | ||
245 | buffer_init(&active_state->incoming_packet); | ||
246 | TAILQ_INIT(&active_state->outgoing); | ||
247 | active_state->p_send.packets = active_state->p_read.packets = 0; | ||
248 | } | 294 | } |
295 | state->newkeys[MODE_IN] = state->newkeys[MODE_OUT] = NULL; | ||
296 | deattack_init(&state->deattack); | ||
297 | /* | ||
298 | * Cache the IP address of the remote connection for use in error | ||
299 | * messages that might be generated after the connection has closed. | ||
300 | */ | ||
301 | (void)ssh_remote_ipaddr(ssh); | ||
302 | return ssh; | ||
249 | } | 303 | } |
250 | 304 | ||
251 | void | 305 | void |
252 | packet_set_timeout(int timeout, int count) | 306 | ssh_packet_set_timeout(struct ssh *ssh, int timeout, int count) |
253 | { | 307 | { |
308 | struct session_state *state = ssh->state; | ||
309 | |||
254 | if (timeout <= 0 || count <= 0) { | 310 | if (timeout <= 0 || count <= 0) { |
255 | active_state->packet_timeout_ms = -1; | 311 | state->packet_timeout_ms = -1; |
256 | return; | 312 | return; |
257 | } | 313 | } |
258 | if ((INT_MAX / 1000) / count < timeout) | 314 | if ((INT_MAX / 1000) / count < timeout) |
259 | active_state->packet_timeout_ms = INT_MAX; | 315 | state->packet_timeout_ms = INT_MAX; |
260 | else | 316 | else |
261 | active_state->packet_timeout_ms = timeout * count * 1000; | 317 | state->packet_timeout_ms = timeout * count * 1000; |
262 | } | 318 | } |
263 | 319 | ||
264 | static void | 320 | int |
265 | packet_stop_discard(void) | 321 | ssh_packet_stop_discard(struct ssh *ssh) |
266 | { | 322 | { |
267 | if (active_state->packet_discard_mac) { | 323 | struct session_state *state = ssh->state; |
324 | int r; | ||
325 | |||
326 | if (state->packet_discard_mac) { | ||
268 | char buf[1024]; | 327 | char buf[1024]; |
269 | 328 | ||
270 | memset(buf, 'a', sizeof(buf)); | 329 | memset(buf, 'a', sizeof(buf)); |
271 | while (buffer_len(&active_state->incoming_packet) < | 330 | while (sshbuf_len(state->incoming_packet) < |
272 | PACKET_MAX_SIZE) | 331 | PACKET_MAX_SIZE) |
273 | buffer_append(&active_state->incoming_packet, buf, | 332 | if ((r = sshbuf_put(state->incoming_packet, buf, |
274 | sizeof(buf)); | 333 | sizeof(buf))) != 0) |
275 | (void) mac_compute(active_state->packet_discard_mac, | 334 | return r; |
276 | active_state->p_read.seqnr, | 335 | (void) mac_compute(state->packet_discard_mac, |
277 | buffer_ptr(&active_state->incoming_packet), | 336 | state->p_read.seqnr, |
278 | PACKET_MAX_SIZE); | 337 | sshbuf_ptr(state->incoming_packet), PACKET_MAX_SIZE, |
279 | } | 338 | NULL, 0); |
280 | logit("Finished discarding for %.200s", get_remote_ipaddr()); | 339 | } |
281 | cleanup_exit(255); | 340 | logit("Finished discarding for %.200s", ssh_remote_ipaddr(ssh)); |
341 | return SSH_ERR_MAC_INVALID; | ||
282 | } | 342 | } |
283 | 343 | ||
284 | static void | 344 | static int |
285 | packet_start_discard(Enc *enc, Mac *mac, u_int packet_length, u_int discard) | 345 | ssh_packet_start_discard(struct ssh *ssh, struct sshenc *enc, |
346 | struct sshmac *mac, u_int packet_length, u_int discard) | ||
286 | { | 347 | { |
287 | if (enc == NULL || !cipher_is_cbc(enc->cipher) || (mac && mac->etm)) | 348 | struct session_state *state = ssh->state; |
288 | packet_disconnect("Packet corrupt"); | 349 | int r; |
350 | |||
351 | if (enc == NULL || !cipher_is_cbc(enc->cipher) || (mac && mac->etm)) { | ||
352 | if ((r = sshpkt_disconnect(ssh, "Packet corrupt")) != 0) | ||
353 | return r; | ||
354 | return SSH_ERR_MAC_INVALID; | ||
355 | } | ||
289 | if (packet_length != PACKET_MAX_SIZE && mac && mac->enabled) | 356 | if (packet_length != PACKET_MAX_SIZE && mac && mac->enabled) |
290 | active_state->packet_discard_mac = mac; | 357 | state->packet_discard_mac = mac; |
291 | if (buffer_len(&active_state->input) >= discard) | 358 | if (sshbuf_len(state->input) >= discard && |
292 | packet_stop_discard(); | 359 | (r = ssh_packet_stop_discard(ssh)) != 0) |
293 | active_state->packet_discard = discard - | 360 | return r; |
294 | buffer_len(&active_state->input); | 361 | state->packet_discard = discard - sshbuf_len(state->input); |
362 | return 0; | ||
295 | } | 363 | } |
296 | 364 | ||
297 | /* Returns 1 if remote host is connected via socket, 0 if not. */ | 365 | /* Returns 1 if remote host is connected via socket, 0 if not. */ |
298 | 366 | ||
299 | int | 367 | int |
300 | packet_connection_is_on_socket(void) | 368 | ssh_packet_connection_is_on_socket(struct ssh *ssh) |
301 | { | 369 | { |
370 | struct session_state *state = ssh->state; | ||
302 | struct sockaddr_storage from, to; | 371 | struct sockaddr_storage from, to; |
303 | socklen_t fromlen, tolen; | 372 | socklen_t fromlen, tolen; |
304 | 373 | ||
305 | /* filedescriptors in and out are the same, so it's a socket */ | 374 | /* filedescriptors in and out are the same, so it's a socket */ |
306 | if (active_state->connection_in == active_state->connection_out) | 375 | if (state->connection_in == state->connection_out) |
307 | return 1; | 376 | return 1; |
308 | fromlen = sizeof(from); | 377 | fromlen = sizeof(from); |
309 | memset(&from, 0, sizeof(from)); | 378 | memset(&from, 0, sizeof(from)); |
310 | if (getpeername(active_state->connection_in, (struct sockaddr *)&from, | 379 | if (getpeername(state->connection_in, (struct sockaddr *)&from, |
311 | &fromlen) < 0) | 380 | &fromlen) < 0) |
312 | return 0; | 381 | return 0; |
313 | tolen = sizeof(to); | 382 | tolen = sizeof(to); |
314 | memset(&to, 0, sizeof(to)); | 383 | memset(&to, 0, sizeof(to)); |
315 | if (getpeername(active_state->connection_out, (struct sockaddr *)&to, | 384 | if (getpeername(state->connection_out, (struct sockaddr *)&to, |
316 | &tolen) < 0) | 385 | &tolen) < 0) |
317 | return 0; | 386 | return 0; |
318 | if (fromlen != tolen || memcmp(&from, &to, fromlen) != 0) | 387 | if (fromlen != tolen || memcmp(&from, &to, fromlen) != 0) |
@@ -322,127 +391,23 @@ packet_connection_is_on_socket(void) | |||
322 | return 1; | 391 | return 1; |
323 | } | 392 | } |
324 | 393 | ||
325 | /* | ||
326 | * Exports an IV from the CipherContext required to export the key | ||
327 | * state back from the unprivileged child to the privileged parent | ||
328 | * process. | ||
329 | */ | ||
330 | |||
331 | void | ||
332 | packet_get_keyiv(int mode, u_char *iv, u_int len) | ||
333 | { | ||
334 | CipherContext *cc; | ||
335 | int r; | ||
336 | |||
337 | if (mode == MODE_OUT) | ||
338 | cc = &active_state->send_context; | ||
339 | else | ||
340 | cc = &active_state->receive_context; | ||
341 | |||
342 | if ((r = cipher_get_keyiv(cc, iv, len)) != 0) | ||
343 | fatal("%s: cipher_get_keyiv: %s", __func__, ssh_err(r)); | ||
344 | } | ||
345 | |||
346 | int | ||
347 | packet_get_keycontext(int mode, u_char *dat) | ||
348 | { | ||
349 | CipherContext *cc; | ||
350 | |||
351 | if (mode == MODE_OUT) | ||
352 | cc = &active_state->send_context; | ||
353 | else | ||
354 | cc = &active_state->receive_context; | ||
355 | |||
356 | return (cipher_get_keycontext(cc, dat)); | ||
357 | } | ||
358 | |||
359 | void | ||
360 | packet_set_keycontext(int mode, u_char *dat) | ||
361 | { | ||
362 | CipherContext *cc; | ||
363 | |||
364 | if (mode == MODE_OUT) | ||
365 | cc = &active_state->send_context; | ||
366 | else | ||
367 | cc = &active_state->receive_context; | ||
368 | |||
369 | cipher_set_keycontext(cc, dat); | ||
370 | } | ||
371 | |||
372 | int | ||
373 | packet_get_keyiv_len(int mode) | ||
374 | { | ||
375 | CipherContext *cc; | ||
376 | |||
377 | if (mode == MODE_OUT) | ||
378 | cc = &active_state->send_context; | ||
379 | else | ||
380 | cc = &active_state->receive_context; | ||
381 | |||
382 | return (cipher_get_keyiv_len(cc)); | ||
383 | } | ||
384 | |||
385 | void | 394 | void |
386 | packet_set_iv(int mode, u_char *dat) | 395 | ssh_packet_get_bytes(struct ssh *ssh, u_int64_t *ibytes, u_int64_t *obytes) |
387 | { | 396 | { |
388 | CipherContext *cc; | 397 | if (ibytes) |
389 | int r; | 398 | *ibytes = ssh->state->p_read.bytes; |
390 | 399 | if (obytes) | |
391 | if (mode == MODE_OUT) | 400 | *obytes = ssh->state->p_send.bytes; |
392 | cc = &active_state->send_context; | ||
393 | else | ||
394 | cc = &active_state->receive_context; | ||
395 | |||
396 | if ((r = cipher_set_keyiv(cc, dat)) != 0) | ||
397 | fatal("%s: cipher_set_keyiv: %s", __func__, ssh_err(r)); | ||
398 | } | 401 | } |
399 | 402 | ||
400 | int | 403 | int |
401 | packet_get_ssh1_cipher(void) | 404 | ssh_packet_connection_af(struct ssh *ssh) |
402 | { | ||
403 | return (cipher_get_number(active_state->receive_context.cipher)); | ||
404 | } | ||
405 | |||
406 | void | ||
407 | packet_get_state(int mode, u_int32_t *seqnr, u_int64_t *blocks, | ||
408 | u_int32_t *packets, u_int64_t *bytes) | ||
409 | { | ||
410 | struct packet_state *state; | ||
411 | |||
412 | state = (mode == MODE_IN) ? | ||
413 | &active_state->p_read : &active_state->p_send; | ||
414 | if (seqnr) | ||
415 | *seqnr = state->seqnr; | ||
416 | if (blocks) | ||
417 | *blocks = state->blocks; | ||
418 | if (packets) | ||
419 | *packets = state->packets; | ||
420 | if (bytes) | ||
421 | *bytes = state->bytes; | ||
422 | } | ||
423 | |||
424 | void | ||
425 | packet_set_state(int mode, u_int32_t seqnr, u_int64_t blocks, u_int32_t packets, | ||
426 | u_int64_t bytes) | ||
427 | { | ||
428 | struct packet_state *state; | ||
429 | |||
430 | state = (mode == MODE_IN) ? | ||
431 | &active_state->p_read : &active_state->p_send; | ||
432 | state->seqnr = seqnr; | ||
433 | state->blocks = blocks; | ||
434 | state->packets = packets; | ||
435 | state->bytes = bytes; | ||
436 | } | ||
437 | |||
438 | static int | ||
439 | packet_connection_af(void) | ||
440 | { | 405 | { |
441 | struct sockaddr_storage to; | 406 | struct sockaddr_storage to; |
442 | socklen_t tolen = sizeof(to); | 407 | socklen_t tolen = sizeof(to); |
443 | 408 | ||
444 | memset(&to, 0, sizeof(to)); | 409 | memset(&to, 0, sizeof(to)); |
445 | if (getsockname(active_state->connection_out, (struct sockaddr *)&to, | 410 | if (getsockname(ssh->state->connection_out, (struct sockaddr *)&to, |
446 | &tolen) < 0) | 411 | &tolen) < 0) |
447 | return 0; | 412 | return 0; |
448 | #ifdef IPV4_IN_IPV6 | 413 | #ifdef IPV4_IN_IPV6 |
@@ -456,72 +421,125 @@ packet_connection_af(void) | |||
456 | /* Sets the connection into non-blocking mode. */ | 421 | /* Sets the connection into non-blocking mode. */ |
457 | 422 | ||
458 | void | 423 | void |
459 | packet_set_nonblocking(void) | 424 | ssh_packet_set_nonblocking(struct ssh *ssh) |
460 | { | 425 | { |
461 | /* Set the socket into non-blocking mode. */ | 426 | /* Set the socket into non-blocking mode. */ |
462 | set_nonblock(active_state->connection_in); | 427 | set_nonblock(ssh->state->connection_in); |
463 | 428 | ||
464 | if (active_state->connection_out != active_state->connection_in) | 429 | if (ssh->state->connection_out != ssh->state->connection_in) |
465 | set_nonblock(active_state->connection_out); | 430 | set_nonblock(ssh->state->connection_out); |
466 | } | 431 | } |
467 | 432 | ||
468 | /* Returns the socket used for reading. */ | 433 | /* Returns the socket used for reading. */ |
469 | 434 | ||
470 | int | 435 | int |
471 | packet_get_connection_in(void) | 436 | ssh_packet_get_connection_in(struct ssh *ssh) |
472 | { | 437 | { |
473 | return active_state->connection_in; | 438 | return ssh->state->connection_in; |
474 | } | 439 | } |
475 | 440 | ||
476 | /* Returns the descriptor used for writing. */ | 441 | /* Returns the descriptor used for writing. */ |
477 | 442 | ||
478 | int | 443 | int |
479 | packet_get_connection_out(void) | 444 | ssh_packet_get_connection_out(struct ssh *ssh) |
445 | { | ||
446 | return ssh->state->connection_out; | ||
447 | } | ||
448 | |||
449 | /* | ||
450 | * Returns the IP-address of the remote host as a string. The returned | ||
451 | * string must not be freed. | ||
452 | */ | ||
453 | |||
454 | const char * | ||
455 | ssh_remote_ipaddr(struct ssh *ssh) | ||
480 | { | 456 | { |
481 | return active_state->connection_out; | 457 | /* Check whether we have cached the ipaddr. */ |
458 | if (ssh->remote_ipaddr == NULL) | ||
459 | ssh->remote_ipaddr = ssh_packet_connection_is_on_socket(ssh) ? | ||
460 | get_peer_ipaddr(ssh->state->connection_in) : | ||
461 | strdup("UNKNOWN"); | ||
462 | if (ssh->remote_ipaddr == NULL) | ||
463 | return "UNKNOWN"; | ||
464 | return ssh->remote_ipaddr; | ||
482 | } | 465 | } |
483 | 466 | ||
484 | /* Closes the connection and clears and frees internal data structures. */ | 467 | /* Closes the connection and clears and frees internal data structures. */ |
485 | 468 | ||
486 | void | 469 | void |
487 | packet_close(void) | 470 | ssh_packet_close(struct ssh *ssh) |
488 | { | 471 | { |
489 | if (!active_state->initialized) | 472 | struct session_state *state = ssh->state; |
473 | int r; | ||
474 | u_int mode; | ||
475 | |||
476 | if (!state->initialized) | ||
490 | return; | 477 | return; |
491 | active_state->initialized = 0; | 478 | state->initialized = 0; |
492 | if (active_state->connection_in == active_state->connection_out) { | 479 | if (state->connection_in == state->connection_out) { |
493 | shutdown(active_state->connection_out, SHUT_RDWR); | 480 | shutdown(state->connection_out, SHUT_RDWR); |
494 | close(active_state->connection_out); | 481 | close(state->connection_out); |
495 | } else { | 482 | } else { |
496 | close(active_state->connection_in); | 483 | close(state->connection_in); |
497 | close(active_state->connection_out); | 484 | close(state->connection_out); |
498 | } | 485 | } |
499 | buffer_free(&active_state->input); | 486 | sshbuf_free(state->input); |
500 | buffer_free(&active_state->output); | 487 | sshbuf_free(state->output); |
501 | buffer_free(&active_state->outgoing_packet); | 488 | sshbuf_free(state->outgoing_packet); |
502 | buffer_free(&active_state->incoming_packet); | 489 | sshbuf_free(state->incoming_packet); |
503 | if (active_state->compression_buffer_ready) { | 490 | for (mode = 0; mode < MODE_MAX; mode++) |
504 | buffer_free(&active_state->compression_buffer); | 491 | kex_free_newkeys(state->newkeys[mode]); |
505 | buffer_compress_uninit(); | 492 | if (state->compression_buffer) { |
493 | sshbuf_free(state->compression_buffer); | ||
494 | if (state->compression_out_started) { | ||
495 | z_streamp stream = &state->compression_out_stream; | ||
496 | debug("compress outgoing: " | ||
497 | "raw data %llu, compressed %llu, factor %.2f", | ||
498 | (unsigned long long)stream->total_in, | ||
499 | (unsigned long long)stream->total_out, | ||
500 | stream->total_in == 0 ? 0.0 : | ||
501 | (double) stream->total_out / stream->total_in); | ||
502 | if (state->compression_out_failures == 0) | ||
503 | deflateEnd(stream); | ||
504 | } | ||
505 | if (state->compression_in_started) { | ||
506 | z_streamp stream = &state->compression_out_stream; | ||
507 | debug("compress incoming: " | ||
508 | "raw data %llu, compressed %llu, factor %.2f", | ||
509 | (unsigned long long)stream->total_out, | ||
510 | (unsigned long long)stream->total_in, | ||
511 | stream->total_out == 0 ? 0.0 : | ||
512 | (double) stream->total_in / stream->total_out); | ||
513 | if (state->compression_in_failures == 0) | ||
514 | inflateEnd(stream); | ||
515 | } | ||
506 | } | 516 | } |
507 | cipher_cleanup(&active_state->send_context); | 517 | if ((r = cipher_cleanup(&state->send_context)) != 0) |
508 | cipher_cleanup(&active_state->receive_context); | 518 | error("%s: cipher_cleanup failed: %s", __func__, ssh_err(r)); |
519 | if ((r = cipher_cleanup(&state->receive_context)) != 0) | ||
520 | error("%s: cipher_cleanup failed: %s", __func__, ssh_err(r)); | ||
521 | if (ssh->remote_ipaddr) { | ||
522 | free(ssh->remote_ipaddr); | ||
523 | ssh->remote_ipaddr = NULL; | ||
524 | } | ||
525 | free(ssh->state); | ||
526 | ssh->state = NULL; | ||
509 | } | 527 | } |
510 | 528 | ||
511 | /* Sets remote side protocol flags. */ | 529 | /* Sets remote side protocol flags. */ |
512 | 530 | ||
513 | void | 531 | void |
514 | packet_set_protocol_flags(u_int protocol_flags) | 532 | ssh_packet_set_protocol_flags(struct ssh *ssh, u_int protocol_flags) |
515 | { | 533 | { |
516 | active_state->remote_protocol_flags = protocol_flags; | 534 | ssh->state->remote_protocol_flags = protocol_flags; |
517 | } | 535 | } |
518 | 536 | ||
519 | /* Returns the remote protocol flags set earlier by the above function. */ | 537 | /* Returns the remote protocol flags set earlier by the above function. */ |
520 | 538 | ||
521 | u_int | 539 | u_int |
522 | packet_get_protocol_flags(void) | 540 | ssh_packet_get_protocol_flags(struct ssh *ssh) |
523 | { | 541 | { |
524 | return active_state->remote_protocol_flags; | 542 | return ssh->state->remote_protocol_flags; |
525 | } | 543 | } |
526 | 544 | ||
527 | /* | 545 | /* |
@@ -529,251 +547,403 @@ packet_get_protocol_flags(void) | |||
529 | * Level is compression level 1 (fastest) - 9 (slow, best) as in gzip. | 547 | * Level is compression level 1 (fastest) - 9 (slow, best) as in gzip. |
530 | */ | 548 | */ |
531 | 549 | ||
532 | static void | 550 | static int |
533 | packet_init_compression(void) | 551 | ssh_packet_init_compression(struct ssh *ssh) |
534 | { | 552 | { |
535 | if (active_state->compression_buffer_ready == 1) | 553 | if (!ssh->state->compression_buffer && |
536 | return; | 554 | ((ssh->state->compression_buffer = sshbuf_new()) == NULL)) |
537 | active_state->compression_buffer_ready = 1; | 555 | return SSH_ERR_ALLOC_FAIL; |
538 | buffer_init(&active_state->compression_buffer); | 556 | return 0; |
539 | } | 557 | } |
540 | 558 | ||
541 | void | 559 | static int |
542 | packet_start_compression(int level) | 560 | start_compression_out(struct ssh *ssh, int level) |
543 | { | 561 | { |
544 | if (active_state->packet_compression && !compat20) | 562 | if (level < 1 || level > 9) |
545 | fatal("Compression already enabled."); | 563 | return SSH_ERR_INVALID_ARGUMENT; |
546 | active_state->packet_compression = 1; | 564 | debug("Enabling compression at level %d.", level); |
547 | packet_init_compression(); | 565 | if (ssh->state->compression_out_started == 1) |
548 | buffer_compress_init_send(level); | 566 | deflateEnd(&ssh->state->compression_out_stream); |
549 | buffer_compress_init_recv(); | 567 | switch (deflateInit(&ssh->state->compression_out_stream, level)) { |
568 | case Z_OK: | ||
569 | ssh->state->compression_out_started = 1; | ||
570 | break; | ||
571 | case Z_MEM_ERROR: | ||
572 | return SSH_ERR_ALLOC_FAIL; | ||
573 | default: | ||
574 | return SSH_ERR_INTERNAL_ERROR; | ||
575 | } | ||
576 | return 0; | ||
550 | } | 577 | } |
551 | 578 | ||
552 | /* | 579 | static int |
553 | * Causes any further packets to be encrypted using the given key. The same | 580 | start_compression_in(struct ssh *ssh) |
554 | * key is used for both sending and reception. However, both directions are | 581 | { |
555 | * encrypted independently of each other. | 582 | if (ssh->state->compression_in_started == 1) |
556 | */ | 583 | inflateEnd(&ssh->state->compression_in_stream); |
584 | switch (inflateInit(&ssh->state->compression_in_stream)) { | ||
585 | case Z_OK: | ||
586 | ssh->state->compression_in_started = 1; | ||
587 | break; | ||
588 | case Z_MEM_ERROR: | ||
589 | return SSH_ERR_ALLOC_FAIL; | ||
590 | default: | ||
591 | return SSH_ERR_INTERNAL_ERROR; | ||
592 | } | ||
593 | return 0; | ||
594 | } | ||
557 | 595 | ||
558 | void | 596 | int |
559 | packet_set_encryption_key(const u_char *key, u_int keylen, int number) | 597 | ssh_packet_start_compression(struct ssh *ssh, int level) |
560 | { | 598 | { |
561 | const Cipher *cipher = cipher_by_number(number); | ||
562 | int r; | 599 | int r; |
563 | 600 | ||
564 | if (cipher == NULL) | 601 | if (ssh->state->packet_compression && !compat20) |
565 | fatal("packet_set_encryption_key: unknown cipher number %d", number); | 602 | return SSH_ERR_INTERNAL_ERROR; |
566 | if (keylen < 20) | 603 | ssh->state->packet_compression = 1; |
567 | fatal("packet_set_encryption_key: keylen too small: %d", keylen); | 604 | if ((r = ssh_packet_init_compression(ssh)) != 0 || |
568 | if (keylen > SSH_SESSION_KEY_LENGTH) | 605 | (r = start_compression_in(ssh)) != 0 || |
569 | fatal("packet_set_encryption_key: keylen too big: %d", keylen); | 606 | (r = start_compression_out(ssh, level)) != 0) |
570 | memcpy(active_state->ssh1_key, key, keylen); | 607 | return r; |
571 | active_state->ssh1_keylen = keylen; | 608 | return 0; |
572 | if ((r = cipher_init(&active_state->send_context, cipher, | ||
573 | key, keylen, NULL, 0, CIPHER_ENCRYPT)) != 0 || | ||
574 | (r = cipher_init(&active_state->receive_context, cipher, | ||
575 | key, keylen, NULL, 0, CIPHER_DECRYPT)) != 0) | ||
576 | fatal("%s: cipher_init: %s", __func__, ssh_err(r)); | ||
577 | } | 609 | } |
578 | 610 | ||
579 | u_int | 611 | /* XXX remove need for separate compression buffer */ |
580 | packet_get_encryption_key(u_char *key) | 612 | static int |
613 | compress_buffer(struct ssh *ssh, struct sshbuf *in, struct sshbuf *out) | ||
581 | { | 614 | { |
582 | if (key == NULL) | 615 | u_char buf[4096]; |
583 | return (active_state->ssh1_keylen); | 616 | int r, status; |
584 | memcpy(key, active_state->ssh1_key, active_state->ssh1_keylen); | ||
585 | return (active_state->ssh1_keylen); | ||
586 | } | ||
587 | 617 | ||
588 | /* Start constructing a packet to send. */ | 618 | if (ssh->state->compression_out_started != 1) |
589 | void | 619 | return SSH_ERR_INTERNAL_ERROR; |
590 | packet_start(u_char type) | ||
591 | { | ||
592 | u_char buf[9]; | ||
593 | int len; | ||
594 | 620 | ||
595 | DBG(debug("packet_start[%d]", type)); | 621 | /* This case is not handled below. */ |
596 | len = compat20 ? 6 : 9; | 622 | if (sshbuf_len(in) == 0) |
597 | memset(buf, 0, len - 1); | 623 | return 0; |
598 | buf[len - 1] = type; | 624 | |
599 | buffer_clear(&active_state->outgoing_packet); | 625 | /* Input is the contents of the input buffer. */ |
600 | buffer_append(&active_state->outgoing_packet, buf, len); | 626 | if ((ssh->state->compression_out_stream.next_in = |
627 | sshbuf_mutable_ptr(in)) == NULL) | ||
628 | return SSH_ERR_INTERNAL_ERROR; | ||
629 | ssh->state->compression_out_stream.avail_in = sshbuf_len(in); | ||
630 | |||
631 | /* Loop compressing until deflate() returns with avail_out != 0. */ | ||
632 | do { | ||
633 | /* Set up fixed-size output buffer. */ | ||
634 | ssh->state->compression_out_stream.next_out = buf; | ||
635 | ssh->state->compression_out_stream.avail_out = sizeof(buf); | ||
636 | |||
637 | /* Compress as much data into the buffer as possible. */ | ||
638 | status = deflate(&ssh->state->compression_out_stream, | ||
639 | Z_PARTIAL_FLUSH); | ||
640 | switch (status) { | ||
641 | case Z_MEM_ERROR: | ||
642 | return SSH_ERR_ALLOC_FAIL; | ||
643 | case Z_OK: | ||
644 | /* Append compressed data to output_buffer. */ | ||
645 | if ((r = sshbuf_put(out, buf, sizeof(buf) - | ||
646 | ssh->state->compression_out_stream.avail_out)) != 0) | ||
647 | return r; | ||
648 | break; | ||
649 | case Z_STREAM_ERROR: | ||
650 | default: | ||
651 | ssh->state->compression_out_failures++; | ||
652 | return SSH_ERR_INVALID_FORMAT; | ||
653 | } | ||
654 | } while (ssh->state->compression_out_stream.avail_out == 0); | ||
655 | return 0; | ||
601 | } | 656 | } |
602 | 657 | ||
603 | /* Append payload. */ | 658 | static int |
604 | void | 659 | uncompress_buffer(struct ssh *ssh, struct sshbuf *in, struct sshbuf *out) |
605 | packet_put_char(int value) | ||
606 | { | 660 | { |
607 | char ch = value; | 661 | u_char buf[4096]; |
662 | int r, status; | ||
608 | 663 | ||
609 | buffer_append(&active_state->outgoing_packet, &ch, 1); | 664 | if (ssh->state->compression_in_started != 1) |
610 | } | 665 | return SSH_ERR_INTERNAL_ERROR; |
611 | 666 | ||
612 | void | 667 | if ((ssh->state->compression_in_stream.next_in = |
613 | packet_put_int(u_int value) | 668 | sshbuf_mutable_ptr(in)) == NULL) |
614 | { | 669 | return SSH_ERR_INTERNAL_ERROR; |
615 | buffer_put_int(&active_state->outgoing_packet, value); | 670 | ssh->state->compression_in_stream.avail_in = sshbuf_len(in); |
616 | } | ||
617 | 671 | ||
618 | void | 672 | for (;;) { |
619 | packet_put_int64(u_int64_t value) | 673 | /* Set up fixed-size output buffer. */ |
620 | { | 674 | ssh->state->compression_in_stream.next_out = buf; |
621 | buffer_put_int64(&active_state->outgoing_packet, value); | 675 | ssh->state->compression_in_stream.avail_out = sizeof(buf); |
676 | |||
677 | status = inflate(&ssh->state->compression_in_stream, | ||
678 | Z_PARTIAL_FLUSH); | ||
679 | switch (status) { | ||
680 | case Z_OK: | ||
681 | if ((r = sshbuf_put(out, buf, sizeof(buf) - | ||
682 | ssh->state->compression_in_stream.avail_out)) != 0) | ||
683 | return r; | ||
684 | break; | ||
685 | case Z_BUF_ERROR: | ||
686 | /* | ||
687 | * Comments in zlib.h say that we should keep calling | ||
688 | * inflate() until we get an error. This appears to | ||
689 | * be the error that we get. | ||
690 | */ | ||
691 | return 0; | ||
692 | case Z_DATA_ERROR: | ||
693 | return SSH_ERR_INVALID_FORMAT; | ||
694 | case Z_MEM_ERROR: | ||
695 | return SSH_ERR_ALLOC_FAIL; | ||
696 | case Z_STREAM_ERROR: | ||
697 | default: | ||
698 | ssh->state->compression_in_failures++; | ||
699 | return SSH_ERR_INTERNAL_ERROR; | ||
700 | } | ||
701 | } | ||
702 | /* NOTREACHED */ | ||
622 | } | 703 | } |
623 | 704 | ||
624 | void | 705 | /* Serialise compression state into a blob for privsep */ |
625 | packet_put_string(const void *buf, u_int len) | 706 | static int |
707 | ssh_packet_get_compress_state(struct sshbuf *m, struct ssh *ssh) | ||
626 | { | 708 | { |
627 | buffer_put_string(&active_state->outgoing_packet, buf, len); | 709 | struct session_state *state = ssh->state; |
628 | } | 710 | struct sshbuf *b; |
711 | int r; | ||
629 | 712 | ||
630 | void | 713 | if ((b = sshbuf_new()) == NULL) |
631 | packet_put_cstring(const char *str) | 714 | return SSH_ERR_ALLOC_FAIL; |
715 | if (state->compression_in_started) { | ||
716 | if ((r = sshbuf_put_string(b, &state->compression_in_stream, | ||
717 | sizeof(state->compression_in_stream))) != 0) | ||
718 | goto out; | ||
719 | } else if ((r = sshbuf_put_string(b, NULL, 0)) != 0) | ||
720 | goto out; | ||
721 | if (state->compression_out_started) { | ||
722 | if ((r = sshbuf_put_string(b, &state->compression_out_stream, | ||
723 | sizeof(state->compression_out_stream))) != 0) | ||
724 | goto out; | ||
725 | } else if ((r = sshbuf_put_string(b, NULL, 0)) != 0) | ||
726 | goto out; | ||
727 | r = sshbuf_put_stringb(m, b); | ||
728 | out: | ||
729 | sshbuf_free(b); | ||
730 | return r; | ||
731 | } | ||
732 | |||
733 | /* Deserialise compression state from a blob for privsep */ | ||
734 | static int | ||
735 | ssh_packet_set_compress_state(struct ssh *ssh, struct sshbuf *m) | ||
632 | { | 736 | { |
633 | buffer_put_cstring(&active_state->outgoing_packet, str); | 737 | struct session_state *state = ssh->state; |
738 | struct sshbuf *b = NULL; | ||
739 | int r; | ||
740 | const u_char *inblob, *outblob; | ||
741 | size_t inl, outl; | ||
742 | |||
743 | if ((r = sshbuf_froms(m, &b)) != 0) | ||
744 | goto out; | ||
745 | if ((r = sshbuf_get_string_direct(b, &inblob, &inl)) != 0 || | ||
746 | (r = sshbuf_get_string_direct(b, &outblob, &outl)) != 0) | ||
747 | goto out; | ||
748 | if (inl == 0) | ||
749 | state->compression_in_started = 0; | ||
750 | else if (inl != sizeof(state->compression_in_stream)) { | ||
751 | r = SSH_ERR_INTERNAL_ERROR; | ||
752 | goto out; | ||
753 | } else { | ||
754 | state->compression_in_started = 1; | ||
755 | memcpy(&state->compression_in_stream, inblob, inl); | ||
756 | } | ||
757 | if (outl == 0) | ||
758 | state->compression_out_started = 0; | ||
759 | else if (outl != sizeof(state->compression_out_stream)) { | ||
760 | r = SSH_ERR_INTERNAL_ERROR; | ||
761 | goto out; | ||
762 | } else { | ||
763 | state->compression_out_started = 1; | ||
764 | memcpy(&state->compression_out_stream, outblob, outl); | ||
765 | } | ||
766 | r = 0; | ||
767 | out: | ||
768 | sshbuf_free(b); | ||
769 | return r; | ||
634 | } | 770 | } |
635 | 771 | ||
636 | void | 772 | void |
637 | packet_put_raw(const void *buf, u_int len) | 773 | ssh_packet_set_compress_hooks(struct ssh *ssh, void *ctx, |
774 | void *(*allocfunc)(void *, u_int, u_int), | ||
775 | void (*freefunc)(void *, void *)) | ||
638 | { | 776 | { |
639 | buffer_append(&active_state->outgoing_packet, buf, len); | 777 | ssh->state->compression_out_stream.zalloc = (alloc_func)allocfunc; |
778 | ssh->state->compression_out_stream.zfree = (free_func)freefunc; | ||
779 | ssh->state->compression_out_stream.opaque = ctx; | ||
780 | ssh->state->compression_in_stream.zalloc = (alloc_func)allocfunc; | ||
781 | ssh->state->compression_in_stream.zfree = (free_func)freefunc; | ||
782 | ssh->state->compression_in_stream.opaque = ctx; | ||
640 | } | 783 | } |
641 | 784 | ||
642 | #ifdef WITH_OPENSSL | 785 | /* |
643 | void | 786 | * Causes any further packets to be encrypted using the given key. The same |
644 | packet_put_bignum(BIGNUM * value) | 787 | * key is used for both sending and reception. However, both directions are |
645 | { | 788 | * encrypted independently of each other. |
646 | buffer_put_bignum(&active_state->outgoing_packet, value); | 789 | */ |
647 | } | ||
648 | 790 | ||
649 | void | 791 | void |
650 | packet_put_bignum2(BIGNUM * value) | 792 | ssh_packet_set_encryption_key(struct ssh *ssh, const u_char *key, u_int keylen, int number) |
651 | { | 793 | { |
652 | buffer_put_bignum2(&active_state->outgoing_packet, value); | 794 | #ifdef WITH_SSH1 |
653 | } | 795 | struct session_state *state = ssh->state; |
654 | #endif | 796 | const struct sshcipher *cipher = cipher_by_number(number); |
797 | int r; | ||
798 | const char *wmsg; | ||
655 | 799 | ||
656 | #ifdef OPENSSL_HAS_ECC | 800 | if (cipher == NULL) |
657 | void | 801 | fatal("%s: unknown cipher number %d", __func__, number); |
658 | packet_put_ecpoint(const EC_GROUP *curve, const EC_POINT *point) | 802 | if (keylen < 20) |
659 | { | 803 | fatal("%s: keylen too small: %d", __func__, keylen); |
660 | buffer_put_ecpoint(&active_state->outgoing_packet, curve, point); | 804 | if (keylen > SSH_SESSION_KEY_LENGTH) |
805 | fatal("%s: keylen too big: %d", __func__, keylen); | ||
806 | memcpy(state->ssh1_key, key, keylen); | ||
807 | state->ssh1_keylen = keylen; | ||
808 | if ((r = cipher_init(&state->send_context, cipher, key, keylen, | ||
809 | NULL, 0, CIPHER_ENCRYPT)) != 0 || | ||
810 | (r = cipher_init(&state->receive_context, cipher, key, keylen, | ||
811 | NULL, 0, CIPHER_DECRYPT) != 0)) | ||
812 | fatal("%s: cipher_init failed: %s", __func__, ssh_err(r)); | ||
813 | if (!state->cipher_warning_done && | ||
814 | ((wmsg = cipher_warning_message(&state->send_context)) != NULL || | ||
815 | (wmsg = cipher_warning_message(&state->send_context)) != NULL)) { | ||
816 | error("Warning: %s", wmsg); | ||
817 | state->cipher_warning_done = 1; | ||
818 | } | ||
819 | #endif /* WITH_SSH1 */ | ||
661 | } | 820 | } |
662 | #endif | ||
663 | 821 | ||
664 | /* | 822 | /* |
665 | * Finalizes and sends the packet. If the encryption key has been set, | 823 | * Finalizes and sends the packet. If the encryption key has been set, |
666 | * encrypts the packet before sending. | 824 | * encrypts the packet before sending. |
667 | */ | 825 | */ |
668 | 826 | ||
669 | static void | 827 | int |
670 | packet_send1(void) | 828 | ssh_packet_send1(struct ssh *ssh) |
671 | { | 829 | { |
830 | struct session_state *state = ssh->state; | ||
672 | u_char buf[8], *cp; | 831 | u_char buf[8], *cp; |
673 | int i, padding, len; | 832 | int r, padding, len; |
674 | u_int checksum; | 833 | u_int checksum; |
675 | u_int32_t rnd = 0; | ||
676 | 834 | ||
677 | /* | 835 | /* |
678 | * If using packet compression, compress the payload of the outgoing | 836 | * If using packet compression, compress the payload of the outgoing |
679 | * packet. | 837 | * packet. |
680 | */ | 838 | */ |
681 | if (active_state->packet_compression) { | 839 | if (state->packet_compression) { |
682 | buffer_clear(&active_state->compression_buffer); | 840 | sshbuf_reset(state->compression_buffer); |
683 | /* Skip padding. */ | 841 | /* Skip padding. */ |
684 | buffer_consume(&active_state->outgoing_packet, 8); | 842 | if ((r = sshbuf_consume(state->outgoing_packet, 8)) != 0) |
843 | goto out; | ||
685 | /* padding */ | 844 | /* padding */ |
686 | buffer_append(&active_state->compression_buffer, | 845 | if ((r = sshbuf_put(state->compression_buffer, |
687 | "\0\0\0\0\0\0\0\0", 8); | 846 | "\0\0\0\0\0\0\0\0", 8)) != 0) |
688 | buffer_compress(&active_state->outgoing_packet, | 847 | goto out; |
689 | &active_state->compression_buffer); | 848 | if ((r = compress_buffer(ssh, state->outgoing_packet, |
690 | buffer_clear(&active_state->outgoing_packet); | 849 | state->compression_buffer)) != 0) |
691 | buffer_append(&active_state->outgoing_packet, | 850 | goto out; |
692 | buffer_ptr(&active_state->compression_buffer), | 851 | sshbuf_reset(state->outgoing_packet); |
693 | buffer_len(&active_state->compression_buffer)); | 852 | if ((r = sshbuf_putb(state->outgoing_packet, |
853 | state->compression_buffer)) != 0) | ||
854 | goto out; | ||
694 | } | 855 | } |
695 | /* Compute packet length without padding (add checksum, remove padding). */ | 856 | /* Compute packet length without padding (add checksum, remove padding). */ |
696 | len = buffer_len(&active_state->outgoing_packet) + 4 - 8; | 857 | len = sshbuf_len(state->outgoing_packet) + 4 - 8; |
697 | 858 | ||
698 | /* Insert padding. Initialized to zero in packet_start1() */ | 859 | /* Insert padding. Initialized to zero in packet_start1() */ |
699 | padding = 8 - len % 8; | 860 | padding = 8 - len % 8; |
700 | if (!active_state->send_context.plaintext) { | 861 | if (!state->send_context.plaintext) { |
701 | cp = buffer_ptr(&active_state->outgoing_packet); | 862 | cp = sshbuf_mutable_ptr(state->outgoing_packet); |
702 | for (i = 0; i < padding; i++) { | 863 | if (cp == NULL) { |
703 | if (i % 4 == 0) | 864 | r = SSH_ERR_INTERNAL_ERROR; |
704 | rnd = arc4random(); | 865 | goto out; |
705 | cp[7 - i] = rnd & 0xff; | ||
706 | rnd >>= 8; | ||
707 | } | 866 | } |
867 | arc4random_buf(cp + 8 - padding, padding); | ||
708 | } | 868 | } |
709 | buffer_consume(&active_state->outgoing_packet, 8 - padding); | 869 | if ((r = sshbuf_consume(state->outgoing_packet, 8 - padding)) != 0) |
870 | goto out; | ||
710 | 871 | ||
711 | /* Add check bytes. */ | 872 | /* Add check bytes. */ |
712 | checksum = ssh_crc32(buffer_ptr(&active_state->outgoing_packet), | 873 | checksum = ssh_crc32(sshbuf_ptr(state->outgoing_packet), |
713 | buffer_len(&active_state->outgoing_packet)); | 874 | sshbuf_len(state->outgoing_packet)); |
714 | put_u32(buf, checksum); | 875 | POKE_U32(buf, checksum); |
715 | buffer_append(&active_state->outgoing_packet, buf, 4); | 876 | if ((r = sshbuf_put(state->outgoing_packet, buf, 4)) != 0) |
877 | goto out; | ||
716 | 878 | ||
717 | #ifdef PACKET_DEBUG | 879 | #ifdef PACKET_DEBUG |
718 | fprintf(stderr, "packet_send plain: "); | 880 | fprintf(stderr, "packet_send plain: "); |
719 | buffer_dump(&active_state->outgoing_packet); | 881 | sshbuf_dump(state->outgoing_packet, stderr); |
720 | #endif | 882 | #endif |
721 | 883 | ||
722 | /* Append to output. */ | 884 | /* Append to output. */ |
723 | put_u32(buf, len); | 885 | POKE_U32(buf, len); |
724 | buffer_append(&active_state->output, buf, 4); | 886 | if ((r = sshbuf_put(state->output, buf, 4)) != 0) |
725 | cp = buffer_append_space(&active_state->output, | 887 | goto out; |
726 | buffer_len(&active_state->outgoing_packet)); | 888 | if ((r = sshbuf_reserve(state->output, |
727 | if (cipher_crypt(&active_state->send_context, 0, cp, | 889 | sshbuf_len(state->outgoing_packet), &cp)) != 0) |
728 | buffer_ptr(&active_state->outgoing_packet), | 890 | goto out; |
729 | buffer_len(&active_state->outgoing_packet), 0, 0) != 0) | 891 | if ((r = cipher_crypt(&state->send_context, 0, cp, |
730 | fatal("%s: cipher_crypt failed", __func__); | 892 | sshbuf_ptr(state->outgoing_packet), |
893 | sshbuf_len(state->outgoing_packet), 0, 0)) != 0) | ||
894 | goto out; | ||
731 | 895 | ||
732 | #ifdef PACKET_DEBUG | 896 | #ifdef PACKET_DEBUG |
733 | fprintf(stderr, "encrypted: "); | 897 | fprintf(stderr, "encrypted: "); |
734 | buffer_dump(&active_state->output); | 898 | sshbuf_dump(state->output, stderr); |
735 | #endif | 899 | #endif |
736 | active_state->p_send.packets++; | 900 | state->p_send.packets++; |
737 | active_state->p_send.bytes += len + | 901 | state->p_send.bytes += len + |
738 | buffer_len(&active_state->outgoing_packet); | 902 | sshbuf_len(state->outgoing_packet); |
739 | buffer_clear(&active_state->outgoing_packet); | 903 | sshbuf_reset(state->outgoing_packet); |
740 | 904 | ||
741 | /* | 905 | /* |
742 | * Note that the packet is now only buffered in output. It won't be | 906 | * Note that the packet is now only buffered in output. It won't be |
743 | * actually sent until packet_write_wait or packet_write_poll is | 907 | * actually sent until ssh_packet_write_wait or ssh_packet_write_poll |
744 | * called. | 908 | * is called. |
745 | */ | 909 | */ |
910 | r = 0; | ||
911 | out: | ||
912 | return r; | ||
746 | } | 913 | } |
747 | 914 | ||
748 | void | 915 | int |
749 | set_newkeys(int mode) | 916 | ssh_set_newkeys(struct ssh *ssh, int mode) |
750 | { | 917 | { |
751 | Enc *enc; | 918 | struct session_state *state = ssh->state; |
752 | Mac *mac; | 919 | struct sshenc *enc; |
753 | Comp *comp; | 920 | struct sshmac *mac; |
754 | CipherContext *cc; | 921 | struct sshcomp *comp; |
922 | struct sshcipher_ctx *cc; | ||
755 | u_int64_t *max_blocks; | 923 | u_int64_t *max_blocks; |
924 | const char *wmsg; | ||
756 | int r, crypt_type; | 925 | int r, crypt_type; |
757 | 926 | ||
758 | debug2("set_newkeys: mode %d", mode); | 927 | debug2("set_newkeys: mode %d", mode); |
759 | 928 | ||
760 | if (mode == MODE_OUT) { | 929 | if (mode == MODE_OUT) { |
761 | cc = &active_state->send_context; | 930 | cc = &state->send_context; |
762 | crypt_type = CIPHER_ENCRYPT; | 931 | crypt_type = CIPHER_ENCRYPT; |
763 | active_state->p_send.packets = active_state->p_send.blocks = 0; | 932 | state->p_send.packets = state->p_send.blocks = 0; |
764 | max_blocks = &active_state->max_blocks_out; | 933 | max_blocks = &state->max_blocks_out; |
765 | } else { | 934 | } else { |
766 | cc = &active_state->receive_context; | 935 | cc = &state->receive_context; |
767 | crypt_type = CIPHER_DECRYPT; | 936 | crypt_type = CIPHER_DECRYPT; |
768 | active_state->p_read.packets = active_state->p_read.blocks = 0; | 937 | state->p_read.packets = state->p_read.blocks = 0; |
769 | max_blocks = &active_state->max_blocks_in; | 938 | max_blocks = &state->max_blocks_in; |
770 | } | 939 | } |
771 | if (active_state->newkeys[mode] != NULL) { | 940 | if (state->newkeys[mode] != NULL) { |
772 | debug("set_newkeys: rekeying"); | 941 | debug("set_newkeys: rekeying"); |
773 | cipher_cleanup(cc); | 942 | if ((r = cipher_cleanup(cc)) != 0) |
774 | enc = &active_state->newkeys[mode]->enc; | 943 | return r; |
775 | mac = &active_state->newkeys[mode]->mac; | 944 | enc = &state->newkeys[mode]->enc; |
776 | comp = &active_state->newkeys[mode]->comp; | 945 | mac = &state->newkeys[mode]->mac; |
946 | comp = &state->newkeys[mode]->comp; | ||
777 | mac_clear(mac); | 947 | mac_clear(mac); |
778 | explicit_bzero(enc->iv, enc->iv_len); | 948 | explicit_bzero(enc->iv, enc->iv_len); |
779 | explicit_bzero(enc->key, enc->key_len); | 949 | explicit_bzero(enc->key, enc->key_len); |
@@ -784,32 +954,45 @@ set_newkeys(int mode) | |||
784 | free(mac->name); | 954 | free(mac->name); |
785 | free(mac->key); | 955 | free(mac->key); |
786 | free(comp->name); | 956 | free(comp->name); |
787 | free(active_state->newkeys[mode]); | 957 | free(state->newkeys[mode]); |
788 | } | 958 | } |
789 | active_state->newkeys[mode] = kex_get_newkeys(mode); | 959 | /* move newkeys from kex to state */ |
790 | if (active_state->newkeys[mode] == NULL) | 960 | if ((state->newkeys[mode] = ssh->kex->newkeys[mode]) == NULL) |
791 | fatal("newkeys: no keys for mode %d", mode); | 961 | return SSH_ERR_INTERNAL_ERROR; |
792 | enc = &active_state->newkeys[mode]->enc; | 962 | ssh->kex->newkeys[mode] = NULL; |
793 | mac = &active_state->newkeys[mode]->mac; | 963 | enc = &state->newkeys[mode]->enc; |
794 | comp = &active_state->newkeys[mode]->comp; | 964 | mac = &state->newkeys[mode]->mac; |
795 | if (cipher_authlen(enc->cipher) == 0 && mac_init(mac) == 0) | 965 | comp = &state->newkeys[mode]->comp; |
796 | mac->enabled = 1; | 966 | if (cipher_authlen(enc->cipher) == 0) { |
967 | if ((r = mac_init(mac)) != 0) | ||
968 | return r; | ||
969 | } | ||
970 | mac->enabled = 1; | ||
797 | DBG(debug("cipher_init_context: %d", mode)); | 971 | DBG(debug("cipher_init_context: %d", mode)); |
798 | if ((r = cipher_init(cc, enc->cipher, enc->key, enc->key_len, | 972 | if ((r = cipher_init(cc, enc->cipher, enc->key, enc->key_len, |
799 | enc->iv, enc->iv_len, crypt_type)) != 0) | 973 | enc->iv, enc->iv_len, crypt_type)) != 0) |
800 | fatal("%s: cipher_init: %s", __func__, ssh_err(r)); | 974 | return r; |
975 | if (!state->cipher_warning_done && | ||
976 | (wmsg = cipher_warning_message(cc)) != NULL) { | ||
977 | error("Warning: %s", wmsg); | ||
978 | state->cipher_warning_done = 1; | ||
979 | } | ||
801 | /* Deleting the keys does not gain extra security */ | 980 | /* Deleting the keys does not gain extra security */ |
802 | /* explicit_bzero(enc->iv, enc->block_size); | 981 | /* explicit_bzero(enc->iv, enc->block_size); |
803 | explicit_bzero(enc->key, enc->key_len); | 982 | explicit_bzero(enc->key, enc->key_len); |
804 | explicit_bzero(mac->key, mac->key_len); */ | 983 | explicit_bzero(mac->key, mac->key_len); */ |
805 | if ((comp->type == COMP_ZLIB || | 984 | if ((comp->type == COMP_ZLIB || |
806 | (comp->type == COMP_DELAYED && | 985 | (comp->type == COMP_DELAYED && |
807 | active_state->after_authentication)) && comp->enabled == 0) { | 986 | state->after_authentication)) && comp->enabled == 0) { |
808 | packet_init_compression(); | 987 | if ((r = ssh_packet_init_compression(ssh)) < 0) |
809 | if (mode == MODE_OUT) | 988 | return r; |
810 | buffer_compress_init_send(6); | 989 | if (mode == MODE_OUT) { |
811 | else | 990 | if ((r = start_compression_out(ssh, 6)) != 0) |
812 | buffer_compress_init_recv(); | 991 | return r; |
992 | } else { | ||
993 | if ((r = start_compression_in(ssh)) != 0) | ||
994 | return r; | ||
995 | } | ||
813 | comp->enabled = 1; | 996 | comp->enabled = 1; |
814 | } | 997 | } |
815 | /* | 998 | /* |
@@ -820,9 +1003,10 @@ set_newkeys(int mode) | |||
820 | *max_blocks = (u_int64_t)1 << (enc->block_size*2); | 1003 | *max_blocks = (u_int64_t)1 << (enc->block_size*2); |
821 | else | 1004 | else |
822 | *max_blocks = ((u_int64_t)1 << 30) / enc->block_size; | 1005 | *max_blocks = ((u_int64_t)1 << 30) / enc->block_size; |
823 | if (active_state->rekey_limit) | 1006 | if (state->rekey_limit) |
824 | *max_blocks = MIN(*max_blocks, | 1007 | *max_blocks = MIN(*max_blocks, |
825 | active_state->rekey_limit / enc->block_size); | 1008 | state->rekey_limit / enc->block_size); |
1009 | return 0; | ||
826 | } | 1010 | } |
827 | 1011 | ||
828 | /* | 1012 | /* |
@@ -830,52 +1014,59 @@ set_newkeys(int mode) | |||
830 | * This happens on the server side after a SSH2_MSG_USERAUTH_SUCCESS is sent, | 1014 | * This happens on the server side after a SSH2_MSG_USERAUTH_SUCCESS is sent, |
831 | * and on the client side after a SSH2_MSG_USERAUTH_SUCCESS is received. | 1015 | * and on the client side after a SSH2_MSG_USERAUTH_SUCCESS is received. |
832 | */ | 1016 | */ |
833 | static void | 1017 | static int |
834 | packet_enable_delayed_compress(void) | 1018 | ssh_packet_enable_delayed_compress(struct ssh *ssh) |
835 | { | 1019 | { |
836 | Comp *comp = NULL; | 1020 | struct session_state *state = ssh->state; |
837 | int mode; | 1021 | struct sshcomp *comp = NULL; |
1022 | int r, mode; | ||
838 | 1023 | ||
839 | /* | 1024 | /* |
840 | * Remember that we are past the authentication step, so rekeying | 1025 | * Remember that we are past the authentication step, so rekeying |
841 | * with COMP_DELAYED will turn on compression immediately. | 1026 | * with COMP_DELAYED will turn on compression immediately. |
842 | */ | 1027 | */ |
843 | active_state->after_authentication = 1; | 1028 | state->after_authentication = 1; |
844 | for (mode = 0; mode < MODE_MAX; mode++) { | 1029 | for (mode = 0; mode < MODE_MAX; mode++) { |
845 | /* protocol error: USERAUTH_SUCCESS received before NEWKEYS */ | 1030 | /* protocol error: USERAUTH_SUCCESS received before NEWKEYS */ |
846 | if (active_state->newkeys[mode] == NULL) | 1031 | if (state->newkeys[mode] == NULL) |
847 | continue; | 1032 | continue; |
848 | comp = &active_state->newkeys[mode]->comp; | 1033 | comp = &state->newkeys[mode]->comp; |
849 | if (comp && !comp->enabled && comp->type == COMP_DELAYED) { | 1034 | if (comp && !comp->enabled && comp->type == COMP_DELAYED) { |
850 | packet_init_compression(); | 1035 | if ((r = ssh_packet_init_compression(ssh)) != 0) |
851 | if (mode == MODE_OUT) | 1036 | return r; |
852 | buffer_compress_init_send(6); | 1037 | if (mode == MODE_OUT) { |
853 | else | 1038 | if ((r = start_compression_out(ssh, 6)) != 0) |
854 | buffer_compress_init_recv(); | 1039 | return r; |
1040 | } else { | ||
1041 | if ((r = start_compression_in(ssh)) != 0) | ||
1042 | return r; | ||
1043 | } | ||
855 | comp->enabled = 1; | 1044 | comp->enabled = 1; |
856 | } | 1045 | } |
857 | } | 1046 | } |
1047 | return 0; | ||
858 | } | 1048 | } |
859 | 1049 | ||
860 | /* | 1050 | /* |
861 | * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue) | 1051 | * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue) |
862 | */ | 1052 | */ |
863 | static void | 1053 | int |
864 | packet_send2_wrapped(void) | 1054 | ssh_packet_send2_wrapped(struct ssh *ssh) |
865 | { | 1055 | { |
866 | u_char type, *cp, *macbuf = NULL; | 1056 | struct session_state *state = ssh->state; |
1057 | u_char type, *cp, macbuf[SSH_DIGEST_MAX_LENGTH]; | ||
867 | u_char padlen, pad = 0; | 1058 | u_char padlen, pad = 0; |
868 | u_int i, len, authlen = 0, aadlen = 0; | 1059 | u_int authlen = 0, aadlen = 0; |
869 | u_int32_t rnd = 0; | 1060 | u_int len; |
870 | Enc *enc = NULL; | 1061 | struct sshenc *enc = NULL; |
871 | Mac *mac = NULL; | 1062 | struct sshmac *mac = NULL; |
872 | Comp *comp = NULL; | 1063 | struct sshcomp *comp = NULL; |
873 | int block_size; | 1064 | int r, block_size; |
874 | 1065 | ||
875 | if (active_state->newkeys[MODE_OUT] != NULL) { | 1066 | if (state->newkeys[MODE_OUT] != NULL) { |
876 | enc = &active_state->newkeys[MODE_OUT]->enc; | 1067 | enc = &state->newkeys[MODE_OUT]->enc; |
877 | mac = &active_state->newkeys[MODE_OUT]->mac; | 1068 | mac = &state->newkeys[MODE_OUT]->mac; |
878 | comp = &active_state->newkeys[MODE_OUT]->comp; | 1069 | comp = &state->newkeys[MODE_OUT]->comp; |
879 | /* disable mac for authenticated encryption */ | 1070 | /* disable mac for authenticated encryption */ |
880 | if ((authlen = cipher_authlen(enc->cipher)) != 0) | 1071 | if ((authlen = cipher_authlen(enc->cipher)) != 0) |
881 | mac = NULL; | 1072 | mac = NULL; |
@@ -883,32 +1074,34 @@ packet_send2_wrapped(void) | |||
883 | block_size = enc ? enc->block_size : 8; | 1074 | block_size = enc ? enc->block_size : 8; |
884 | aadlen = (mac && mac->enabled && mac->etm) || authlen ? 4 : 0; | 1075 | aadlen = (mac && mac->enabled && mac->etm) || authlen ? 4 : 0; |
885 | 1076 | ||
886 | cp = buffer_ptr(&active_state->outgoing_packet); | 1077 | type = (sshbuf_ptr(state->outgoing_packet))[5]; |
887 | type = cp[5]; | ||
888 | 1078 | ||
889 | #ifdef PACKET_DEBUG | 1079 | #ifdef PACKET_DEBUG |
890 | fprintf(stderr, "plain: "); | 1080 | fprintf(stderr, "plain: "); |
891 | buffer_dump(&active_state->outgoing_packet); | 1081 | sshbuf_dump(state->outgoing_packet, stderr); |
892 | #endif | 1082 | #endif |
893 | 1083 | ||
894 | if (comp && comp->enabled) { | 1084 | if (comp && comp->enabled) { |
895 | len = buffer_len(&active_state->outgoing_packet); | 1085 | len = sshbuf_len(state->outgoing_packet); |
896 | /* skip header, compress only payload */ | 1086 | /* skip header, compress only payload */ |
897 | buffer_consume(&active_state->outgoing_packet, 5); | 1087 | if ((r = sshbuf_consume(state->outgoing_packet, 5)) != 0) |
898 | buffer_clear(&active_state->compression_buffer); | 1088 | goto out; |
899 | buffer_compress(&active_state->outgoing_packet, | 1089 | sshbuf_reset(state->compression_buffer); |
900 | &active_state->compression_buffer); | 1090 | if ((r = compress_buffer(ssh, state->outgoing_packet, |
901 | buffer_clear(&active_state->outgoing_packet); | 1091 | state->compression_buffer)) != 0) |
902 | buffer_append(&active_state->outgoing_packet, "\0\0\0\0\0", 5); | 1092 | goto out; |
903 | buffer_append(&active_state->outgoing_packet, | 1093 | sshbuf_reset(state->outgoing_packet); |
904 | buffer_ptr(&active_state->compression_buffer), | 1094 | if ((r = sshbuf_put(state->outgoing_packet, |
905 | buffer_len(&active_state->compression_buffer)); | 1095 | "\0\0\0\0\0", 5)) != 0 || |
906 | DBG(debug("compression: raw %d compressed %d", len, | 1096 | (r = sshbuf_putb(state->outgoing_packet, |
907 | buffer_len(&active_state->outgoing_packet))); | 1097 | state->compression_buffer)) != 0) |
1098 | goto out; | ||
1099 | DBG(debug("compression: raw %d compressed %zd", len, | ||
1100 | sshbuf_len(state->outgoing_packet))); | ||
908 | } | 1101 | } |
909 | 1102 | ||
910 | /* sizeof (packet_len + pad_len + payload) */ | 1103 | /* sizeof (packet_len + pad_len + payload) */ |
911 | len = buffer_len(&active_state->outgoing_packet); | 1104 | len = sshbuf_len(state->outgoing_packet); |
912 | 1105 | ||
913 | /* | 1106 | /* |
914 | * calc size of padding, alloc space, get random data, | 1107 | * calc size of padding, alloc space, get random data, |
@@ -918,139 +1111,145 @@ packet_send2_wrapped(void) | |||
918 | padlen = block_size - (len % block_size); | 1111 | padlen = block_size - (len % block_size); |
919 | if (padlen < 4) | 1112 | if (padlen < 4) |
920 | padlen += block_size; | 1113 | padlen += block_size; |
921 | if (active_state->extra_pad) { | 1114 | if (state->extra_pad) { |
922 | /* will wrap if extra_pad+padlen > 255 */ | 1115 | /* will wrap if extra_pad+padlen > 255 */ |
923 | active_state->extra_pad = | 1116 | state->extra_pad = |
924 | roundup(active_state->extra_pad, block_size); | 1117 | roundup(state->extra_pad, block_size); |
925 | pad = active_state->extra_pad - | 1118 | pad = state->extra_pad - |
926 | ((len + padlen) % active_state->extra_pad); | 1119 | ((len + padlen) % state->extra_pad); |
927 | DBG(debug3("%s: adding %d (len %d padlen %d extra_pad %d)", | 1120 | DBG(debug3("%s: adding %d (len %d padlen %d extra_pad %d)", |
928 | __func__, pad, len, padlen, active_state->extra_pad)); | 1121 | __func__, pad, len, padlen, state->extra_pad)); |
929 | padlen += pad; | 1122 | padlen += pad; |
930 | active_state->extra_pad = 0; | 1123 | state->extra_pad = 0; |
931 | } | 1124 | } |
932 | cp = buffer_append_space(&active_state->outgoing_packet, padlen); | 1125 | if ((r = sshbuf_reserve(state->outgoing_packet, padlen, &cp)) != 0) |
933 | if (enc && !active_state->send_context.plaintext) { | 1126 | goto out; |
1127 | if (enc && !state->send_context.plaintext) { | ||
934 | /* random padding */ | 1128 | /* random padding */ |
935 | for (i = 0; i < padlen; i++) { | 1129 | arc4random_buf(cp, padlen); |
936 | if (i % 4 == 0) | ||
937 | rnd = arc4random(); | ||
938 | cp[i] = rnd & 0xff; | ||
939 | rnd >>= 8; | ||
940 | } | ||
941 | } else { | 1130 | } else { |
942 | /* clear padding */ | 1131 | /* clear padding */ |
943 | explicit_bzero(cp, padlen); | 1132 | explicit_bzero(cp, padlen); |
944 | } | 1133 | } |
945 | /* sizeof (packet_len + pad_len + payload + padding) */ | 1134 | /* sizeof (packet_len + pad_len + payload + padding) */ |
946 | len = buffer_len(&active_state->outgoing_packet); | 1135 | len = sshbuf_len(state->outgoing_packet); |
947 | cp = buffer_ptr(&active_state->outgoing_packet); | 1136 | cp = sshbuf_mutable_ptr(state->outgoing_packet); |
1137 | if (cp == NULL) { | ||
1138 | r = SSH_ERR_INTERNAL_ERROR; | ||
1139 | goto out; | ||
1140 | } | ||
948 | /* packet_length includes payload, padding and padding length field */ | 1141 | /* packet_length includes payload, padding and padding length field */ |
949 | put_u32(cp, len - 4); | 1142 | POKE_U32(cp, len - 4); |
950 | cp[4] = padlen; | 1143 | cp[4] = padlen; |
951 | DBG(debug("send: len %d (includes padlen %d, aadlen %d)", | 1144 | DBG(debug("send: len %d (includes padlen %d, aadlen %d)", |
952 | len, padlen, aadlen)); | 1145 | len, padlen, aadlen)); |
953 | 1146 | ||
954 | /* compute MAC over seqnr and packet(length fields, payload, padding) */ | 1147 | /* compute MAC over seqnr and packet(length fields, payload, padding) */ |
955 | if (mac && mac->enabled && !mac->etm) { | 1148 | if (mac && mac->enabled && !mac->etm) { |
956 | macbuf = mac_compute(mac, active_state->p_send.seqnr, | 1149 | if ((r = mac_compute(mac, state->p_send.seqnr, |
957 | buffer_ptr(&active_state->outgoing_packet), len); | 1150 | sshbuf_ptr(state->outgoing_packet), len, |
958 | DBG(debug("done calc MAC out #%d", active_state->p_send.seqnr)); | 1151 | macbuf, sizeof(macbuf))) != 0) |
1152 | goto out; | ||
1153 | DBG(debug("done calc MAC out #%d", state->p_send.seqnr)); | ||
959 | } | 1154 | } |
960 | /* encrypt packet and append to output buffer. */ | 1155 | /* encrypt packet and append to output buffer. */ |
961 | cp = buffer_append_space(&active_state->output, len + authlen); | 1156 | if ((r = sshbuf_reserve(state->output, |
962 | if (cipher_crypt(&active_state->send_context, active_state->p_send.seqnr, | 1157 | sshbuf_len(state->outgoing_packet) + authlen, &cp)) != 0) |
963 | cp, buffer_ptr(&active_state->outgoing_packet), | 1158 | goto out; |
964 | len - aadlen, aadlen, authlen) != 0) | 1159 | if ((r = cipher_crypt(&state->send_context, state->p_send.seqnr, cp, |
965 | fatal("%s: cipher_crypt failed", __func__); | 1160 | sshbuf_ptr(state->outgoing_packet), |
1161 | len - aadlen, aadlen, authlen)) != 0) | ||
1162 | goto out; | ||
966 | /* append unencrypted MAC */ | 1163 | /* append unencrypted MAC */ |
967 | if (mac && mac->enabled) { | 1164 | if (mac && mac->enabled) { |
968 | if (mac->etm) { | 1165 | if (mac->etm) { |
969 | /* EtM: compute mac over aadlen + cipher text */ | 1166 | /* EtM: compute mac over aadlen + cipher text */ |
970 | macbuf = mac_compute(mac, | 1167 | if ((r = mac_compute(mac, state->p_send.seqnr, |
971 | active_state->p_send.seqnr, cp, len); | 1168 | cp, len, macbuf, sizeof(macbuf))) != 0) |
1169 | goto out; | ||
972 | DBG(debug("done calc MAC(EtM) out #%d", | 1170 | DBG(debug("done calc MAC(EtM) out #%d", |
973 | active_state->p_send.seqnr)); | 1171 | state->p_send.seqnr)); |
974 | } | 1172 | } |
975 | buffer_append(&active_state->output, macbuf, mac->mac_len); | 1173 | if ((r = sshbuf_put(state->output, macbuf, mac->mac_len)) != 0) |
1174 | goto out; | ||
976 | } | 1175 | } |
977 | #ifdef PACKET_DEBUG | 1176 | #ifdef PACKET_DEBUG |
978 | fprintf(stderr, "encrypted: "); | 1177 | fprintf(stderr, "encrypted: "); |
979 | buffer_dump(&active_state->output); | 1178 | sshbuf_dump(state->output, stderr); |
980 | #endif | 1179 | #endif |
981 | /* increment sequence number for outgoing packets */ | 1180 | /* increment sequence number for outgoing packets */ |
982 | if (++active_state->p_send.seqnr == 0) | 1181 | if (++state->p_send.seqnr == 0) |
983 | logit("outgoing seqnr wraps around"); | 1182 | logit("outgoing seqnr wraps around"); |
984 | if (++active_state->p_send.packets == 0) | 1183 | if (++state->p_send.packets == 0) |
985 | if (!(datafellows & SSH_BUG_NOREKEY)) | 1184 | if (!(ssh->compat & SSH_BUG_NOREKEY)) |
986 | fatal("XXX too many packets with same key"); | 1185 | return SSH_ERR_NEED_REKEY; |
987 | active_state->p_send.blocks += len / block_size; | 1186 | state->p_send.blocks += len / block_size; |
988 | active_state->p_send.bytes += len; | 1187 | state->p_send.bytes += len; |
989 | buffer_clear(&active_state->outgoing_packet); | 1188 | sshbuf_reset(state->outgoing_packet); |
990 | 1189 | ||
991 | if (type == SSH2_MSG_NEWKEYS) | 1190 | if (type == SSH2_MSG_NEWKEYS) |
992 | set_newkeys(MODE_OUT); | 1191 | r = ssh_set_newkeys(ssh, MODE_OUT); |
993 | else if (type == SSH2_MSG_USERAUTH_SUCCESS && active_state->server_side) | 1192 | else if (type == SSH2_MSG_USERAUTH_SUCCESS && state->server_side) |
994 | packet_enable_delayed_compress(); | 1193 | r = ssh_packet_enable_delayed_compress(ssh); |
1194 | else | ||
1195 | r = 0; | ||
1196 | out: | ||
1197 | return r; | ||
995 | } | 1198 | } |
996 | 1199 | ||
997 | static void | 1200 | int |
998 | packet_send2(void) | 1201 | ssh_packet_send2(struct ssh *ssh) |
999 | { | 1202 | { |
1203 | struct session_state *state = ssh->state; | ||
1000 | struct packet *p; | 1204 | struct packet *p; |
1001 | u_char type, *cp; | 1205 | u_char type; |
1206 | int r; | ||
1002 | 1207 | ||
1003 | cp = buffer_ptr(&active_state->outgoing_packet); | 1208 | type = sshbuf_ptr(state->outgoing_packet)[5]; |
1004 | type = cp[5]; | ||
1005 | 1209 | ||
1006 | /* during rekeying we can only send key exchange messages */ | 1210 | /* during rekeying we can only send key exchange messages */ |
1007 | if (active_state->rekeying) { | 1211 | if (state->rekeying) { |
1008 | if ((type < SSH2_MSG_TRANSPORT_MIN) || | 1212 | if ((type < SSH2_MSG_TRANSPORT_MIN) || |
1009 | (type > SSH2_MSG_TRANSPORT_MAX) || | 1213 | (type > SSH2_MSG_TRANSPORT_MAX) || |
1010 | (type == SSH2_MSG_SERVICE_REQUEST) || | 1214 | (type == SSH2_MSG_SERVICE_REQUEST) || |
1011 | (type == SSH2_MSG_SERVICE_ACCEPT)) { | 1215 | (type == SSH2_MSG_SERVICE_ACCEPT)) { |
1012 | debug("enqueue packet: %u", type); | 1216 | debug("enqueue packet: %u", type); |
1013 | p = xcalloc(1, sizeof(*p)); | 1217 | p = calloc(1, sizeof(*p)); |
1218 | if (p == NULL) | ||
1219 | return SSH_ERR_ALLOC_FAIL; | ||
1014 | p->type = type; | 1220 | p->type = type; |
1015 | memcpy(&p->payload, &active_state->outgoing_packet, | 1221 | p->payload = state->outgoing_packet; |
1016 | sizeof(Buffer)); | 1222 | TAILQ_INSERT_TAIL(&state->outgoing, p, next); |
1017 | buffer_init(&active_state->outgoing_packet); | 1223 | state->outgoing_packet = sshbuf_new(); |
1018 | TAILQ_INSERT_TAIL(&active_state->outgoing, p, next); | 1224 | if (state->outgoing_packet == NULL) |
1019 | return; | 1225 | return SSH_ERR_ALLOC_FAIL; |
1226 | return 0; | ||
1020 | } | 1227 | } |
1021 | } | 1228 | } |
1022 | 1229 | ||
1023 | /* rekeying starts with sending KEXINIT */ | 1230 | /* rekeying starts with sending KEXINIT */ |
1024 | if (type == SSH2_MSG_KEXINIT) | 1231 | if (type == SSH2_MSG_KEXINIT) |
1025 | active_state->rekeying = 1; | 1232 | state->rekeying = 1; |
1026 | 1233 | ||
1027 | packet_send2_wrapped(); | 1234 | if ((r = ssh_packet_send2_wrapped(ssh)) != 0) |
1235 | return r; | ||
1028 | 1236 | ||
1029 | /* after a NEWKEYS message we can send the complete queue */ | 1237 | /* after a NEWKEYS message we can send the complete queue */ |
1030 | if (type == SSH2_MSG_NEWKEYS) { | 1238 | if (type == SSH2_MSG_NEWKEYS) { |
1031 | active_state->rekeying = 0; | 1239 | state->rekeying = 0; |
1032 | active_state->rekey_time = monotime(); | 1240 | state->rekey_time = monotime(); |
1033 | while ((p = TAILQ_FIRST(&active_state->outgoing))) { | 1241 | while ((p = TAILQ_FIRST(&state->outgoing))) { |
1034 | type = p->type; | 1242 | type = p->type; |
1035 | debug("dequeue packet: %u", type); | 1243 | debug("dequeue packet: %u", type); |
1036 | buffer_free(&active_state->outgoing_packet); | 1244 | sshbuf_free(state->outgoing_packet); |
1037 | memcpy(&active_state->outgoing_packet, &p->payload, | 1245 | state->outgoing_packet = p->payload; |
1038 | sizeof(Buffer)); | 1246 | TAILQ_REMOVE(&state->outgoing, p, next); |
1039 | TAILQ_REMOVE(&active_state->outgoing, p, next); | ||
1040 | free(p); | 1247 | free(p); |
1041 | packet_send2_wrapped(); | 1248 | if ((r = ssh_packet_send2_wrapped(ssh)) != 0) |
1249 | return r; | ||
1042 | } | 1250 | } |
1043 | } | 1251 | } |
1044 | } | 1252 | return 0; |
1045 | |||
1046 | void | ||
1047 | packet_send(void) | ||
1048 | { | ||
1049 | if (compat20) | ||
1050 | packet_send2(); | ||
1051 | else | ||
1052 | packet_send1(); | ||
1053 | DBG(debug("packet_send done")); | ||
1054 | } | 1253 | } |
1055 | 1254 | ||
1056 | /* | 1255 | /* |
@@ -1060,95 +1259,106 @@ packet_send(void) | |||
1060 | */ | 1259 | */ |
1061 | 1260 | ||
1062 | int | 1261 | int |
1063 | packet_read_seqnr(u_int32_t *seqnr_p) | 1262 | ssh_packet_read_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) |
1064 | { | 1263 | { |
1065 | int type, len, ret, cont, ms_remain = 0; | 1264 | struct session_state *state = ssh->state; |
1265 | int len, r, ms_remain, cont; | ||
1066 | fd_set *setp; | 1266 | fd_set *setp; |
1067 | char buf[8192]; | 1267 | char buf[8192]; |
1068 | struct timeval timeout, start, *timeoutp = NULL; | 1268 | struct timeval timeout, start, *timeoutp = NULL; |
1069 | 1269 | ||
1070 | DBG(debug("packet_read()")); | 1270 | DBG(debug("packet_read()")); |
1071 | 1271 | ||
1072 | setp = (fd_set *)xcalloc(howmany(active_state->connection_in + 1, | 1272 | setp = (fd_set *)calloc(howmany(state->connection_in + 1, |
1073 | NFDBITS), sizeof(fd_mask)); | 1273 | NFDBITS), sizeof(fd_mask)); |
1274 | if (setp == NULL) | ||
1275 | return SSH_ERR_ALLOC_FAIL; | ||
1074 | 1276 | ||
1075 | /* Since we are blocking, ensure that all written packets have been sent. */ | 1277 | /* |
1076 | packet_write_wait(); | 1278 | * Since we are blocking, ensure that all written packets have |
1279 | * been sent. | ||
1280 | */ | ||
1281 | if ((r = ssh_packet_write_wait(ssh)) != 0) | ||
1282 | return r; | ||
1077 | 1283 | ||
1078 | /* Stay in the loop until we have received a complete packet. */ | 1284 | /* Stay in the loop until we have received a complete packet. */ |
1079 | for (;;) { | 1285 | for (;;) { |
1080 | /* Try to read a packet from the buffer. */ | 1286 | /* Try to read a packet from the buffer. */ |
1081 | type = packet_read_poll_seqnr(seqnr_p); | 1287 | r = ssh_packet_read_poll_seqnr(ssh, typep, seqnr_p); |
1288 | if (r != 0) | ||
1289 | break; | ||
1082 | if (!compat20 && ( | 1290 | if (!compat20 && ( |
1083 | type == SSH_SMSG_SUCCESS | 1291 | *typep == SSH_SMSG_SUCCESS |
1084 | || type == SSH_SMSG_FAILURE | 1292 | || *typep == SSH_SMSG_FAILURE |
1085 | || type == SSH_CMSG_EOF | 1293 | || *typep == SSH_CMSG_EOF |
1086 | || type == SSH_CMSG_EXIT_CONFIRMATION)) | 1294 | || *typep == SSH_CMSG_EXIT_CONFIRMATION)) |
1087 | packet_check_eom(); | 1295 | if ((r = sshpkt_get_end(ssh)) != 0) |
1296 | break; | ||
1088 | /* If we got a packet, return it. */ | 1297 | /* If we got a packet, return it. */ |
1089 | if (type != SSH_MSG_NONE) { | 1298 | if (*typep != SSH_MSG_NONE) |
1090 | free(setp); | 1299 | break; |
1091 | return type; | ||
1092 | } | ||
1093 | /* | 1300 | /* |
1094 | * Otherwise, wait for some data to arrive, add it to the | 1301 | * Otherwise, wait for some data to arrive, add it to the |
1095 | * buffer, and try again. | 1302 | * buffer, and try again. |
1096 | */ | 1303 | */ |
1097 | memset(setp, 0, howmany(active_state->connection_in + 1, | 1304 | memset(setp, 0, howmany(state->connection_in + 1, |
1098 | NFDBITS) * sizeof(fd_mask)); | 1305 | NFDBITS) * sizeof(fd_mask)); |
1099 | FD_SET(active_state->connection_in, setp); | 1306 | FD_SET(state->connection_in, setp); |
1100 | 1307 | ||
1101 | if (active_state->packet_timeout_ms > 0) { | 1308 | if (state->packet_timeout_ms > 0) { |
1102 | ms_remain = active_state->packet_timeout_ms; | 1309 | ms_remain = state->packet_timeout_ms; |
1103 | timeoutp = &timeout; | 1310 | timeoutp = &timeout; |
1104 | } | 1311 | } |
1105 | /* Wait for some data to arrive. */ | 1312 | /* Wait for some data to arrive. */ |
1106 | for (;;) { | 1313 | for (;;) { |
1107 | if (active_state->packet_timeout_ms != -1) { | 1314 | if (state->packet_timeout_ms != -1) { |
1108 | ms_to_timeval(&timeout, ms_remain); | 1315 | ms_to_timeval(&timeout, ms_remain); |
1109 | gettimeofday(&start, NULL); | 1316 | gettimeofday(&start, NULL); |
1110 | } | 1317 | } |
1111 | if ((ret = select(active_state->connection_in + 1, setp, | 1318 | if ((r = select(state->connection_in + 1, setp, |
1112 | NULL, NULL, timeoutp)) >= 0) | 1319 | NULL, NULL, timeoutp)) >= 0) |
1113 | break; | 1320 | break; |
1114 | if (errno != EAGAIN && errno != EINTR && | 1321 | if (errno != EAGAIN && errno != EINTR && |
1115 | errno != EWOULDBLOCK) | 1322 | errno != EWOULDBLOCK) |
1116 | break; | 1323 | break; |
1117 | if (active_state->packet_timeout_ms == -1) | 1324 | if (state->packet_timeout_ms == -1) |
1118 | continue; | 1325 | continue; |
1119 | ms_subtract_diff(&start, &ms_remain); | 1326 | ms_subtract_diff(&start, &ms_remain); |
1120 | if (ms_remain <= 0) { | 1327 | if (ms_remain <= 0) { |
1121 | ret = 0; | 1328 | r = 0; |
1122 | break; | 1329 | break; |
1123 | } | 1330 | } |
1124 | } | 1331 | } |
1125 | if (ret == 0) { | 1332 | if (r == 0) |
1126 | logit("Connection to %.200s timed out while " | 1333 | return SSH_ERR_CONN_TIMEOUT; |
1127 | "waiting to read", get_remote_ipaddr()); | ||
1128 | cleanup_exit(255); | ||
1129 | } | ||
1130 | /* Read data from the socket. */ | 1334 | /* Read data from the socket. */ |
1131 | do { | 1335 | do { |
1132 | cont = 0; | 1336 | cont = 0; |
1133 | len = roaming_read(active_state->connection_in, buf, | 1337 | len = roaming_read(state->connection_in, buf, |
1134 | sizeof(buf), &cont); | 1338 | sizeof(buf), &cont); |
1135 | } while (len == 0 && cont); | 1339 | } while (len == 0 && cont); |
1136 | if (len == 0) { | 1340 | if (len == 0) |
1137 | logit("Connection closed by %.200s", get_remote_ipaddr()); | 1341 | return SSH_ERR_CONN_CLOSED; |
1138 | cleanup_exit(255); | ||
1139 | } | ||
1140 | if (len < 0) | 1342 | if (len < 0) |
1141 | fatal("Read from socket failed: %.100s", strerror(errno)); | 1343 | return SSH_ERR_SYSTEM_ERROR; |
1344 | |||
1142 | /* Append it to the buffer. */ | 1345 | /* Append it to the buffer. */ |
1143 | packet_process_incoming(buf, len); | 1346 | if ((r = ssh_packet_process_incoming(ssh, buf, len)) != 0) |
1347 | return r; | ||
1144 | } | 1348 | } |
1145 | /* NOTREACHED */ | 1349 | free(setp); |
1350 | return r; | ||
1146 | } | 1351 | } |
1147 | 1352 | ||
1148 | int | 1353 | int |
1149 | packet_read(void) | 1354 | ssh_packet_read(struct ssh *ssh) |
1150 | { | 1355 | { |
1151 | return packet_read_seqnr(NULL); | 1356 | u_char type; |
1357 | int r; | ||
1358 | |||
1359 | if ((r = ssh_packet_read_seqnr(ssh, &type, NULL)) != 0) | ||
1360 | fatal("%s: %s", __func__, ssh_err(r)); | ||
1361 | return type; | ||
1152 | } | 1362 | } |
1153 | 1363 | ||
1154 | /* | 1364 | /* |
@@ -1156,15 +1366,22 @@ packet_read(void) | |||
1156 | * that given, and gives a fatal error and exits if there is a mismatch. | 1366 | * that given, and gives a fatal error and exits if there is a mismatch. |
1157 | */ | 1367 | */ |
1158 | 1368 | ||
1159 | void | 1369 | int |
1160 | packet_read_expect(int expected_type) | 1370 | ssh_packet_read_expect(struct ssh *ssh, u_int expected_type) |
1161 | { | 1371 | { |
1162 | int type; | 1372 | int r; |
1373 | u_char type; | ||
1163 | 1374 | ||
1164 | type = packet_read(); | 1375 | if ((r = ssh_packet_read_seqnr(ssh, &type, NULL)) != 0) |
1165 | if (type != expected_type) | 1376 | return r; |
1166 | packet_disconnect("Protocol error: expected packet type %d, got %d", | 1377 | if (type != expected_type) { |
1167 | expected_type, type); | 1378 | if ((r = sshpkt_disconnect(ssh, |
1379 | "Protocol error: expected packet type %d, got %d", | ||
1380 | expected_type, type)) != 0) | ||
1381 | return r; | ||
1382 | return SSH_ERR_PROTOCOL_ERROR; | ||
1383 | } | ||
1384 | return 0; | ||
1168 | } | 1385 | } |
1169 | 1386 | ||
1170 | /* Checks if a full packet is available in the data received so far via | 1387 | /* Checks if a full packet is available in the data received so far via |
@@ -1176,115 +1393,165 @@ packet_read_expect(int expected_type) | |||
1176 | * to higher levels. | 1393 | * to higher levels. |
1177 | */ | 1394 | */ |
1178 | 1395 | ||
1179 | static int | 1396 | int |
1180 | packet_read_poll1(void) | 1397 | ssh_packet_read_poll1(struct ssh *ssh, u_char *typep) |
1181 | { | 1398 | { |
1399 | struct session_state *state = ssh->state; | ||
1182 | u_int len, padded_len; | 1400 | u_int len, padded_len; |
1183 | u_char *cp, type; | 1401 | const char *emsg; |
1402 | const u_char *cp; | ||
1403 | u_char *p; | ||
1184 | u_int checksum, stored_checksum; | 1404 | u_int checksum, stored_checksum; |
1405 | int r; | ||
1406 | |||
1407 | *typep = SSH_MSG_NONE; | ||
1185 | 1408 | ||
1186 | /* Check if input size is less than minimum packet size. */ | 1409 | /* Check if input size is less than minimum packet size. */ |
1187 | if (buffer_len(&active_state->input) < 4 + 8) | 1410 | if (sshbuf_len(state->input) < 4 + 8) |
1188 | return SSH_MSG_NONE; | 1411 | return 0; |
1189 | /* Get length of incoming packet. */ | 1412 | /* Get length of incoming packet. */ |
1190 | cp = buffer_ptr(&active_state->input); | 1413 | len = PEEK_U32(sshbuf_ptr(state->input)); |
1191 | len = get_u32(cp); | 1414 | if (len < 1 + 2 + 2 || len > 256 * 1024) { |
1192 | if (len < 1 + 2 + 2 || len > 256 * 1024) | 1415 | if ((r = sshpkt_disconnect(ssh, "Bad packet length %u", |
1193 | packet_disconnect("Bad packet length %u.", len); | 1416 | len)) != 0) |
1417 | return r; | ||
1418 | return SSH_ERR_CONN_CORRUPT; | ||
1419 | } | ||
1194 | padded_len = (len + 8) & ~7; | 1420 | padded_len = (len + 8) & ~7; |
1195 | 1421 | ||
1196 | /* Check if the packet has been entirely received. */ | 1422 | /* Check if the packet has been entirely received. */ |
1197 | if (buffer_len(&active_state->input) < 4 + padded_len) | 1423 | if (sshbuf_len(state->input) < 4 + padded_len) |
1198 | return SSH_MSG_NONE; | 1424 | return 0; |
1199 | 1425 | ||
1200 | /* The entire packet is in buffer. */ | 1426 | /* The entire packet is in buffer. */ |
1201 | 1427 | ||
1202 | /* Consume packet length. */ | 1428 | /* Consume packet length. */ |
1203 | buffer_consume(&active_state->input, 4); | 1429 | if ((r = sshbuf_consume(state->input, 4)) != 0) |
1430 | goto out; | ||
1204 | 1431 | ||
1205 | /* | 1432 | /* |
1206 | * Cryptographic attack detector for ssh | 1433 | * Cryptographic attack detector for ssh |
1207 | * (C)1998 CORE-SDI, Buenos Aires Argentina | 1434 | * (C)1998 CORE-SDI, Buenos Aires Argentina |
1208 | * Ariel Futoransky(futo@core-sdi.com) | 1435 | * Ariel Futoransky(futo@core-sdi.com) |
1209 | */ | 1436 | */ |
1210 | if (!active_state->receive_context.plaintext) { | 1437 | if (!state->receive_context.plaintext) { |
1211 | switch (detect_attack(buffer_ptr(&active_state->input), | 1438 | emsg = NULL; |
1212 | padded_len)) { | 1439 | switch (detect_attack(&state->deattack, |
1440 | sshbuf_ptr(state->input), padded_len)) { | ||
1441 | case DEATTACK_OK: | ||
1442 | break; | ||
1213 | case DEATTACK_DETECTED: | 1443 | case DEATTACK_DETECTED: |
1214 | packet_disconnect("crc32 compensation attack: " | 1444 | emsg = "crc32 compensation attack detected"; |
1215 | "network attack detected"); | 1445 | break; |
1216 | case DEATTACK_DOS_DETECTED: | 1446 | case DEATTACK_DOS_DETECTED: |
1217 | packet_disconnect("deattack denial of " | 1447 | emsg = "deattack denial of service detected"; |
1218 | "service detected"); | 1448 | break; |
1449 | default: | ||
1450 | emsg = "deattack error"; | ||
1451 | break; | ||
1452 | } | ||
1453 | if (emsg != NULL) { | ||
1454 | error("%s", emsg); | ||
1455 | if ((r = sshpkt_disconnect(ssh, "%s", emsg)) != 0 || | ||
1456 | (r = ssh_packet_write_wait(ssh)) != 0) | ||
1457 | return r; | ||
1458 | return SSH_ERR_CONN_CORRUPT; | ||
1219 | } | 1459 | } |
1220 | } | 1460 | } |
1221 | 1461 | ||
1222 | /* Decrypt data to incoming_packet. */ | 1462 | /* Decrypt data to incoming_packet. */ |
1223 | buffer_clear(&active_state->incoming_packet); | 1463 | sshbuf_reset(state->incoming_packet); |
1224 | cp = buffer_append_space(&active_state->incoming_packet, padded_len); | 1464 | if ((r = sshbuf_reserve(state->incoming_packet, padded_len, &p)) != 0) |
1225 | if (cipher_crypt(&active_state->receive_context, 0, cp, | 1465 | goto out; |
1226 | buffer_ptr(&active_state->input), padded_len, 0, 0) != 0) | 1466 | if ((r = cipher_crypt(&state->receive_context, 0, p, |
1227 | fatal("%s: cipher_crypt failed", __func__); | 1467 | sshbuf_ptr(state->input), padded_len, 0, 0)) != 0) |
1468 | goto out; | ||
1228 | 1469 | ||
1229 | buffer_consume(&active_state->input, padded_len); | 1470 | if ((r = sshbuf_consume(state->input, padded_len)) != 0) |
1471 | goto out; | ||
1230 | 1472 | ||
1231 | #ifdef PACKET_DEBUG | 1473 | #ifdef PACKET_DEBUG |
1232 | fprintf(stderr, "read_poll plain: "); | 1474 | fprintf(stderr, "read_poll plain: "); |
1233 | buffer_dump(&active_state->incoming_packet); | 1475 | sshbuf_dump(state->incoming_packet, stderr); |
1234 | #endif | 1476 | #endif |
1235 | 1477 | ||
1236 | /* Compute packet checksum. */ | 1478 | /* Compute packet checksum. */ |
1237 | checksum = ssh_crc32(buffer_ptr(&active_state->incoming_packet), | 1479 | checksum = ssh_crc32(sshbuf_ptr(state->incoming_packet), |
1238 | buffer_len(&active_state->incoming_packet) - 4); | 1480 | sshbuf_len(state->incoming_packet) - 4); |
1239 | 1481 | ||
1240 | /* Skip padding. */ | 1482 | /* Skip padding. */ |
1241 | buffer_consume(&active_state->incoming_packet, 8 - len % 8); | 1483 | if ((r = sshbuf_consume(state->incoming_packet, 8 - len % 8)) != 0) |
1484 | goto out; | ||
1242 | 1485 | ||
1243 | /* Test check bytes. */ | 1486 | /* Test check bytes. */ |
1244 | if (len != buffer_len(&active_state->incoming_packet)) | 1487 | if (len != sshbuf_len(state->incoming_packet)) { |
1245 | packet_disconnect("packet_read_poll1: len %d != buffer_len %d.", | 1488 | error("%s: len %d != sshbuf_len %zd", __func__, |
1246 | len, buffer_len(&active_state->incoming_packet)); | 1489 | len, sshbuf_len(state->incoming_packet)); |
1247 | 1490 | if ((r = sshpkt_disconnect(ssh, "invalid packet length")) != 0 || | |
1248 | cp = (u_char *)buffer_ptr(&active_state->incoming_packet) + len - 4; | 1491 | (r = ssh_packet_write_wait(ssh)) != 0) |
1249 | stored_checksum = get_u32(cp); | 1492 | return r; |
1250 | if (checksum != stored_checksum) | 1493 | return SSH_ERR_CONN_CORRUPT; |
1251 | packet_disconnect("Corrupted check bytes on input."); | 1494 | } |
1252 | buffer_consume_end(&active_state->incoming_packet, 4); | 1495 | |
1253 | 1496 | cp = sshbuf_ptr(state->incoming_packet) + len - 4; | |
1254 | if (active_state->packet_compression) { | 1497 | stored_checksum = PEEK_U32(cp); |
1255 | buffer_clear(&active_state->compression_buffer); | 1498 | if (checksum != stored_checksum) { |
1256 | buffer_uncompress(&active_state->incoming_packet, | 1499 | error("Corrupted check bytes on input"); |
1257 | &active_state->compression_buffer); | 1500 | if ((r = sshpkt_disconnect(ssh, "connection corrupted")) != 0 || |
1258 | buffer_clear(&active_state->incoming_packet); | 1501 | (r = ssh_packet_write_wait(ssh)) != 0) |
1259 | buffer_append(&active_state->incoming_packet, | 1502 | return r; |
1260 | buffer_ptr(&active_state->compression_buffer), | 1503 | return SSH_ERR_CONN_CORRUPT; |
1261 | buffer_len(&active_state->compression_buffer)); | 1504 | } |
1262 | } | 1505 | if ((r = sshbuf_consume_end(state->incoming_packet, 4)) < 0) |
1263 | active_state->p_read.packets++; | 1506 | goto out; |
1264 | active_state->p_read.bytes += padded_len + 4; | 1507 | |
1265 | type = buffer_get_char(&active_state->incoming_packet); | 1508 | if (state->packet_compression) { |
1266 | if (type < SSH_MSG_MIN || type > SSH_MSG_MAX) | 1509 | sshbuf_reset(state->compression_buffer); |
1267 | packet_disconnect("Invalid ssh1 packet type: %d", type); | 1510 | if ((r = uncompress_buffer(ssh, state->incoming_packet, |
1268 | return type; | 1511 | state->compression_buffer)) != 0) |
1512 | goto out; | ||
1513 | sshbuf_reset(state->incoming_packet); | ||
1514 | if ((r = sshbuf_putb(state->incoming_packet, | ||
1515 | state->compression_buffer)) != 0) | ||
1516 | goto out; | ||
1517 | } | ||
1518 | state->p_read.packets++; | ||
1519 | state->p_read.bytes += padded_len + 4; | ||
1520 | if ((r = sshbuf_get_u8(state->incoming_packet, typep)) != 0) | ||
1521 | goto out; | ||
1522 | if (*typep < SSH_MSG_MIN || *typep > SSH_MSG_MAX) { | ||
1523 | error("Invalid ssh1 packet type: %d", *typep); | ||
1524 | if ((r = sshpkt_disconnect(ssh, "invalid packet type")) != 0 || | ||
1525 | (r = ssh_packet_write_wait(ssh)) != 0) | ||
1526 | return r; | ||
1527 | return SSH_ERR_PROTOCOL_ERROR; | ||
1528 | } | ||
1529 | r = 0; | ||
1530 | out: | ||
1531 | return r; | ||
1269 | } | 1532 | } |
1270 | 1533 | ||
1271 | static int | 1534 | int |
1272 | packet_read_poll2(u_int32_t *seqnr_p) | 1535 | ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) |
1273 | { | 1536 | { |
1537 | struct session_state *state = ssh->state; | ||
1274 | u_int padlen, need; | 1538 | u_int padlen, need; |
1275 | u_char *macbuf = NULL, *cp, type; | 1539 | u_char *cp, macbuf[SSH_DIGEST_MAX_LENGTH]; |
1276 | u_int maclen, authlen = 0, aadlen = 0, block_size; | 1540 | u_int maclen, aadlen = 0, authlen = 0, block_size; |
1277 | Enc *enc = NULL; | 1541 | struct sshenc *enc = NULL; |
1278 | Mac *mac = NULL; | 1542 | struct sshmac *mac = NULL; |
1279 | Comp *comp = NULL; | 1543 | struct sshcomp *comp = NULL; |
1280 | 1544 | int r; | |
1281 | if (active_state->packet_discard) | 1545 | |
1282 | return SSH_MSG_NONE; | 1546 | *typep = SSH_MSG_NONE; |
1283 | 1547 | ||
1284 | if (active_state->newkeys[MODE_IN] != NULL) { | 1548 | if (state->packet_discard) |
1285 | enc = &active_state->newkeys[MODE_IN]->enc; | 1549 | return 0; |
1286 | mac = &active_state->newkeys[MODE_IN]->mac; | 1550 | |
1287 | comp = &active_state->newkeys[MODE_IN]->comp; | 1551 | if (state->newkeys[MODE_IN] != NULL) { |
1552 | enc = &state->newkeys[MODE_IN]->enc; | ||
1553 | mac = &state->newkeys[MODE_IN]->mac; | ||
1554 | comp = &state->newkeys[MODE_IN]->comp; | ||
1288 | /* disable mac for authenticated encryption */ | 1555 | /* disable mac for authenticated encryption */ |
1289 | if ((authlen = cipher_authlen(enc->cipher)) != 0) | 1556 | if ((authlen = cipher_authlen(enc->cipher)) != 0) |
1290 | mac = NULL; | 1557 | mac = NULL; |
@@ -1293,69 +1560,71 @@ packet_read_poll2(u_int32_t *seqnr_p) | |||
1293 | block_size = enc ? enc->block_size : 8; | 1560 | block_size = enc ? enc->block_size : 8; |
1294 | aadlen = (mac && mac->enabled && mac->etm) || authlen ? 4 : 0; | 1561 | aadlen = (mac && mac->enabled && mac->etm) || authlen ? 4 : 0; |
1295 | 1562 | ||
1296 | if (aadlen && active_state->packlen == 0) { | 1563 | if (aadlen && state->packlen == 0) { |
1297 | if (cipher_get_length(&active_state->receive_context, | 1564 | if (cipher_get_length(&state->receive_context, |
1298 | &active_state->packlen, | 1565 | &state->packlen, state->p_read.seqnr, |
1299 | active_state->p_read.seqnr, | 1566 | sshbuf_ptr(state->input), sshbuf_len(state->input)) != 0) |
1300 | buffer_ptr(&active_state->input), | 1567 | return 0; |
1301 | buffer_len(&active_state->input)) != 0) | 1568 | if (state->packlen < 1 + 4 || |
1302 | return SSH_MSG_NONE; | 1569 | state->packlen > PACKET_MAX_SIZE) { |
1303 | if (active_state->packlen < 1 + 4 || | ||
1304 | active_state->packlen > PACKET_MAX_SIZE) { | ||
1305 | #ifdef PACKET_DEBUG | 1570 | #ifdef PACKET_DEBUG |
1306 | buffer_dump(&active_state->input); | 1571 | sshbuf_dump(state->input, stderr); |
1307 | #endif | 1572 | #endif |
1308 | logit("Bad packet length %u.", active_state->packlen); | 1573 | logit("Bad packet length %u.", state->packlen); |
1309 | packet_disconnect("Packet corrupt"); | 1574 | if ((r = sshpkt_disconnect(ssh, "Packet corrupt")) != 0) |
1575 | return r; | ||
1310 | } | 1576 | } |
1311 | buffer_clear(&active_state->incoming_packet); | 1577 | sshbuf_reset(state->incoming_packet); |
1312 | } else if (active_state->packlen == 0) { | 1578 | } else if (state->packlen == 0) { |
1313 | /* | 1579 | /* |
1314 | * check if input size is less than the cipher block size, | 1580 | * check if input size is less than the cipher block size, |
1315 | * decrypt first block and extract length of incoming packet | 1581 | * decrypt first block and extract length of incoming packet |
1316 | */ | 1582 | */ |
1317 | if (buffer_len(&active_state->input) < block_size) | 1583 | if (sshbuf_len(state->input) < block_size) |
1318 | return SSH_MSG_NONE; | 1584 | return 0; |
1319 | buffer_clear(&active_state->incoming_packet); | 1585 | sshbuf_reset(state->incoming_packet); |
1320 | cp = buffer_append_space(&active_state->incoming_packet, | 1586 | if ((r = sshbuf_reserve(state->incoming_packet, block_size, |
1321 | block_size); | 1587 | &cp)) != 0) |
1322 | if (cipher_crypt(&active_state->receive_context, | 1588 | goto out; |
1323 | active_state->p_read.seqnr, cp, | 1589 | if ((r = cipher_crypt(&state->receive_context, |
1324 | buffer_ptr(&active_state->input), block_size, 0, 0) != 0) | 1590 | state->p_send.seqnr, cp, sshbuf_ptr(state->input), |
1325 | fatal("Decryption integrity check failed"); | 1591 | block_size, 0, 0)) != 0) |
1326 | cp = buffer_ptr(&active_state->incoming_packet); | 1592 | goto out; |
1327 | active_state->packlen = get_u32(cp); | 1593 | state->packlen = PEEK_U32(sshbuf_ptr(state->incoming_packet)); |
1328 | if (active_state->packlen < 1 + 4 || | 1594 | if (state->packlen < 1 + 4 || |
1329 | active_state->packlen > PACKET_MAX_SIZE) { | 1595 | state->packlen > PACKET_MAX_SIZE) { |
1330 | #ifdef PACKET_DEBUG | 1596 | #ifdef PACKET_DEBUG |
1331 | buffer_dump(&active_state->incoming_packet); | 1597 | fprintf(stderr, "input: \n"); |
1598 | sshbuf_dump(state->input, stderr); | ||
1599 | fprintf(stderr, "incoming_packet: \n"); | ||
1600 | sshbuf_dump(state->incoming_packet, stderr); | ||
1332 | #endif | 1601 | #endif |
1333 | logit("Bad packet length %u.", active_state->packlen); | 1602 | logit("Bad packet length %u.", state->packlen); |
1334 | packet_start_discard(enc, mac, active_state->packlen, | 1603 | return ssh_packet_start_discard(ssh, enc, mac, |
1335 | PACKET_MAX_SIZE); | 1604 | state->packlen, PACKET_MAX_SIZE); |
1336 | return SSH_MSG_NONE; | ||
1337 | } | 1605 | } |
1338 | buffer_consume(&active_state->input, block_size); | 1606 | if ((r = sshbuf_consume(state->input, block_size)) != 0) |
1607 | goto out; | ||
1339 | } | 1608 | } |
1340 | DBG(debug("input: packet len %u", active_state->packlen+4)); | 1609 | DBG(debug("input: packet len %u", state->packlen+4)); |
1610 | |||
1341 | if (aadlen) { | 1611 | if (aadlen) { |
1342 | /* only the payload is encrypted */ | 1612 | /* only the payload is encrypted */ |
1343 | need = active_state->packlen; | 1613 | need = state->packlen; |
1344 | } else { | 1614 | } else { |
1345 | /* | 1615 | /* |
1346 | * the payload size and the payload are encrypted, but we | 1616 | * the payload size and the payload are encrypted, but we |
1347 | * have a partial packet of block_size bytes | 1617 | * have a partial packet of block_size bytes |
1348 | */ | 1618 | */ |
1349 | need = 4 + active_state->packlen - block_size; | 1619 | need = 4 + state->packlen - block_size; |
1350 | } | 1620 | } |
1351 | DBG(debug("partial packet: block %d, need %d, maclen %d, authlen %d," | 1621 | DBG(debug("partial packet: block %d, need %d, maclen %d, authlen %d," |
1352 | " aadlen %d", block_size, need, maclen, authlen, aadlen)); | 1622 | " aadlen %d", block_size, need, maclen, authlen, aadlen)); |
1353 | if (need % block_size != 0) { | 1623 | if (need % block_size != 0) { |
1354 | logit("padding error: need %d block %d mod %d", | 1624 | logit("padding error: need %d block %d mod %d", |
1355 | need, block_size, need % block_size); | 1625 | need, block_size, need % block_size); |
1356 | packet_start_discard(enc, mac, active_state->packlen, | 1626 | return ssh_packet_start_discard(ssh, enc, mac, |
1357 | PACKET_MAX_SIZE - block_size); | 1627 | state->packlen, PACKET_MAX_SIZE - block_size); |
1358 | return SSH_MSG_NONE; | ||
1359 | } | 1628 | } |
1360 | /* | 1629 | /* |
1361 | * check if the entire packet has been received and | 1630 | * check if the entire packet has been received and |
@@ -1365,167 +1634,197 @@ packet_read_poll2(u_int32_t *seqnr_p) | |||
1365 | * 'authlen' bytes of authentication tag or | 1634 | * 'authlen' bytes of authentication tag or |
1366 | * 'maclen' bytes of message authentication code. | 1635 | * 'maclen' bytes of message authentication code. |
1367 | */ | 1636 | */ |
1368 | if (buffer_len(&active_state->input) < aadlen + need + authlen + maclen) | 1637 | if (sshbuf_len(state->input) < aadlen + need + authlen + maclen) |
1369 | return SSH_MSG_NONE; | 1638 | return 0; |
1370 | #ifdef PACKET_DEBUG | 1639 | #ifdef PACKET_DEBUG |
1371 | fprintf(stderr, "read_poll enc/full: "); | 1640 | fprintf(stderr, "read_poll enc/full: "); |
1372 | buffer_dump(&active_state->input); | 1641 | sshbuf_dump(state->input, stderr); |
1373 | #endif | 1642 | #endif |
1374 | /* EtM: compute mac over encrypted input */ | 1643 | /* EtM: compute mac over encrypted input */ |
1375 | if (mac && mac->enabled && mac->etm) | 1644 | if (mac && mac->enabled && mac->etm) { |
1376 | macbuf = mac_compute(mac, active_state->p_read.seqnr, | 1645 | if ((r = mac_compute(mac, state->p_read.seqnr, |
1377 | buffer_ptr(&active_state->input), aadlen + need); | 1646 | sshbuf_ptr(state->input), aadlen + need, |
1378 | cp = buffer_append_space(&active_state->incoming_packet, aadlen + need); | 1647 | macbuf, sizeof(macbuf))) != 0) |
1379 | if (cipher_crypt(&active_state->receive_context, | 1648 | goto out; |
1380 | active_state->p_read.seqnr, cp, | 1649 | } |
1381 | buffer_ptr(&active_state->input), need, aadlen, authlen) != 0) | 1650 | if ((r = sshbuf_reserve(state->incoming_packet, aadlen + need, |
1382 | fatal("Decryption integrity check failed"); | 1651 | &cp)) != 0) |
1383 | buffer_consume(&active_state->input, aadlen + need + authlen); | 1652 | goto out; |
1653 | if ((r = cipher_crypt(&state->receive_context, state->p_read.seqnr, cp, | ||
1654 | sshbuf_ptr(state->input), need, aadlen, authlen)) != 0) | ||
1655 | goto out; | ||
1656 | if ((r = sshbuf_consume(state->input, aadlen + need + authlen)) != 0) | ||
1657 | goto out; | ||
1384 | /* | 1658 | /* |
1385 | * compute MAC over seqnr and packet, | 1659 | * compute MAC over seqnr and packet, |
1386 | * increment sequence number for incoming packet | 1660 | * increment sequence number for incoming packet |
1387 | */ | 1661 | */ |
1388 | if (mac && mac->enabled) { | 1662 | if (mac && mac->enabled) { |
1389 | if (!mac->etm) | 1663 | if (!mac->etm) |
1390 | macbuf = mac_compute(mac, active_state->p_read.seqnr, | 1664 | if ((r = mac_compute(mac, state->p_read.seqnr, |
1391 | buffer_ptr(&active_state->incoming_packet), | 1665 | sshbuf_ptr(state->incoming_packet), |
1392 | buffer_len(&active_state->incoming_packet)); | 1666 | sshbuf_len(state->incoming_packet), |
1393 | if (timingsafe_bcmp(macbuf, buffer_ptr(&active_state->input), | 1667 | macbuf, sizeof(macbuf))) != 0) |
1668 | goto out; | ||
1669 | if (timingsafe_bcmp(macbuf, sshbuf_ptr(state->input), | ||
1394 | mac->mac_len) != 0) { | 1670 | mac->mac_len) != 0) { |
1395 | logit("Corrupted MAC on input."); | 1671 | logit("Corrupted MAC on input."); |
1396 | if (need > PACKET_MAX_SIZE) | 1672 | if (need > PACKET_MAX_SIZE) |
1397 | fatal("internal error need %d", need); | 1673 | return SSH_ERR_INTERNAL_ERROR; |
1398 | packet_start_discard(enc, mac, active_state->packlen, | 1674 | return ssh_packet_start_discard(ssh, enc, mac, |
1399 | PACKET_MAX_SIZE - need); | 1675 | state->packlen, PACKET_MAX_SIZE - need); |
1400 | return SSH_MSG_NONE; | ||
1401 | } | 1676 | } |
1402 | 1677 | ||
1403 | DBG(debug("MAC #%d ok", active_state->p_read.seqnr)); | 1678 | DBG(debug("MAC #%d ok", state->p_read.seqnr)); |
1404 | buffer_consume(&active_state->input, mac->mac_len); | 1679 | if ((r = sshbuf_consume(state->input, mac->mac_len)) != 0) |
1680 | goto out; | ||
1405 | } | 1681 | } |
1406 | /* XXX now it's safe to use fatal/packet_disconnect */ | ||
1407 | if (seqnr_p != NULL) | 1682 | if (seqnr_p != NULL) |
1408 | *seqnr_p = active_state->p_read.seqnr; | 1683 | *seqnr_p = state->p_read.seqnr; |
1409 | if (++active_state->p_read.seqnr == 0) | 1684 | if (++state->p_read.seqnr == 0) |
1410 | logit("incoming seqnr wraps around"); | 1685 | logit("incoming seqnr wraps around"); |
1411 | if (++active_state->p_read.packets == 0) | 1686 | if (++state->p_read.packets == 0) |
1412 | if (!(datafellows & SSH_BUG_NOREKEY)) | 1687 | if (!(ssh->compat & SSH_BUG_NOREKEY)) |
1413 | fatal("XXX too many packets with same key"); | 1688 | return SSH_ERR_NEED_REKEY; |
1414 | active_state->p_read.blocks += (active_state->packlen + 4) / block_size; | 1689 | state->p_read.blocks += (state->packlen + 4) / block_size; |
1415 | active_state->p_read.bytes += active_state->packlen + 4; | 1690 | state->p_read.bytes += state->packlen + 4; |
1416 | 1691 | ||
1417 | /* get padlen */ | 1692 | /* get padlen */ |
1418 | cp = buffer_ptr(&active_state->incoming_packet); | 1693 | padlen = sshbuf_ptr(state->incoming_packet)[4]; |
1419 | padlen = cp[4]; | ||
1420 | DBG(debug("input: padlen %d", padlen)); | 1694 | DBG(debug("input: padlen %d", padlen)); |
1421 | if (padlen < 4) | 1695 | if (padlen < 4) { |
1422 | packet_disconnect("Corrupted padlen %d on input.", padlen); | 1696 | if ((r = sshpkt_disconnect(ssh, |
1697 | "Corrupted padlen %d on input.", padlen)) != 0 || | ||
1698 | (r = ssh_packet_write_wait(ssh)) != 0) | ||
1699 | return r; | ||
1700 | return SSH_ERR_CONN_CORRUPT; | ||
1701 | } | ||
1423 | 1702 | ||
1424 | /* skip packet size + padlen, discard padding */ | 1703 | /* skip packet size + padlen, discard padding */ |
1425 | buffer_consume(&active_state->incoming_packet, 4 + 1); | 1704 | if ((r = sshbuf_consume(state->incoming_packet, 4 + 1)) != 0 || |
1426 | buffer_consume_end(&active_state->incoming_packet, padlen); | 1705 | ((r = sshbuf_consume_end(state->incoming_packet, padlen)) != 0)) |
1706 | goto out; | ||
1427 | 1707 | ||
1428 | DBG(debug("input: len before de-compress %d", | 1708 | DBG(debug("input: len before de-compress %zd", |
1429 | buffer_len(&active_state->incoming_packet))); | 1709 | sshbuf_len(state->incoming_packet))); |
1430 | if (comp && comp->enabled) { | 1710 | if (comp && comp->enabled) { |
1431 | buffer_clear(&active_state->compression_buffer); | 1711 | sshbuf_reset(state->compression_buffer); |
1432 | buffer_uncompress(&active_state->incoming_packet, | 1712 | if ((r = uncompress_buffer(ssh, state->incoming_packet, |
1433 | &active_state->compression_buffer); | 1713 | state->compression_buffer)) != 0) |
1434 | buffer_clear(&active_state->incoming_packet); | 1714 | goto out; |
1435 | buffer_append(&active_state->incoming_packet, | 1715 | sshbuf_reset(state->incoming_packet); |
1436 | buffer_ptr(&active_state->compression_buffer), | 1716 | if ((r = sshbuf_putb(state->incoming_packet, |
1437 | buffer_len(&active_state->compression_buffer)); | 1717 | state->compression_buffer)) != 0) |
1438 | DBG(debug("input: len after de-compress %d", | 1718 | goto out; |
1439 | buffer_len(&active_state->incoming_packet))); | 1719 | DBG(debug("input: len after de-compress %zd", |
1720 | sshbuf_len(state->incoming_packet))); | ||
1440 | } | 1721 | } |
1441 | /* | 1722 | /* |
1442 | * get packet type, implies consume. | 1723 | * get packet type, implies consume. |
1443 | * return length of payload (without type field) | 1724 | * return length of payload (without type field) |
1444 | */ | 1725 | */ |
1445 | type = buffer_get_char(&active_state->incoming_packet); | 1726 | if ((r = sshbuf_get_u8(state->incoming_packet, typep)) != 0) |
1446 | if (type < SSH2_MSG_MIN || type >= SSH2_MSG_LOCAL_MIN) | 1727 | goto out; |
1447 | packet_disconnect("Invalid ssh2 packet type: %d", type); | 1728 | if (*typep < SSH2_MSG_MIN || *typep >= SSH2_MSG_LOCAL_MIN) { |
1448 | if (type == SSH2_MSG_NEWKEYS) | 1729 | if ((r = sshpkt_disconnect(ssh, |
1449 | set_newkeys(MODE_IN); | 1730 | "Invalid ssh2 packet type: %d", *typep)) != 0 || |
1450 | else if (type == SSH2_MSG_USERAUTH_SUCCESS && | 1731 | (r = ssh_packet_write_wait(ssh)) != 0) |
1451 | !active_state->server_side) | 1732 | return r; |
1452 | packet_enable_delayed_compress(); | 1733 | return SSH_ERR_PROTOCOL_ERROR; |
1734 | } | ||
1735 | if (*typep == SSH2_MSG_NEWKEYS) | ||
1736 | r = ssh_set_newkeys(ssh, MODE_IN); | ||
1737 | else if (*typep == SSH2_MSG_USERAUTH_SUCCESS && !state->server_side) | ||
1738 | r = ssh_packet_enable_delayed_compress(ssh); | ||
1739 | else | ||
1740 | r = 0; | ||
1453 | #ifdef PACKET_DEBUG | 1741 | #ifdef PACKET_DEBUG |
1454 | fprintf(stderr, "read/plain[%d]:\r\n", type); | 1742 | fprintf(stderr, "read/plain[%d]:\r\n", *typep); |
1455 | buffer_dump(&active_state->incoming_packet); | 1743 | sshbuf_dump(state->incoming_packet, stderr); |
1456 | #endif | 1744 | #endif |
1457 | /* reset for next packet */ | 1745 | /* reset for next packet */ |
1458 | active_state->packlen = 0; | 1746 | state->packlen = 0; |
1459 | return type; | 1747 | out: |
1748 | return r; | ||
1460 | } | 1749 | } |
1461 | 1750 | ||
1462 | int | 1751 | int |
1463 | packet_read_poll_seqnr(u_int32_t *seqnr_p) | 1752 | ssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) |
1464 | { | 1753 | { |
1754 | struct session_state *state = ssh->state; | ||
1465 | u_int reason, seqnr; | 1755 | u_int reason, seqnr; |
1466 | u_char type; | 1756 | int r; |
1467 | char *msg; | 1757 | u_char *msg; |
1468 | 1758 | ||
1469 | for (;;) { | 1759 | for (;;) { |
1760 | msg = NULL; | ||
1470 | if (compat20) { | 1761 | if (compat20) { |
1471 | type = packet_read_poll2(seqnr_p); | 1762 | r = ssh_packet_read_poll2(ssh, typep, seqnr_p); |
1472 | if (type) { | 1763 | if (r != 0) |
1473 | active_state->keep_alive_timeouts = 0; | 1764 | return r; |
1474 | DBG(debug("received packet type %d", type)); | 1765 | if (*typep) { |
1766 | state->keep_alive_timeouts = 0; | ||
1767 | DBG(debug("received packet type %d", *typep)); | ||
1475 | } | 1768 | } |
1476 | switch (type) { | 1769 | switch (*typep) { |
1477 | case SSH2_MSG_IGNORE: | 1770 | case SSH2_MSG_IGNORE: |
1478 | debug3("Received SSH2_MSG_IGNORE"); | 1771 | debug3("Received SSH2_MSG_IGNORE"); |
1479 | break; | 1772 | break; |
1480 | case SSH2_MSG_DEBUG: | 1773 | case SSH2_MSG_DEBUG: |
1481 | packet_get_char(); | 1774 | if ((r = sshpkt_get_u8(ssh, NULL)) != 0 || |
1482 | msg = packet_get_string(NULL); | 1775 | (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 || |
1776 | (r = sshpkt_get_string(ssh, NULL, NULL)) != 0) { | ||
1777 | if (msg) | ||
1778 | free(msg); | ||
1779 | return r; | ||
1780 | } | ||
1483 | debug("Remote: %.900s", msg); | 1781 | debug("Remote: %.900s", msg); |
1484 | free(msg); | 1782 | free(msg); |
1485 | msg = packet_get_string(NULL); | ||
1486 | free(msg); | ||
1487 | break; | 1783 | break; |
1488 | case SSH2_MSG_DISCONNECT: | 1784 | case SSH2_MSG_DISCONNECT: |
1489 | reason = packet_get_int(); | 1785 | if ((r = sshpkt_get_u32(ssh, &reason)) != 0 || |
1490 | msg = packet_get_string(NULL); | 1786 | (r = sshpkt_get_string(ssh, &msg, NULL)) != 0) |
1787 | return r; | ||
1491 | /* Ignore normal client exit notifications */ | 1788 | /* Ignore normal client exit notifications */ |
1492 | do_log2(active_state->server_side && | 1789 | do_log2(ssh->state->server_side && |
1493 | reason == SSH2_DISCONNECT_BY_APPLICATION ? | 1790 | reason == SSH2_DISCONNECT_BY_APPLICATION ? |
1494 | SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR, | 1791 | SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR, |
1495 | "Received disconnect from %s: %u: %.400s", | 1792 | "Received disconnect from %s: %u: %.400s", |
1496 | get_remote_ipaddr(), reason, msg); | 1793 | ssh_remote_ipaddr(ssh), reason, msg); |
1497 | free(msg); | 1794 | free(msg); |
1498 | cleanup_exit(255); | 1795 | return SSH_ERR_DISCONNECTED; |
1499 | break; | ||
1500 | case SSH2_MSG_UNIMPLEMENTED: | 1796 | case SSH2_MSG_UNIMPLEMENTED: |
1501 | seqnr = packet_get_int(); | 1797 | if ((r = sshpkt_get_u32(ssh, &seqnr)) != 0) |
1798 | return r; | ||
1502 | debug("Received SSH2_MSG_UNIMPLEMENTED for %u", | 1799 | debug("Received SSH2_MSG_UNIMPLEMENTED for %u", |
1503 | seqnr); | 1800 | seqnr); |
1504 | break; | 1801 | break; |
1505 | default: | 1802 | default: |
1506 | return type; | 1803 | return 0; |
1507 | } | 1804 | } |
1508 | } else { | 1805 | } else { |
1509 | type = packet_read_poll1(); | 1806 | r = ssh_packet_read_poll1(ssh, typep); |
1510 | switch (type) { | 1807 | switch (*typep) { |
1511 | case SSH_MSG_NONE: | 1808 | case SSH_MSG_NONE: |
1512 | return SSH_MSG_NONE; | 1809 | return SSH_MSG_NONE; |
1513 | case SSH_MSG_IGNORE: | 1810 | case SSH_MSG_IGNORE: |
1514 | break; | 1811 | break; |
1515 | case SSH_MSG_DEBUG: | 1812 | case SSH_MSG_DEBUG: |
1516 | msg = packet_get_string(NULL); | 1813 | if ((r = sshpkt_get_string(ssh, &msg, NULL)) != 0) |
1814 | return r; | ||
1517 | debug("Remote: %.900s", msg); | 1815 | debug("Remote: %.900s", msg); |
1518 | free(msg); | 1816 | free(msg); |
1519 | break; | 1817 | break; |
1520 | case SSH_MSG_DISCONNECT: | 1818 | case SSH_MSG_DISCONNECT: |
1521 | msg = packet_get_string(NULL); | 1819 | if ((r = sshpkt_get_string(ssh, &msg, NULL)) != 0) |
1820 | return r; | ||
1522 | error("Received disconnect from %s: %.400s", | 1821 | error("Received disconnect from %s: %.400s", |
1523 | get_remote_ipaddr(), msg); | 1822 | ssh_remote_ipaddr(ssh), msg); |
1524 | cleanup_exit(255); | 1823 | free(msg); |
1525 | break; | 1824 | return SSH_ERR_DISCONNECTED; |
1526 | default: | 1825 | default: |
1527 | DBG(debug("received packet type %d", type)); | 1826 | DBG(debug("received packet type %d", *typep)); |
1528 | return type; | 1827 | return 0; |
1529 | } | 1828 | } |
1530 | } | 1829 | } |
1531 | } | 1830 | } |
@@ -1536,113 +1835,31 @@ packet_read_poll_seqnr(u_int32_t *seqnr_p) | |||
1536 | * together with packet_read_poll. | 1835 | * together with packet_read_poll. |
1537 | */ | 1836 | */ |
1538 | 1837 | ||
1539 | void | ||
1540 | packet_process_incoming(const char *buf, u_int len) | ||
1541 | { | ||
1542 | if (active_state->packet_discard) { | ||
1543 | active_state->keep_alive_timeouts = 0; /* ?? */ | ||
1544 | if (len >= active_state->packet_discard) | ||
1545 | packet_stop_discard(); | ||
1546 | active_state->packet_discard -= len; | ||
1547 | return; | ||
1548 | } | ||
1549 | buffer_append(&active_state->input, buf, len); | ||
1550 | } | ||
1551 | |||
1552 | /* Returns a character from the packet. */ | ||
1553 | |||
1554 | u_int | ||
1555 | packet_get_char(void) | ||
1556 | { | ||
1557 | char ch; | ||
1558 | |||
1559 | buffer_get(&active_state->incoming_packet, &ch, 1); | ||
1560 | return (u_char) ch; | ||
1561 | } | ||
1562 | |||
1563 | /* Returns an integer from the packet data. */ | ||
1564 | |||
1565 | u_int | ||
1566 | packet_get_int(void) | ||
1567 | { | ||
1568 | return buffer_get_int(&active_state->incoming_packet); | ||
1569 | } | ||
1570 | |||
1571 | /* Returns an 64 bit integer from the packet data. */ | ||
1572 | |||
1573 | u_int64_t | ||
1574 | packet_get_int64(void) | ||
1575 | { | ||
1576 | return buffer_get_int64(&active_state->incoming_packet); | ||
1577 | } | ||
1578 | |||
1579 | /* | ||
1580 | * Returns an arbitrary precision integer from the packet data. The integer | ||
1581 | * must have been initialized before this call. | ||
1582 | */ | ||
1583 | |||
1584 | #ifdef WITH_OPENSSL | ||
1585 | void | ||
1586 | packet_get_bignum(BIGNUM * value) | ||
1587 | { | ||
1588 | buffer_get_bignum(&active_state->incoming_packet, value); | ||
1589 | } | ||
1590 | |||
1591 | void | ||
1592 | packet_get_bignum2(BIGNUM * value) | ||
1593 | { | ||
1594 | buffer_get_bignum2(&active_state->incoming_packet, value); | ||
1595 | } | ||
1596 | |||
1597 | #ifdef OPENSSL_HAS_ECC | ||
1598 | void | ||
1599 | packet_get_ecpoint(const EC_GROUP *curve, EC_POINT *point) | ||
1600 | { | ||
1601 | buffer_get_ecpoint(&active_state->incoming_packet, curve, point); | ||
1602 | } | ||
1603 | #endif | ||
1604 | |||
1605 | void * | ||
1606 | packet_get_raw(u_int *length_ptr) | ||
1607 | { | ||
1608 | u_int bytes = buffer_len(&active_state->incoming_packet); | ||
1609 | |||
1610 | if (length_ptr != NULL) | ||
1611 | *length_ptr = bytes; | ||
1612 | return buffer_ptr(&active_state->incoming_packet); | ||
1613 | } | ||
1614 | #endif | ||
1615 | |||
1616 | int | 1838 | int |
1617 | packet_remaining(void) | 1839 | ssh_packet_process_incoming(struct ssh *ssh, const char *buf, u_int len) |
1618 | { | 1840 | { |
1619 | return buffer_len(&active_state->incoming_packet); | 1841 | struct session_state *state = ssh->state; |
1620 | } | 1842 | int r; |
1621 | |||
1622 | /* | ||
1623 | * Returns a string from the packet data. The string is allocated using | ||
1624 | * xmalloc; it is the responsibility of the calling program to free it when | ||
1625 | * no longer needed. The length_ptr argument may be NULL, or point to an | ||
1626 | * integer into which the length of the string is stored. | ||
1627 | */ | ||
1628 | 1843 | ||
1629 | void * | 1844 | if (state->packet_discard) { |
1630 | packet_get_string(u_int *length_ptr) | 1845 | state->keep_alive_timeouts = 0; /* ?? */ |
1631 | { | 1846 | if (len >= state->packet_discard) { |
1632 | return buffer_get_string(&active_state->incoming_packet, length_ptr); | 1847 | if ((r = ssh_packet_stop_discard(ssh)) != 0) |
1633 | } | 1848 | return r; |
1849 | } | ||
1850 | state->packet_discard -= len; | ||
1851 | return 0; | ||
1852 | } | ||
1853 | if ((r = sshbuf_put(ssh->state->input, buf, len)) != 0) | ||
1854 | return r; | ||
1634 | 1855 | ||
1635 | const void * | 1856 | return 0; |
1636 | packet_get_string_ptr(u_int *length_ptr) | ||
1637 | { | ||
1638 | return buffer_get_string_ptr(&active_state->incoming_packet, length_ptr); | ||
1639 | } | 1857 | } |
1640 | 1858 | ||
1641 | /* Ensures the returned string has no embedded \0 characters in it. */ | 1859 | int |
1642 | char * | 1860 | ssh_packet_remaining(struct ssh *ssh) |
1643 | packet_get_cstring(u_int *length_ptr) | ||
1644 | { | 1861 | { |
1645 | return buffer_get_cstring(&active_state->incoming_packet, length_ptr); | 1862 | return sshbuf_len(ssh->state->incoming_packet); |
1646 | } | 1863 | } |
1647 | 1864 | ||
1648 | /* | 1865 | /* |
@@ -1651,16 +1868,16 @@ packet_get_cstring(u_int *length_ptr) | |||
1651 | * message is printed immediately, but only if the client is being executed | 1868 | * message is printed immediately, but only if the client is being executed |
1652 | * in verbose mode. These messages are primarily intended to ease debugging | 1869 | * in verbose mode. These messages are primarily intended to ease debugging |
1653 | * authentication problems. The length of the formatted message must not | 1870 | * authentication problems. The length of the formatted message must not |
1654 | * exceed 1024 bytes. This will automatically call packet_write_wait. | 1871 | * exceed 1024 bytes. This will automatically call ssh_packet_write_wait. |
1655 | */ | 1872 | */ |
1656 | |||
1657 | void | 1873 | void |
1658 | packet_send_debug(const char *fmt,...) | 1874 | ssh_packet_send_debug(struct ssh *ssh, const char *fmt,...) |
1659 | { | 1875 | { |
1660 | char buf[1024]; | 1876 | char buf[1024]; |
1661 | va_list args; | 1877 | va_list args; |
1878 | int r; | ||
1662 | 1879 | ||
1663 | if (compat20 && (datafellows & SSH_BUG_DEBUG)) | 1880 | if (compat20 && (ssh->compat & SSH_BUG_DEBUG)) |
1664 | return; | 1881 | return; |
1665 | 1882 | ||
1666 | va_start(args, fmt); | 1883 | va_start(args, fmt); |
@@ -1668,16 +1885,41 @@ packet_send_debug(const char *fmt,...) | |||
1668 | va_end(args); | 1885 | va_end(args); |
1669 | 1886 | ||
1670 | if (compat20) { | 1887 | if (compat20) { |
1671 | packet_start(SSH2_MSG_DEBUG); | 1888 | if ((r = sshpkt_start(ssh, SSH2_MSG_DEBUG)) != 0 || |
1672 | packet_put_char(0); /* bool: always display */ | 1889 | (r = sshpkt_put_u8(ssh, 0)) != 0 || /* always display */ |
1673 | packet_put_cstring(buf); | 1890 | (r = sshpkt_put_cstring(ssh, buf)) != 0 || |
1674 | packet_put_cstring(""); | 1891 | (r = sshpkt_put_cstring(ssh, "")) != 0 || |
1892 | (r = sshpkt_send(ssh)) != 0) | ||
1893 | fatal("%s: %s", __func__, ssh_err(r)); | ||
1675 | } else { | 1894 | } else { |
1676 | packet_start(SSH_MSG_DEBUG); | 1895 | if ((r = sshpkt_start(ssh, SSH_MSG_DEBUG)) != 0 || |
1677 | packet_put_cstring(buf); | 1896 | (r = sshpkt_put_cstring(ssh, buf)) != 0 || |
1897 | (r = sshpkt_send(ssh)) != 0) | ||
1898 | fatal("%s: %s", __func__, ssh_err(r)); | ||
1899 | } | ||
1900 | if ((r = ssh_packet_write_wait(ssh)) != 0) | ||
1901 | fatal("%s: %s", __func__, ssh_err(r)); | ||
1902 | } | ||
1903 | |||
1904 | /* | ||
1905 | * Pretty-print connection-terminating errors and exit. | ||
1906 | */ | ||
1907 | void | ||
1908 | sshpkt_fatal(struct ssh *ssh, const char *tag, int r) | ||
1909 | { | ||
1910 | switch (r) { | ||
1911 | case SSH_ERR_CONN_CLOSED: | ||
1912 | logit("Connection closed by %.200s", ssh_remote_ipaddr(ssh)); | ||
1913 | cleanup_exit(255); | ||
1914 | case SSH_ERR_CONN_TIMEOUT: | ||
1915 | logit("Connection to %.200s timed out while " | ||
1916 | "waiting to write", ssh_remote_ipaddr(ssh)); | ||
1917 | cleanup_exit(255); | ||
1918 | default: | ||
1919 | fatal("%s%sConnection to %.200s: %s", | ||
1920 | tag != NULL ? tag : "", tag != NULL ? ": " : "", | ||
1921 | ssh_remote_ipaddr(ssh), ssh_err(r)); | ||
1678 | } | 1922 | } |
1679 | packet_send(); | ||
1680 | packet_write_wait(); | ||
1681 | } | 1923 | } |
1682 | 1924 | ||
1683 | /* | 1925 | /* |
@@ -1686,13 +1928,13 @@ packet_send_debug(const char *fmt,...) | |||
1686 | * should not contain a newline. The length of the formatted message must | 1928 | * should not contain a newline. The length of the formatted message must |
1687 | * not exceed 1024 bytes. | 1929 | * not exceed 1024 bytes. |
1688 | */ | 1930 | */ |
1689 | |||
1690 | void | 1931 | void |
1691 | packet_disconnect(const char *fmt,...) | 1932 | ssh_packet_disconnect(struct ssh *ssh, const char *fmt,...) |
1692 | { | 1933 | { |
1693 | char buf[1024]; | 1934 | char buf[1024]; |
1694 | va_list args; | 1935 | va_list args; |
1695 | static int disconnecting = 0; | 1936 | static int disconnecting = 0; |
1937 | int r; | ||
1696 | 1938 | ||
1697 | if (disconnecting) /* Guard against recursive invocations. */ | 1939 | if (disconnecting) /* Guard against recursive invocations. */ |
1698 | fatal("packet_disconnect called recursively."); | 1940 | fatal("packet_disconnect called recursively."); |
@@ -1709,87 +1951,88 @@ packet_disconnect(const char *fmt,...) | |||
1709 | /* Display the error locally */ | 1951 | /* Display the error locally */ |
1710 | logit("Disconnecting: %.100s", buf); | 1952 | logit("Disconnecting: %.100s", buf); |
1711 | 1953 | ||
1712 | /* Send the disconnect message to the other side, and wait for it to get sent. */ | 1954 | /* |
1713 | if (compat20) { | 1955 | * Send the disconnect message to the other side, and wait |
1714 | packet_start(SSH2_MSG_DISCONNECT); | 1956 | * for it to get sent. |
1715 | packet_put_int(SSH2_DISCONNECT_PROTOCOL_ERROR); | 1957 | */ |
1716 | packet_put_cstring(buf); | 1958 | if ((r = sshpkt_disconnect(ssh, "%s", buf)) != 0) |
1717 | packet_put_cstring(""); | 1959 | sshpkt_fatal(ssh, __func__, r); |
1718 | } else { | ||
1719 | packet_start(SSH_MSG_DISCONNECT); | ||
1720 | packet_put_cstring(buf); | ||
1721 | } | ||
1722 | packet_send(); | ||
1723 | packet_write_wait(); | ||
1724 | 1960 | ||
1725 | /* Stop listening for connections. */ | 1961 | if ((r = ssh_packet_write_wait(ssh)) != 0) |
1726 | channel_close_all(); | 1962 | sshpkt_fatal(ssh, __func__, r); |
1727 | 1963 | ||
1728 | /* Close the connection. */ | 1964 | /* Close the connection. */ |
1729 | packet_close(); | 1965 | ssh_packet_close(ssh); |
1730 | cleanup_exit(255); | 1966 | cleanup_exit(255); |
1731 | } | 1967 | } |
1732 | 1968 | ||
1733 | /* Checks if there is any buffered output, and tries to write some of the output. */ | 1969 | /* |
1734 | 1970 | * Checks if there is any buffered output, and tries to write some of | |
1735 | void | 1971 | * the output. |
1736 | packet_write_poll(void) | 1972 | */ |
1973 | int | ||
1974 | ssh_packet_write_poll(struct ssh *ssh) | ||
1737 | { | 1975 | { |
1738 | int len = buffer_len(&active_state->output); | 1976 | struct session_state *state = ssh->state; |
1739 | int cont; | 1977 | int len = sshbuf_len(state->output); |
1978 | int cont, r; | ||
1740 | 1979 | ||
1741 | if (len > 0) { | 1980 | if (len > 0) { |
1742 | cont = 0; | 1981 | cont = 0; |
1743 | len = roaming_write(active_state->connection_out, | 1982 | len = roaming_write(state->connection_out, |
1744 | buffer_ptr(&active_state->output), len, &cont); | 1983 | sshbuf_ptr(state->output), len, &cont); |
1745 | if (len == -1) { | 1984 | if (len == -1) { |
1746 | if (errno == EINTR || errno == EAGAIN || | 1985 | if (errno == EINTR || errno == EAGAIN || |
1747 | errno == EWOULDBLOCK) | 1986 | errno == EWOULDBLOCK) |
1748 | return; | 1987 | return 0; |
1749 | fatal("Write failed: %.100s", strerror(errno)); | 1988 | return SSH_ERR_SYSTEM_ERROR; |
1750 | } | 1989 | } |
1751 | if (len == 0 && !cont) | 1990 | if (len == 0 && !cont) |
1752 | fatal("Write connection closed"); | 1991 | return SSH_ERR_CONN_CLOSED; |
1753 | buffer_consume(&active_state->output, len); | 1992 | if ((r = sshbuf_consume(state->output, len)) != 0) |
1993 | return r; | ||
1754 | } | 1994 | } |
1995 | return 0; | ||
1755 | } | 1996 | } |
1756 | 1997 | ||
1757 | /* | 1998 | /* |
1758 | * Calls packet_write_poll repeatedly until all pending output data has been | 1999 | * Calls packet_write_poll repeatedly until all pending output data has been |
1759 | * written. | 2000 | * written. |
1760 | */ | 2001 | */ |
1761 | 2002 | int | |
1762 | void | 2003 | ssh_packet_write_wait(struct ssh *ssh) |
1763 | packet_write_wait(void) | ||
1764 | { | 2004 | { |
1765 | fd_set *setp; | 2005 | fd_set *setp; |
1766 | int ret, ms_remain = 0; | 2006 | int ret, r, ms_remain = 0; |
1767 | struct timeval start, timeout, *timeoutp = NULL; | 2007 | struct timeval start, timeout, *timeoutp = NULL; |
2008 | struct session_state *state = ssh->state; | ||
1768 | 2009 | ||
1769 | setp = (fd_set *)xcalloc(howmany(active_state->connection_out + 1, | 2010 | setp = (fd_set *)calloc(howmany(state->connection_out + 1, |
1770 | NFDBITS), sizeof(fd_mask)); | 2011 | NFDBITS), sizeof(fd_mask)); |
1771 | packet_write_poll(); | 2012 | if (setp == NULL) |
1772 | while (packet_have_data_to_write()) { | 2013 | return SSH_ERR_ALLOC_FAIL; |
1773 | memset(setp, 0, howmany(active_state->connection_out + 1, | 2014 | ssh_packet_write_poll(ssh); |
2015 | while (ssh_packet_have_data_to_write(ssh)) { | ||
2016 | memset(setp, 0, howmany(state->connection_out + 1, | ||
1774 | NFDBITS) * sizeof(fd_mask)); | 2017 | NFDBITS) * sizeof(fd_mask)); |
1775 | FD_SET(active_state->connection_out, setp); | 2018 | FD_SET(state->connection_out, setp); |
1776 | 2019 | ||
1777 | if (active_state->packet_timeout_ms > 0) { | 2020 | if (state->packet_timeout_ms > 0) { |
1778 | ms_remain = active_state->packet_timeout_ms; | 2021 | ms_remain = state->packet_timeout_ms; |
1779 | timeoutp = &timeout; | 2022 | timeoutp = &timeout; |
1780 | } | 2023 | } |
1781 | for (;;) { | 2024 | for (;;) { |
1782 | if (active_state->packet_timeout_ms != -1) { | 2025 | if (state->packet_timeout_ms != -1) { |
1783 | ms_to_timeval(&timeout, ms_remain); | 2026 | ms_to_timeval(&timeout, ms_remain); |
1784 | gettimeofday(&start, NULL); | 2027 | gettimeofday(&start, NULL); |
1785 | } | 2028 | } |
1786 | if ((ret = select(active_state->connection_out + 1, | 2029 | if ((ret = select(state->connection_out + 1, |
1787 | NULL, setp, NULL, timeoutp)) >= 0) | 2030 | NULL, setp, NULL, timeoutp)) >= 0) |
1788 | break; | 2031 | break; |
1789 | if (errno != EAGAIN && errno != EINTR && | 2032 | if (errno != EAGAIN && errno != EINTR && |
1790 | errno != EWOULDBLOCK) | 2033 | errno != EWOULDBLOCK) |
1791 | break; | 2034 | break; |
1792 | if (active_state->packet_timeout_ms == -1) | 2035 | if (state->packet_timeout_ms == -1) |
1793 | continue; | 2036 | continue; |
1794 | ms_subtract_diff(&start, &ms_remain); | 2037 | ms_subtract_diff(&start, &ms_remain); |
1795 | if (ms_remain <= 0) { | 2038 | if (ms_remain <= 0) { |
@@ -1798,45 +2041,48 @@ packet_write_wait(void) | |||
1798 | } | 2041 | } |
1799 | } | 2042 | } |
1800 | if (ret == 0) { | 2043 | if (ret == 0) { |
1801 | logit("Connection to %.200s timed out while " | 2044 | free(setp); |
1802 | "waiting to write", get_remote_ipaddr()); | 2045 | return SSH_ERR_CONN_TIMEOUT; |
1803 | cleanup_exit(255); | 2046 | } |
2047 | if ((r = ssh_packet_write_poll(ssh)) != 0) { | ||
2048 | free(setp); | ||
2049 | return r; | ||
1804 | } | 2050 | } |
1805 | packet_write_poll(); | ||
1806 | } | 2051 | } |
1807 | free(setp); | 2052 | free(setp); |
2053 | return 0; | ||
1808 | } | 2054 | } |
1809 | 2055 | ||
1810 | /* Returns true if there is buffered data to write to the connection. */ | 2056 | /* Returns true if there is buffered data to write to the connection. */ |
1811 | 2057 | ||
1812 | int | 2058 | int |
1813 | packet_have_data_to_write(void) | 2059 | ssh_packet_have_data_to_write(struct ssh *ssh) |
1814 | { | 2060 | { |
1815 | return buffer_len(&active_state->output) != 0; | 2061 | return sshbuf_len(ssh->state->output) != 0; |
1816 | } | 2062 | } |
1817 | 2063 | ||
1818 | /* Returns true if there is not too much data to write to the connection. */ | 2064 | /* Returns true if there is not too much data to write to the connection. */ |
1819 | 2065 | ||
1820 | int | 2066 | int |
1821 | packet_not_very_much_data_to_write(void) | 2067 | ssh_packet_not_very_much_data_to_write(struct ssh *ssh) |
1822 | { | 2068 | { |
1823 | if (active_state->interactive_mode) | 2069 | if (ssh->state->interactive_mode) |
1824 | return buffer_len(&active_state->output) < 16384; | 2070 | return sshbuf_len(ssh->state->output) < 16384; |
1825 | else | 2071 | else |
1826 | return buffer_len(&active_state->output) < 128 * 1024; | 2072 | return sshbuf_len(ssh->state->output) < 128 * 1024; |
1827 | } | 2073 | } |
1828 | 2074 | ||
1829 | static void | 2075 | void |
1830 | packet_set_tos(int tos) | 2076 | ssh_packet_set_tos(struct ssh *ssh, int tos) |
1831 | { | 2077 | { |
1832 | #ifndef IP_TOS_IS_BROKEN | 2078 | #ifndef IP_TOS_IS_BROKEN |
1833 | if (!packet_connection_is_on_socket()) | 2079 | if (!ssh_packet_connection_is_on_socket(ssh)) |
1834 | return; | 2080 | return; |
1835 | switch (packet_connection_af()) { | 2081 | switch (ssh_packet_connection_af(ssh)) { |
1836 | # ifdef IP_TOS | 2082 | # ifdef IP_TOS |
1837 | case AF_INET: | 2083 | case AF_INET: |
1838 | debug3("%s: set IP_TOS 0x%02x", __func__, tos); | 2084 | debug3("%s: set IP_TOS 0x%02x", __func__, tos); |
1839 | if (setsockopt(active_state->connection_in, | 2085 | if (setsockopt(ssh->state->connection_in, |
1840 | IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) | 2086 | IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) |
1841 | error("setsockopt IP_TOS %d: %.100s:", | 2087 | error("setsockopt IP_TOS %d: %.100s:", |
1842 | tos, strerror(errno)); | 2088 | tos, strerror(errno)); |
@@ -1845,7 +2091,7 @@ packet_set_tos(int tos) | |||
1845 | # ifdef IPV6_TCLASS | 2091 | # ifdef IPV6_TCLASS |
1846 | case AF_INET6: | 2092 | case AF_INET6: |
1847 | debug3("%s: set IPV6_TCLASS 0x%02x", __func__, tos); | 2093 | debug3("%s: set IPV6_TCLASS 0x%02x", __func__, tos); |
1848 | if (setsockopt(active_state->connection_in, | 2094 | if (setsockopt(ssh->state->connection_in, |
1849 | IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof(tos)) < 0) | 2095 | IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof(tos)) < 0) |
1850 | error("setsockopt IPV6_TCLASS %d: %.100s:", | 2096 | error("setsockopt IPV6_TCLASS %d: %.100s:", |
1851 | tos, strerror(errno)); | 2097 | tos, strerror(errno)); |
@@ -1858,71 +2104,69 @@ packet_set_tos(int tos) | |||
1858 | /* Informs that the current session is interactive. Sets IP flags for that. */ | 2104 | /* Informs that the current session is interactive. Sets IP flags for that. */ |
1859 | 2105 | ||
1860 | void | 2106 | void |
1861 | packet_set_interactive(int interactive, int qos_interactive, int qos_bulk) | 2107 | ssh_packet_set_interactive(struct ssh *ssh, int interactive, int qos_interactive, int qos_bulk) |
1862 | { | 2108 | { |
1863 | if (active_state->set_interactive_called) | 2109 | struct session_state *state = ssh->state; |
2110 | |||
2111 | if (state->set_interactive_called) | ||
1864 | return; | 2112 | return; |
1865 | active_state->set_interactive_called = 1; | 2113 | state->set_interactive_called = 1; |
1866 | 2114 | ||
1867 | /* Record that we are in interactive mode. */ | 2115 | /* Record that we are in interactive mode. */ |
1868 | active_state->interactive_mode = interactive; | 2116 | state->interactive_mode = interactive; |
1869 | 2117 | ||
1870 | /* Only set socket options if using a socket. */ | 2118 | /* Only set socket options if using a socket. */ |
1871 | if (!packet_connection_is_on_socket()) | 2119 | if (!ssh_packet_connection_is_on_socket(ssh)) |
1872 | return; | 2120 | return; |
1873 | set_nodelay(active_state->connection_in); | 2121 | set_nodelay(state->connection_in); |
1874 | packet_set_tos(interactive ? qos_interactive : qos_bulk); | 2122 | ssh_packet_set_tos(ssh, interactive ? qos_interactive : |
2123 | qos_bulk); | ||
1875 | } | 2124 | } |
1876 | 2125 | ||
1877 | /* Returns true if the current connection is interactive. */ | 2126 | /* Returns true if the current connection is interactive. */ |
1878 | 2127 | ||
1879 | int | 2128 | int |
1880 | packet_is_interactive(void) | 2129 | ssh_packet_is_interactive(struct ssh *ssh) |
1881 | { | 2130 | { |
1882 | return active_state->interactive_mode; | 2131 | return ssh->state->interactive_mode; |
1883 | } | 2132 | } |
1884 | 2133 | ||
1885 | int | 2134 | int |
1886 | packet_set_maxsize(u_int s) | 2135 | ssh_packet_set_maxsize(struct ssh *ssh, u_int s) |
1887 | { | 2136 | { |
1888 | if (active_state->set_maxsize_called) { | 2137 | struct session_state *state = ssh->state; |
2138 | |||
2139 | if (state->set_maxsize_called) { | ||
1889 | logit("packet_set_maxsize: called twice: old %d new %d", | 2140 | logit("packet_set_maxsize: called twice: old %d new %d", |
1890 | active_state->max_packet_size, s); | 2141 | state->max_packet_size, s); |
1891 | return -1; | 2142 | return -1; |
1892 | } | 2143 | } |
1893 | if (s < 4 * 1024 || s > 1024 * 1024) { | 2144 | if (s < 4 * 1024 || s > 1024 * 1024) { |
1894 | logit("packet_set_maxsize: bad size %d", s); | 2145 | logit("packet_set_maxsize: bad size %d", s); |
1895 | return -1; | 2146 | return -1; |
1896 | } | 2147 | } |
1897 | active_state->set_maxsize_called = 1; | 2148 | state->set_maxsize_called = 1; |
1898 | debug("packet_set_maxsize: setting to %d", s); | 2149 | debug("packet_set_maxsize: setting to %d", s); |
1899 | active_state->max_packet_size = s; | 2150 | state->max_packet_size = s; |
1900 | return s; | 2151 | return s; |
1901 | } | 2152 | } |
1902 | 2153 | ||
1903 | int | 2154 | int |
1904 | packet_inc_alive_timeouts(void) | 2155 | ssh_packet_inc_alive_timeouts(struct ssh *ssh) |
1905 | { | 2156 | { |
1906 | return ++active_state->keep_alive_timeouts; | 2157 | return ++ssh->state->keep_alive_timeouts; |
1907 | } | 2158 | } |
1908 | 2159 | ||
1909 | void | 2160 | void |
1910 | packet_set_alive_timeouts(int ka) | 2161 | ssh_packet_set_alive_timeouts(struct ssh *ssh, int ka) |
1911 | { | 2162 | { |
1912 | active_state->keep_alive_timeouts = ka; | 2163 | ssh->state->keep_alive_timeouts = ka; |
1913 | } | 2164 | } |
1914 | 2165 | ||
1915 | u_int | 2166 | u_int |
1916 | packet_get_maxsize(void) | 2167 | ssh_packet_get_maxsize(struct ssh *ssh) |
1917 | { | 2168 | { |
1918 | return active_state->max_packet_size; | 2169 | return ssh->state->max_packet_size; |
1919 | } | ||
1920 | |||
1921 | /* roundup current message to pad bytes */ | ||
1922 | void | ||
1923 | packet_add_padding(u_char pad) | ||
1924 | { | ||
1925 | active_state->extra_pad = pad; | ||
1926 | } | 2170 | } |
1927 | 2171 | ||
1928 | /* | 2172 | /* |
@@ -1937,155 +2181,718 @@ packet_add_padding(u_char pad) | |||
1937 | * protection measure against advanced traffic analysis techniques. | 2181 | * protection measure against advanced traffic analysis techniques. |
1938 | */ | 2182 | */ |
1939 | void | 2183 | void |
1940 | packet_send_ignore(int nbytes) | 2184 | ssh_packet_send_ignore(struct ssh *ssh, int nbytes) |
1941 | { | 2185 | { |
1942 | u_int32_t rnd = 0; | 2186 | u_int32_t rnd = 0; |
1943 | int i; | 2187 | int r, i; |
1944 | 2188 | ||
1945 | packet_start(compat20 ? SSH2_MSG_IGNORE : SSH_MSG_IGNORE); | 2189 | if ((r = sshpkt_start(ssh, compat20 ? |
1946 | packet_put_int(nbytes); | 2190 | SSH2_MSG_IGNORE : SSH_MSG_IGNORE)) != 0 || |
2191 | (r = sshpkt_put_u32(ssh, nbytes)) != 0) | ||
2192 | fatal("%s: %s", __func__, ssh_err(r)); | ||
1947 | for (i = 0; i < nbytes; i++) { | 2193 | for (i = 0; i < nbytes; i++) { |
1948 | if (i % 4 == 0) | 2194 | if (i % 4 == 0) |
1949 | rnd = arc4random(); | 2195 | rnd = arc4random(); |
1950 | packet_put_char((u_char)rnd & 0xff); | 2196 | if ((r = sshpkt_put_u8(ssh, (u_char)rnd & 0xff)) != 0) |
2197 | fatal("%s: %s", __func__, ssh_err(r)); | ||
1951 | rnd >>= 8; | 2198 | rnd >>= 8; |
1952 | } | 2199 | } |
1953 | } | 2200 | } |
1954 | 2201 | ||
1955 | #define MAX_PACKETS (1U<<31) | 2202 | #define MAX_PACKETS (1U<<31) |
1956 | int | 2203 | int |
1957 | packet_need_rekeying(void) | 2204 | ssh_packet_need_rekeying(struct ssh *ssh) |
1958 | { | 2205 | { |
1959 | if (datafellows & SSH_BUG_NOREKEY) | 2206 | struct session_state *state = ssh->state; |
2207 | |||
2208 | if (ssh->compat & SSH_BUG_NOREKEY) | ||
1960 | return 0; | 2209 | return 0; |
1961 | return | 2210 | return |
1962 | (active_state->p_send.packets > MAX_PACKETS) || | 2211 | (state->p_send.packets > MAX_PACKETS) || |
1963 | (active_state->p_read.packets > MAX_PACKETS) || | 2212 | (state->p_read.packets > MAX_PACKETS) || |
1964 | (active_state->max_blocks_out && | 2213 | (state->max_blocks_out && |
1965 | (active_state->p_send.blocks > active_state->max_blocks_out)) || | 2214 | (state->p_send.blocks > state->max_blocks_out)) || |
1966 | (active_state->max_blocks_in && | 2215 | (state->max_blocks_in && |
1967 | (active_state->p_read.blocks > active_state->max_blocks_in)) || | 2216 | (state->p_read.blocks > state->max_blocks_in)) || |
1968 | (active_state->rekey_interval != 0 && active_state->rekey_time + | 2217 | (state->rekey_interval != 0 && state->rekey_time + |
1969 | active_state->rekey_interval <= monotime()); | 2218 | state->rekey_interval <= monotime()); |
1970 | } | 2219 | } |
1971 | 2220 | ||
1972 | void | 2221 | void |
1973 | packet_set_rekey_limits(u_int32_t bytes, time_t seconds) | 2222 | ssh_packet_set_rekey_limits(struct ssh *ssh, u_int32_t bytes, time_t seconds) |
1974 | { | 2223 | { |
1975 | debug3("rekey after %lld bytes, %d seconds", (long long)bytes, | 2224 | debug3("rekey after %lld bytes, %d seconds", (long long)bytes, |
1976 | (int)seconds); | 2225 | (int)seconds); |
1977 | active_state->rekey_limit = bytes; | 2226 | ssh->state->rekey_limit = bytes; |
1978 | active_state->rekey_interval = seconds; | 2227 | ssh->state->rekey_interval = seconds; |
1979 | /* | ||
1980 | * We set the time here so that in post-auth privsep slave we count | ||
1981 | * from the completion of the authentication. | ||
1982 | */ | ||
1983 | active_state->rekey_time = monotime(); | ||
1984 | } | 2228 | } |
1985 | 2229 | ||
1986 | time_t | 2230 | time_t |
1987 | packet_get_rekey_timeout(void) | 2231 | ssh_packet_get_rekey_timeout(struct ssh *ssh) |
1988 | { | 2232 | { |
1989 | time_t seconds; | 2233 | time_t seconds; |
1990 | 2234 | ||
1991 | seconds = active_state->rekey_time + active_state->rekey_interval - | 2235 | seconds = ssh->state->rekey_time + ssh->state->rekey_interval - |
1992 | monotime(); | 2236 | monotime(); |
1993 | return (seconds <= 0 ? 1 : seconds); | 2237 | return (seconds <= 0 ? 1 : seconds); |
1994 | } | 2238 | } |
1995 | 2239 | ||
1996 | void | 2240 | void |
1997 | packet_set_server(void) | 2241 | ssh_packet_set_server(struct ssh *ssh) |
1998 | { | 2242 | { |
1999 | active_state->server_side = 1; | 2243 | ssh->state->server_side = 1; |
2000 | } | 2244 | } |
2001 | 2245 | ||
2002 | void | 2246 | void |
2003 | packet_set_authenticated(void) | 2247 | ssh_packet_set_authenticated(struct ssh *ssh) |
2004 | { | ||
2005 | active_state->after_authentication = 1; | ||
2006 | } | ||
2007 | |||
2008 | void * | ||
2009 | packet_get_input(void) | ||
2010 | { | 2248 | { |
2011 | return (void *)&active_state->input; | 2249 | ssh->state->after_authentication = 1; |
2012 | } | 2250 | } |
2013 | 2251 | ||
2014 | void * | 2252 | void * |
2015 | packet_get_output(void) | 2253 | ssh_packet_get_input(struct ssh *ssh) |
2016 | { | 2254 | { |
2017 | return (void *)&active_state->output; | 2255 | return (void *)ssh->state->input; |
2018 | } | 2256 | } |
2019 | 2257 | ||
2020 | void * | 2258 | void * |
2021 | packet_get_newkeys(int mode) | 2259 | ssh_packet_get_output(struct ssh *ssh) |
2022 | { | 2260 | { |
2023 | return (void *)active_state->newkeys[mode]; | 2261 | return (void *)ssh->state->output; |
2024 | } | 2262 | } |
2025 | 2263 | ||
2264 | /* XXX TODO update roaming to new API (does not work anyway) */ | ||
2026 | /* | 2265 | /* |
2027 | * Save the state for the real connection, and use a separate state when | 2266 | * Save the state for the real connection, and use a separate state when |
2028 | * resuming a suspended connection. | 2267 | * resuming a suspended connection. |
2029 | */ | 2268 | */ |
2030 | void | 2269 | void |
2031 | packet_backup_state(void) | 2270 | ssh_packet_backup_state(struct ssh *ssh, |
2271 | struct ssh *backup_state) | ||
2032 | { | 2272 | { |
2033 | struct session_state *tmp; | 2273 | struct ssh *tmp; |
2034 | 2274 | ||
2035 | close(active_state->connection_in); | 2275 | close(ssh->state->connection_in); |
2036 | active_state->connection_in = -1; | 2276 | ssh->state->connection_in = -1; |
2037 | close(active_state->connection_out); | 2277 | close(ssh->state->connection_out); |
2038 | active_state->connection_out = -1; | 2278 | ssh->state->connection_out = -1; |
2039 | if (backup_state) | 2279 | if (backup_state) |
2040 | tmp = backup_state; | 2280 | tmp = backup_state; |
2041 | else | 2281 | else |
2042 | tmp = alloc_session_state(); | 2282 | tmp = ssh_alloc_session_state(); |
2043 | backup_state = active_state; | 2283 | backup_state = ssh; |
2044 | active_state = tmp; | 2284 | ssh = tmp; |
2045 | } | 2285 | } |
2046 | 2286 | ||
2287 | /* XXX FIXME FIXME FIXME */ | ||
2047 | /* | 2288 | /* |
2048 | * Swap in the old state when resuming a connecion. | 2289 | * Swap in the old state when resuming a connecion. |
2049 | */ | 2290 | */ |
2050 | void | 2291 | void |
2051 | packet_restore_state(void) | 2292 | ssh_packet_restore_state(struct ssh *ssh, |
2293 | struct ssh *backup_state) | ||
2052 | { | 2294 | { |
2053 | struct session_state *tmp; | 2295 | struct ssh *tmp; |
2054 | void *buf; | ||
2055 | u_int len; | 2296 | u_int len; |
2297 | int r; | ||
2056 | 2298 | ||
2057 | tmp = backup_state; | 2299 | tmp = backup_state; |
2058 | backup_state = active_state; | 2300 | backup_state = ssh; |
2059 | active_state = tmp; | 2301 | ssh = tmp; |
2060 | active_state->connection_in = backup_state->connection_in; | 2302 | ssh->state->connection_in = backup_state->state->connection_in; |
2061 | backup_state->connection_in = -1; | 2303 | backup_state->state->connection_in = -1; |
2062 | active_state->connection_out = backup_state->connection_out; | 2304 | ssh->state->connection_out = backup_state->state->connection_out; |
2063 | backup_state->connection_out = -1; | 2305 | backup_state->state->connection_out = -1; |
2064 | len = buffer_len(&backup_state->input); | 2306 | len = sshbuf_len(backup_state->state->input); |
2065 | if (len > 0) { | 2307 | if (len > 0) { |
2066 | buf = buffer_ptr(&backup_state->input); | 2308 | if ((r = sshbuf_putb(ssh->state->input, |
2067 | buffer_append(&active_state->input, buf, len); | 2309 | backup_state->state->input)) != 0) |
2068 | buffer_clear(&backup_state->input); | 2310 | fatal("%s: %s", __func__, ssh_err(r)); |
2311 | sshbuf_reset(backup_state->state->input); | ||
2069 | add_recv_bytes(len); | 2312 | add_recv_bytes(len); |
2070 | } | 2313 | } |
2071 | } | 2314 | } |
2072 | 2315 | ||
2073 | /* Reset after_authentication and reset compression in post-auth privsep */ | 2316 | /* Reset after_authentication and reset compression in post-auth privsep */ |
2074 | void | 2317 | static int |
2075 | packet_set_postauth(void) | 2318 | ssh_packet_set_postauth(struct ssh *ssh) |
2076 | { | 2319 | { |
2077 | Comp *comp; | 2320 | struct sshcomp *comp; |
2078 | int mode; | 2321 | int r, mode; |
2079 | 2322 | ||
2080 | debug("%s: called", __func__); | 2323 | debug("%s: called", __func__); |
2081 | /* This was set in net child, but is not visible in user child */ | 2324 | /* This was set in net child, but is not visible in user child */ |
2082 | active_state->after_authentication = 1; | 2325 | ssh->state->after_authentication = 1; |
2083 | active_state->rekeying = 0; | 2326 | ssh->state->rekeying = 0; |
2084 | for (mode = 0; mode < MODE_MAX; mode++) { | 2327 | for (mode = 0; mode < MODE_MAX; mode++) { |
2085 | if (active_state->newkeys[mode] == NULL) | 2328 | if (ssh->state->newkeys[mode] == NULL) |
2086 | continue; | 2329 | continue; |
2087 | comp = &active_state->newkeys[mode]->comp; | 2330 | comp = &ssh->state->newkeys[mode]->comp; |
2088 | if (comp && comp->enabled) | 2331 | if (comp && comp->enabled && |
2089 | packet_init_compression(); | 2332 | (r = ssh_packet_init_compression(ssh)) != 0) |
2333 | return r; | ||
2334 | } | ||
2335 | return 0; | ||
2336 | } | ||
2337 | |||
2338 | /* Packet state (de-)serialization for privsep */ | ||
2339 | |||
2340 | /* turn kex into a blob for packet state serialization */ | ||
2341 | static int | ||
2342 | kex_to_blob(struct sshbuf *m, struct kex *kex) | ||
2343 | { | ||
2344 | int r; | ||
2345 | |||
2346 | if ((r = sshbuf_put_string(m, kex->session_id, | ||
2347 | kex->session_id_len)) != 0 || | ||
2348 | (r = sshbuf_put_u32(m, kex->we_need)) != 0 || | ||
2349 | (r = sshbuf_put_u32(m, kex->hostkey_type)) != 0 || | ||
2350 | (r = sshbuf_put_u32(m, kex->kex_type)) != 0 || | ||
2351 | (r = sshbuf_put_stringb(m, kex->my)) != 0 || | ||
2352 | (r = sshbuf_put_stringb(m, kex->peer)) != 0 || | ||
2353 | (r = sshbuf_put_u32(m, kex->flags)) != 0 || | ||
2354 | (r = sshbuf_put_cstring(m, kex->client_version_string)) != 0 || | ||
2355 | (r = sshbuf_put_cstring(m, kex->server_version_string)) != 0) | ||
2356 | return r; | ||
2357 | return 0; | ||
2358 | } | ||
2359 | |||
2360 | /* turn key exchange results into a blob for packet state serialization */ | ||
2361 | static int | ||
2362 | newkeys_to_blob(struct sshbuf *m, struct ssh *ssh, int mode) | ||
2363 | { | ||
2364 | struct sshbuf *b; | ||
2365 | struct sshcipher_ctx *cc; | ||
2366 | struct sshcomp *comp; | ||
2367 | struct sshenc *enc; | ||
2368 | struct sshmac *mac; | ||
2369 | struct newkeys *newkey; | ||
2370 | int r; | ||
2371 | |||
2372 | if ((newkey = ssh->state->newkeys[mode]) == NULL) | ||
2373 | return SSH_ERR_INTERNAL_ERROR; | ||
2374 | enc = &newkey->enc; | ||
2375 | mac = &newkey->mac; | ||
2376 | comp = &newkey->comp; | ||
2377 | cc = (mode == MODE_OUT) ? &ssh->state->send_context : | ||
2378 | &ssh->state->receive_context; | ||
2379 | if ((r = cipher_get_keyiv(cc, enc->iv, enc->iv_len)) != 0) | ||
2380 | return r; | ||
2381 | if ((b = sshbuf_new()) == NULL) | ||
2382 | return SSH_ERR_ALLOC_FAIL; | ||
2383 | /* The cipher struct is constant and shared, you export pointer */ | ||
2384 | if ((r = sshbuf_put_cstring(b, enc->name)) != 0 || | ||
2385 | (r = sshbuf_put(b, &enc->cipher, sizeof(enc->cipher))) != 0 || | ||
2386 | (r = sshbuf_put_u32(b, enc->enabled)) != 0 || | ||
2387 | (r = sshbuf_put_u32(b, enc->block_size)) != 0 || | ||
2388 | (r = sshbuf_put_string(b, enc->key, enc->key_len)) != 0 || | ||
2389 | (r = sshbuf_put_string(b, enc->iv, enc->iv_len)) != 0) | ||
2390 | goto out; | ||
2391 | if (cipher_authlen(enc->cipher) == 0) { | ||
2392 | if ((r = sshbuf_put_cstring(b, mac->name)) != 0 || | ||
2393 | (r = sshbuf_put_u32(b, mac->enabled)) != 0 || | ||
2394 | (r = sshbuf_put_string(b, mac->key, mac->key_len)) != 0) | ||
2395 | goto out; | ||
2396 | } | ||
2397 | if ((r = sshbuf_put_u32(b, comp->type)) != 0 || | ||
2398 | (r = sshbuf_put_u32(b, comp->enabled)) != 0 || | ||
2399 | (r = sshbuf_put_cstring(b, comp->name)) != 0) | ||
2400 | goto out; | ||
2401 | r = sshbuf_put_stringb(m, b); | ||
2402 | out: | ||
2403 | if (b != NULL) | ||
2404 | sshbuf_free(b); | ||
2405 | return r; | ||
2406 | } | ||
2407 | |||
2408 | /* serialize packet state into a blob */ | ||
2409 | int | ||
2410 | ssh_packet_get_state(struct ssh *ssh, struct sshbuf *m) | ||
2411 | { | ||
2412 | struct session_state *state = ssh->state; | ||
2413 | u_char *p; | ||
2414 | size_t slen, rlen; | ||
2415 | int r, ssh1cipher; | ||
2416 | |||
2417 | if (!compat20) { | ||
2418 | ssh1cipher = cipher_get_number(state->receive_context.cipher); | ||
2419 | slen = cipher_get_keyiv_len(&state->send_context); | ||
2420 | rlen = cipher_get_keyiv_len(&state->receive_context); | ||
2421 | if ((r = sshbuf_put_u32(m, state->remote_protocol_flags)) != 0 || | ||
2422 | (r = sshbuf_put_u32(m, ssh1cipher)) != 0 || | ||
2423 | (r = sshbuf_put_string(m, state->ssh1_key, state->ssh1_keylen)) != 0 || | ||
2424 | (r = sshbuf_put_u32(m, slen)) != 0 || | ||
2425 | (r = sshbuf_reserve(m, slen, &p)) != 0 || | ||
2426 | (r = cipher_get_keyiv(&state->send_context, p, slen)) != 0 || | ||
2427 | (r = sshbuf_put_u32(m, rlen)) != 0 || | ||
2428 | (r = sshbuf_reserve(m, rlen, &p)) != 0 || | ||
2429 | (r = cipher_get_keyiv(&state->receive_context, p, rlen)) != 0) | ||
2430 | return r; | ||
2431 | } else { | ||
2432 | if ((r = kex_to_blob(m, ssh->kex)) != 0 || | ||
2433 | (r = newkeys_to_blob(m, ssh, MODE_OUT)) != 0 || | ||
2434 | (r = newkeys_to_blob(m, ssh, MODE_IN)) != 0 || | ||
2435 | (r = sshbuf_put_u32(m, state->rekey_limit)) != 0 || | ||
2436 | (r = sshbuf_put_u32(m, state->rekey_interval)) != 0 || | ||
2437 | (r = sshbuf_put_u32(m, state->p_send.seqnr)) != 0 || | ||
2438 | (r = sshbuf_put_u64(m, state->p_send.blocks)) != 0 || | ||
2439 | (r = sshbuf_put_u32(m, state->p_send.packets)) != 0 || | ||
2440 | (r = sshbuf_put_u64(m, state->p_send.bytes)) != 0 || | ||
2441 | (r = sshbuf_put_u32(m, state->p_read.seqnr)) != 0 || | ||
2442 | (r = sshbuf_put_u64(m, state->p_read.blocks)) != 0 || | ||
2443 | (r = sshbuf_put_u32(m, state->p_read.packets)) != 0 || | ||
2444 | (r = sshbuf_put_u64(m, state->p_read.bytes)) != 0) | ||
2445 | return r; | ||
2446 | } | ||
2447 | |||
2448 | slen = cipher_get_keycontext(&state->send_context, NULL); | ||
2449 | rlen = cipher_get_keycontext(&state->receive_context, NULL); | ||
2450 | if ((r = sshbuf_put_u32(m, slen)) != 0 || | ||
2451 | (r = sshbuf_reserve(m, slen, &p)) != 0) | ||
2452 | return r; | ||
2453 | if (cipher_get_keycontext(&state->send_context, p) != (int)slen) | ||
2454 | return SSH_ERR_INTERNAL_ERROR; | ||
2455 | if ((r = sshbuf_put_u32(m, rlen)) != 0 || | ||
2456 | (r = sshbuf_reserve(m, rlen, &p)) != 0) | ||
2457 | return r; | ||
2458 | if (cipher_get_keycontext(&state->receive_context, p) != (int)rlen) | ||
2459 | return SSH_ERR_INTERNAL_ERROR; | ||
2460 | |||
2461 | if ((r = ssh_packet_get_compress_state(m, ssh)) != 0 || | ||
2462 | (r = sshbuf_put_stringb(m, state->input)) != 0 || | ||
2463 | (r = sshbuf_put_stringb(m, state->output)) != 0) | ||
2464 | return r; | ||
2465 | |||
2466 | if (compat20) { | ||
2467 | if ((r = sshbuf_put_u64(m, get_sent_bytes())) != 0 || | ||
2468 | (r = sshbuf_put_u64(m, get_recv_bytes())) != 0) | ||
2469 | return r; | ||
2470 | } | ||
2471 | return 0; | ||
2472 | } | ||
2473 | |||
2474 | /* restore key exchange results from blob for packet state de-serialization */ | ||
2475 | static int | ||
2476 | newkeys_from_blob(struct sshbuf *m, struct ssh *ssh, int mode) | ||
2477 | { | ||
2478 | struct sshbuf *b = NULL; | ||
2479 | struct sshcomp *comp; | ||
2480 | struct sshenc *enc; | ||
2481 | struct sshmac *mac; | ||
2482 | struct newkeys *newkey = NULL; | ||
2483 | size_t keylen, ivlen, maclen; | ||
2484 | int r; | ||
2485 | |||
2486 | if ((newkey = calloc(1, sizeof(*newkey))) == NULL) { | ||
2487 | r = SSH_ERR_ALLOC_FAIL; | ||
2488 | goto out; | ||
2489 | } | ||
2490 | if ((r = sshbuf_froms(m, &b)) != 0) | ||
2491 | goto out; | ||
2492 | #ifdef DEBUG_PK | ||
2493 | sshbuf_dump(b, stderr); | ||
2494 | #endif | ||
2495 | enc = &newkey->enc; | ||
2496 | mac = &newkey->mac; | ||
2497 | comp = &newkey->comp; | ||
2498 | |||
2499 | if ((r = sshbuf_get_cstring(b, &enc->name, NULL)) != 0 || | ||
2500 | (r = sshbuf_get(b, &enc->cipher, sizeof(enc->cipher))) != 0 || | ||
2501 | (r = sshbuf_get_u32(b, (u_int *)&enc->enabled)) != 0 || | ||
2502 | (r = sshbuf_get_u32(b, &enc->block_size)) != 0 || | ||
2503 | (r = sshbuf_get_string(b, &enc->key, &keylen)) != 0 || | ||
2504 | (r = sshbuf_get_string(b, &enc->iv, &ivlen)) != 0) | ||
2505 | goto out; | ||
2506 | if (cipher_authlen(enc->cipher) == 0) { | ||
2507 | if ((r = sshbuf_get_cstring(b, &mac->name, NULL)) != 0) | ||
2508 | goto out; | ||
2509 | if ((r = mac_setup(mac, mac->name)) != 0) | ||
2510 | goto out; | ||
2511 | if ((r = sshbuf_get_u32(b, (u_int *)&mac->enabled)) != 0 || | ||
2512 | (r = sshbuf_get_string(b, &mac->key, &maclen)) != 0) | ||
2513 | goto out; | ||
2514 | if (maclen > mac->key_len) { | ||
2515 | r = SSH_ERR_INVALID_FORMAT; | ||
2516 | goto out; | ||
2517 | } | ||
2518 | mac->key_len = maclen; | ||
2519 | } | ||
2520 | if ((r = sshbuf_get_u32(b, &comp->type)) != 0 || | ||
2521 | (r = sshbuf_get_u32(b, (u_int *)&comp->enabled)) != 0 || | ||
2522 | (r = sshbuf_get_cstring(b, &comp->name, NULL)) != 0) | ||
2523 | goto out; | ||
2524 | if (enc->name == NULL || | ||
2525 | cipher_by_name(enc->name) != enc->cipher) { | ||
2526 | r = SSH_ERR_INVALID_FORMAT; | ||
2527 | goto out; | ||
2528 | } | ||
2529 | if (sshbuf_len(b) != 0) { | ||
2530 | r = SSH_ERR_INVALID_FORMAT; | ||
2531 | goto out; | ||
2532 | } | ||
2533 | enc->key_len = keylen; | ||
2534 | enc->iv_len = ivlen; | ||
2535 | ssh->kex->newkeys[mode] = newkey; | ||
2536 | newkey = NULL; | ||
2537 | r = 0; | ||
2538 | out: | ||
2539 | if (newkey != NULL) | ||
2540 | free(newkey); | ||
2541 | if (b != NULL) | ||
2542 | sshbuf_free(b); | ||
2543 | return r; | ||
2544 | } | ||
2545 | |||
2546 | /* restore kex from blob for packet state de-serialization */ | ||
2547 | static int | ||
2548 | kex_from_blob(struct sshbuf *m, struct kex **kexp) | ||
2549 | { | ||
2550 | struct kex *kex; | ||
2551 | int r; | ||
2552 | |||
2553 | if ((kex = calloc(1, sizeof(struct kex))) == NULL || | ||
2554 | (kex->my = sshbuf_new()) == NULL || | ||
2555 | (kex->peer = sshbuf_new()) == NULL) { | ||
2556 | r = SSH_ERR_ALLOC_FAIL; | ||
2557 | goto out; | ||
2558 | } | ||
2559 | if ((r = sshbuf_get_string(m, &kex->session_id, &kex->session_id_len)) != 0 || | ||
2560 | (r = sshbuf_get_u32(m, &kex->we_need)) != 0 || | ||
2561 | (r = sshbuf_get_u32(m, (u_int *)&kex->hostkey_type)) != 0 || | ||
2562 | (r = sshbuf_get_u32(m, &kex->kex_type)) != 0 || | ||
2563 | (r = sshbuf_get_stringb(m, kex->my)) != 0 || | ||
2564 | (r = sshbuf_get_stringb(m, kex->peer)) != 0 || | ||
2565 | (r = sshbuf_get_u32(m, &kex->flags)) != 0 || | ||
2566 | (r = sshbuf_get_cstring(m, &kex->client_version_string, NULL)) != 0 || | ||
2567 | (r = sshbuf_get_cstring(m, &kex->server_version_string, NULL)) != 0) | ||
2568 | goto out; | ||
2569 | kex->server = 1; | ||
2570 | kex->done = 1; | ||
2571 | r = 0; | ||
2572 | out: | ||
2573 | if (r != 0 || kexp == NULL) { | ||
2574 | if (kex != NULL) { | ||
2575 | if (kex->my != NULL) | ||
2576 | sshbuf_free(kex->my); | ||
2577 | if (kex->peer != NULL) | ||
2578 | sshbuf_free(kex->peer); | ||
2579 | free(kex); | ||
2580 | } | ||
2581 | if (kexp != NULL) | ||
2582 | *kexp = NULL; | ||
2583 | } else { | ||
2584 | *kexp = kex; | ||
2585 | } | ||
2586 | return r; | ||
2587 | } | ||
2588 | |||
2589 | /* | ||
2590 | * Restore packet state from content of blob 'm' (de-serialization). | ||
2591 | * Note that 'm' will be partially consumed on parsing or any other errors. | ||
2592 | */ | ||
2593 | int | ||
2594 | ssh_packet_set_state(struct ssh *ssh, struct sshbuf *m) | ||
2595 | { | ||
2596 | struct session_state *state = ssh->state; | ||
2597 | const u_char *ssh1key, *ivin, *ivout, *keyin, *keyout, *input, *output; | ||
2598 | size_t ssh1keylen, rlen, slen, ilen, olen; | ||
2599 | int r; | ||
2600 | u_int ssh1cipher = 0; | ||
2601 | u_int64_t sent_bytes = 0, recv_bytes = 0; | ||
2602 | |||
2603 | if (!compat20) { | ||
2604 | if ((r = sshbuf_get_u32(m, &state->remote_protocol_flags)) != 0 || | ||
2605 | (r = sshbuf_get_u32(m, &ssh1cipher)) != 0 || | ||
2606 | (r = sshbuf_get_string_direct(m, &ssh1key, &ssh1keylen)) != 0 || | ||
2607 | (r = sshbuf_get_string_direct(m, &ivout, &slen)) != 0 || | ||
2608 | (r = sshbuf_get_string_direct(m, &ivin, &rlen)) != 0) | ||
2609 | return r; | ||
2610 | if (ssh1cipher > INT_MAX) | ||
2611 | return SSH_ERR_KEY_UNKNOWN_CIPHER; | ||
2612 | ssh_packet_set_encryption_key(ssh, ssh1key, ssh1keylen, | ||
2613 | (int)ssh1cipher); | ||
2614 | if (cipher_get_keyiv_len(&state->send_context) != (int)slen || | ||
2615 | cipher_get_keyiv_len(&state->receive_context) != (int)rlen) | ||
2616 | return SSH_ERR_INVALID_FORMAT; | ||
2617 | if ((r = cipher_set_keyiv(&state->send_context, ivout)) != 0 || | ||
2618 | (r = cipher_set_keyiv(&state->receive_context, ivin)) != 0) | ||
2619 | return r; | ||
2620 | } else { | ||
2621 | if ((r = kex_from_blob(m, &ssh->kex)) != 0 || | ||
2622 | (r = newkeys_from_blob(m, ssh, MODE_OUT)) != 0 || | ||
2623 | (r = newkeys_from_blob(m, ssh, MODE_IN)) != 0 || | ||
2624 | (r = sshbuf_get_u32(m, &state->rekey_limit)) != 0 || | ||
2625 | (r = sshbuf_get_u32(m, &state->rekey_interval)) != 0 || | ||
2626 | (r = sshbuf_get_u32(m, &state->p_send.seqnr)) != 0 || | ||
2627 | (r = sshbuf_get_u64(m, &state->p_send.blocks)) != 0 || | ||
2628 | (r = sshbuf_get_u32(m, &state->p_send.packets)) != 0 || | ||
2629 | (r = sshbuf_get_u64(m, &state->p_send.bytes)) != 0 || | ||
2630 | (r = sshbuf_get_u32(m, &state->p_read.seqnr)) != 0 || | ||
2631 | (r = sshbuf_get_u64(m, &state->p_read.blocks)) != 0 || | ||
2632 | (r = sshbuf_get_u32(m, &state->p_read.packets)) != 0 || | ||
2633 | (r = sshbuf_get_u64(m, &state->p_read.bytes)) != 0) | ||
2634 | return r; | ||
2635 | /* | ||
2636 | * We set the time here so that in post-auth privsep slave we | ||
2637 | * count from the completion of the authentication. | ||
2638 | */ | ||
2639 | state->rekey_time = monotime(); | ||
2640 | /* XXX ssh_set_newkeys overrides p_read.packets? XXX */ | ||
2641 | if ((r = ssh_set_newkeys(ssh, MODE_IN)) != 0 || | ||
2642 | (r = ssh_set_newkeys(ssh, MODE_OUT)) != 0) | ||
2643 | return r; | ||
2644 | } | ||
2645 | if ((r = sshbuf_get_string_direct(m, &keyout, &slen)) != 0 || | ||
2646 | (r = sshbuf_get_string_direct(m, &keyin, &rlen)) != 0) | ||
2647 | return r; | ||
2648 | if (cipher_get_keycontext(&state->send_context, NULL) != (int)slen || | ||
2649 | cipher_get_keycontext(&state->receive_context, NULL) != (int)rlen) | ||
2650 | return SSH_ERR_INVALID_FORMAT; | ||
2651 | cipher_set_keycontext(&state->send_context, keyout); | ||
2652 | cipher_set_keycontext(&state->receive_context, keyin); | ||
2653 | |||
2654 | if ((r = ssh_packet_set_compress_state(ssh, m)) != 0 || | ||
2655 | (r = ssh_packet_set_postauth(ssh)) != 0) | ||
2656 | return r; | ||
2657 | |||
2658 | sshbuf_reset(state->input); | ||
2659 | sshbuf_reset(state->output); | ||
2660 | if ((r = sshbuf_get_string_direct(m, &input, &ilen)) != 0 || | ||
2661 | (r = sshbuf_get_string_direct(m, &output, &olen)) != 0 || | ||
2662 | (r = sshbuf_put(state->input, input, ilen)) != 0 || | ||
2663 | (r = sshbuf_put(state->output, output, olen)) != 0) | ||
2664 | return r; | ||
2665 | |||
2666 | if (compat20) { | ||
2667 | if ((r = sshbuf_get_u64(m, &sent_bytes)) != 0 || | ||
2668 | (r = sshbuf_get_u64(m, &recv_bytes)) != 0) | ||
2669 | return r; | ||
2670 | roam_set_bytes(sent_bytes, recv_bytes); | ||
2090 | } | 2671 | } |
2672 | if (sshbuf_len(m)) | ||
2673 | return SSH_ERR_INVALID_FORMAT; | ||
2674 | debug3("%s: done", __func__); | ||
2675 | return 0; | ||
2676 | } | ||
2677 | |||
2678 | /* NEW API */ | ||
2679 | |||
2680 | /* put data to the outgoing packet */ | ||
2681 | |||
2682 | int | ||
2683 | sshpkt_put(struct ssh *ssh, const void *v, size_t len) | ||
2684 | { | ||
2685 | return sshbuf_put(ssh->state->outgoing_packet, v, len); | ||
2686 | } | ||
2687 | |||
2688 | int | ||
2689 | sshpkt_putb(struct ssh *ssh, const struct sshbuf *b) | ||
2690 | { | ||
2691 | return sshbuf_putb(ssh->state->outgoing_packet, b); | ||
2692 | } | ||
2693 | |||
2694 | int | ||
2695 | sshpkt_put_u8(struct ssh *ssh, u_char val) | ||
2696 | { | ||
2697 | return sshbuf_put_u8(ssh->state->outgoing_packet, val); | ||
2698 | } | ||
2699 | |||
2700 | int | ||
2701 | sshpkt_put_u32(struct ssh *ssh, u_int32_t val) | ||
2702 | { | ||
2703 | return sshbuf_put_u32(ssh->state->outgoing_packet, val); | ||
2704 | } | ||
2705 | |||
2706 | int | ||
2707 | sshpkt_put_u64(struct ssh *ssh, u_int64_t val) | ||
2708 | { | ||
2709 | return sshbuf_put_u64(ssh->state->outgoing_packet, val); | ||
2710 | } | ||
2711 | |||
2712 | int | ||
2713 | sshpkt_put_string(struct ssh *ssh, const void *v, size_t len) | ||
2714 | { | ||
2715 | return sshbuf_put_string(ssh->state->outgoing_packet, v, len); | ||
2716 | } | ||
2717 | |||
2718 | int | ||
2719 | sshpkt_put_cstring(struct ssh *ssh, const void *v) | ||
2720 | { | ||
2721 | return sshbuf_put_cstring(ssh->state->outgoing_packet, v); | ||
2722 | } | ||
2723 | |||
2724 | int | ||
2725 | sshpkt_put_stringb(struct ssh *ssh, const struct sshbuf *v) | ||
2726 | { | ||
2727 | return sshbuf_put_stringb(ssh->state->outgoing_packet, v); | ||
2728 | } | ||
2729 | |||
2730 | #if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) | ||
2731 | int | ||
2732 | sshpkt_put_ec(struct ssh *ssh, const EC_POINT *v, const EC_GROUP *g) | ||
2733 | { | ||
2734 | return sshbuf_put_ec(ssh->state->outgoing_packet, v, g); | ||
2735 | } | ||
2736 | #endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */ | ||
2737 | |||
2738 | #ifdef WITH_SSH1 | ||
2739 | int | ||
2740 | sshpkt_put_bignum1(struct ssh *ssh, const BIGNUM *v) | ||
2741 | { | ||
2742 | return sshbuf_put_bignum1(ssh->state->outgoing_packet, v); | ||
2743 | } | ||
2744 | #endif /* WITH_SSH1 */ | ||
2745 | |||
2746 | #ifdef WITH_OPENSSL | ||
2747 | int | ||
2748 | sshpkt_put_bignum2(struct ssh *ssh, const BIGNUM *v) | ||
2749 | { | ||
2750 | return sshbuf_put_bignum2(ssh->state->outgoing_packet, v); | ||
2751 | } | ||
2752 | #endif /* WITH_OPENSSL */ | ||
2753 | |||
2754 | /* fetch data from the incoming packet */ | ||
2755 | |||
2756 | int | ||
2757 | sshpkt_get(struct ssh *ssh, void *valp, size_t len) | ||
2758 | { | ||
2759 | return sshbuf_get(ssh->state->incoming_packet, valp, len); | ||
2760 | } | ||
2761 | |||
2762 | int | ||
2763 | sshpkt_get_u8(struct ssh *ssh, u_char *valp) | ||
2764 | { | ||
2765 | return sshbuf_get_u8(ssh->state->incoming_packet, valp); | ||
2766 | } | ||
2767 | |||
2768 | int | ||
2769 | sshpkt_get_u32(struct ssh *ssh, u_int32_t *valp) | ||
2770 | { | ||
2771 | return sshbuf_get_u32(ssh->state->incoming_packet, valp); | ||
2772 | } | ||
2773 | |||
2774 | int | ||
2775 | sshpkt_get_u64(struct ssh *ssh, u_int64_t *valp) | ||
2776 | { | ||
2777 | return sshbuf_get_u64(ssh->state->incoming_packet, valp); | ||
2778 | } | ||
2779 | |||
2780 | int | ||
2781 | sshpkt_get_string(struct ssh *ssh, u_char **valp, size_t *lenp) | ||
2782 | { | ||
2783 | return sshbuf_get_string(ssh->state->incoming_packet, valp, lenp); | ||
2784 | } | ||
2785 | |||
2786 | int | ||
2787 | sshpkt_get_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp) | ||
2788 | { | ||
2789 | return sshbuf_get_string_direct(ssh->state->incoming_packet, valp, lenp); | ||
2790 | } | ||
2791 | |||
2792 | int | ||
2793 | sshpkt_get_cstring(struct ssh *ssh, char **valp, size_t *lenp) | ||
2794 | { | ||
2795 | return sshbuf_get_cstring(ssh->state->incoming_packet, valp, lenp); | ||
2796 | } | ||
2797 | |||
2798 | #if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) | ||
2799 | int | ||
2800 | sshpkt_get_ec(struct ssh *ssh, EC_POINT *v, const EC_GROUP *g) | ||
2801 | { | ||
2802 | return sshbuf_get_ec(ssh->state->incoming_packet, v, g); | ||
2803 | } | ||
2804 | #endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */ | ||
2805 | |||
2806 | #ifdef WITH_SSH1 | ||
2807 | int | ||
2808 | sshpkt_get_bignum1(struct ssh *ssh, BIGNUM *v) | ||
2809 | { | ||
2810 | return sshbuf_get_bignum1(ssh->state->incoming_packet, v); | ||
2811 | } | ||
2812 | #endif /* WITH_SSH1 */ | ||
2813 | |||
2814 | #ifdef WITH_OPENSSL | ||
2815 | int | ||
2816 | sshpkt_get_bignum2(struct ssh *ssh, BIGNUM *v) | ||
2817 | { | ||
2818 | return sshbuf_get_bignum2(ssh->state->incoming_packet, v); | ||
2819 | } | ||
2820 | #endif /* WITH_OPENSSL */ | ||
2821 | |||
2822 | int | ||
2823 | sshpkt_get_end(struct ssh *ssh) | ||
2824 | { | ||
2825 | if (sshbuf_len(ssh->state->incoming_packet) > 0) | ||
2826 | return SSH_ERR_UNEXPECTED_TRAILING_DATA; | ||
2827 | return 0; | ||
2828 | } | ||
2829 | |||
2830 | const u_char * | ||
2831 | sshpkt_ptr(struct ssh *ssh, size_t *lenp) | ||
2832 | { | ||
2833 | if (lenp != NULL) | ||
2834 | *lenp = sshbuf_len(ssh->state->incoming_packet); | ||
2835 | return sshbuf_ptr(ssh->state->incoming_packet); | ||
2836 | } | ||
2837 | |||
2838 | /* start a new packet */ | ||
2839 | |||
2840 | int | ||
2841 | sshpkt_start(struct ssh *ssh, u_char type) | ||
2842 | { | ||
2843 | u_char buf[9]; | ||
2844 | int len; | ||
2845 | |||
2846 | DBG(debug("packet_start[%d]", type)); | ||
2847 | len = compat20 ? 6 : 9; | ||
2848 | memset(buf, 0, len - 1); | ||
2849 | buf[len - 1] = type; | ||
2850 | sshbuf_reset(ssh->state->outgoing_packet); | ||
2851 | return sshbuf_put(ssh->state->outgoing_packet, buf, len); | ||
2852 | } | ||
2853 | |||
2854 | /* send it */ | ||
2855 | |||
2856 | int | ||
2857 | sshpkt_send(struct ssh *ssh) | ||
2858 | { | ||
2859 | if (compat20) | ||
2860 | return ssh_packet_send2(ssh); | ||
2861 | else | ||
2862 | return ssh_packet_send1(ssh); | ||
2863 | } | ||
2864 | |||
2865 | int | ||
2866 | sshpkt_disconnect(struct ssh *ssh, const char *fmt,...) | ||
2867 | { | ||
2868 | char buf[1024]; | ||
2869 | va_list args; | ||
2870 | int r; | ||
2871 | |||
2872 | va_start(args, fmt); | ||
2873 | vsnprintf(buf, sizeof(buf), fmt, args); | ||
2874 | va_end(args); | ||
2875 | |||
2876 | if (compat20) { | ||
2877 | if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT)) != 0 || | ||
2878 | (r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_PROTOCOL_ERROR)) != 0 || | ||
2879 | (r = sshpkt_put_cstring(ssh, buf)) != 0 || | ||
2880 | (r = sshpkt_put_cstring(ssh, "")) != 0 || | ||
2881 | (r = sshpkt_send(ssh)) != 0) | ||
2882 | return r; | ||
2883 | } else { | ||
2884 | if ((r = sshpkt_start(ssh, SSH_MSG_DISCONNECT)) != 0 || | ||
2885 | (r = sshpkt_put_cstring(ssh, buf)) != 0 || | ||
2886 | (r = sshpkt_send(ssh)) != 0) | ||
2887 | return r; | ||
2888 | } | ||
2889 | return 0; | ||
2890 | } | ||
2891 | |||
2892 | /* roundup current message to pad bytes */ | ||
2893 | int | ||
2894 | sshpkt_add_padding(struct ssh *ssh, u_char pad) | ||
2895 | { | ||
2896 | ssh->state->extra_pad = pad; | ||
2897 | return 0; | ||
2091 | } | 2898 | } |