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