GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* $OpenBSD: packet.c,v 1.264 2017/09/12 06:32:07 djm Exp $ */ |
||
2 |
/* |
||
3 |
* Author: Tatu Ylonen <ylo@cs.hut.fi> |
||
4 |
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
||
5 |
* All rights reserved |
||
6 |
* This file contains code implementing the packet protocol and communication |
||
7 |
* with the other side. This same code is used both on client and server side. |
||
8 |
* |
||
9 |
* As far as I am concerned, the code I have written for this software |
||
10 |
* can be used freely for any purpose. Any derived versions of this |
||
11 |
* software must be clearly marked as such, and if the derived work is |
||
12 |
* incompatible with the protocol description in the RFC file, it must be |
||
13 |
* called by a name other than "ssh" or "Secure Shell". |
||
14 |
* |
||
15 |
* |
||
16 |
* SSH2 packet format added by Markus Friedl. |
||
17 |
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. |
||
18 |
* |
||
19 |
* Redistribution and use in source and binary forms, with or without |
||
20 |
* modification, are permitted provided that the following conditions |
||
21 |
* are met: |
||
22 |
* 1. Redistributions of source code must retain the above copyright |
||
23 |
* notice, this list of conditions and the following disclaimer. |
||
24 |
* 2. Redistributions in binary form must reproduce the above copyright |
||
25 |
* notice, this list of conditions and the following disclaimer in the |
||
26 |
* documentation and/or other materials provided with the distribution. |
||
27 |
* |
||
28 |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
||
29 |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
||
30 |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
||
31 |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
||
32 |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
||
33 |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||
34 |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||
35 |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||
36 |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
||
37 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
38 |
*/ |
||
39 |
|||
40 |
#include <sys/types.h> |
||
41 |
#include <sys/queue.h> |
||
42 |
#include <sys/socket.h> |
||
43 |
#include <sys/time.h> |
||
44 |
#include <netinet/in.h> |
||
45 |
#include <netinet/ip.h> |
||
46 |
|||
47 |
#include <errno.h> |
||
48 |
#include <netdb.h> |
||
49 |
#include <stdarg.h> |
||
50 |
#include <stdio.h> |
||
51 |
#include <stdlib.h> |
||
52 |
#include <string.h> |
||
53 |
#include <unistd.h> |
||
54 |
#include <limits.h> |
||
55 |
#include <signal.h> |
||
56 |
#include <time.h> |
||
57 |
|||
58 |
#include <zlib.h> |
||
59 |
|||
60 |
#include "buffer.h" /* typedefs XXX */ |
||
61 |
#include "key.h" /* typedefs XXX */ |
||
62 |
|||
63 |
#include "xmalloc.h" |
||
64 |
#include "crc32.h" |
||
65 |
#include "compat.h" |
||
66 |
#include "ssh2.h" |
||
67 |
#include "cipher.h" |
||
68 |
#include "sshkey.h" |
||
69 |
#include "kex.h" |
||
70 |
#include "digest.h" |
||
71 |
#include "mac.h" |
||
72 |
#include "log.h" |
||
73 |
#include "canohost.h" |
||
74 |
#include "misc.h" |
||
75 |
#include "channels.h" |
||
76 |
#include "ssh.h" |
||
77 |
#include "packet.h" |
||
78 |
#include "ssherr.h" |
||
79 |
#include "sshbuf.h" |
||
80 |
|||
81 |
#ifdef PACKET_DEBUG |
||
82 |
#define DBG(x) x |
||
83 |
#else |
||
84 |
#define DBG(x) |
||
85 |
#endif |
||
86 |
|||
87 |
#define PACKET_MAX_SIZE (256 * 1024) |
||
88 |
|||
89 |
struct packet_state { |
||
90 |
u_int32_t seqnr; |
||
91 |
u_int32_t packets; |
||
92 |
u_int64_t blocks; |
||
93 |
u_int64_t bytes; |
||
94 |
}; |
||
95 |
|||
96 |
struct packet { |
||
97 |
TAILQ_ENTRY(packet) next; |
||
98 |
u_char type; |
||
99 |
struct sshbuf *payload; |
||
100 |
}; |
||
101 |
|||
102 |
struct session_state { |
||
103 |
/* |
||
104 |
* This variable contains the file descriptors used for |
||
105 |
* communicating with the other side. connection_in is used for |
||
106 |
* reading; connection_out for writing. These can be the same |
||
107 |
* descriptor, in which case it is assumed to be a socket. |
||
108 |
*/ |
||
109 |
int connection_in; |
||
110 |
int connection_out; |
||
111 |
|||
112 |
/* Protocol flags for the remote side. */ |
||
113 |
u_int remote_protocol_flags; |
||
114 |
|||
115 |
/* Encryption context for receiving data. Only used for decryption. */ |
||
116 |
struct sshcipher_ctx *receive_context; |
||
117 |
|||
118 |
/* Encryption context for sending data. Only used for encryption. */ |
||
119 |
struct sshcipher_ctx *send_context; |
||
120 |
|||
121 |
/* Buffer for raw input data from the socket. */ |
||
122 |
struct sshbuf *input; |
||
123 |
|||
124 |
/* Buffer for raw output data going to the socket. */ |
||
125 |
struct sshbuf *output; |
||
126 |
|||
127 |
/* Buffer for the partial outgoing packet being constructed. */ |
||
128 |
struct sshbuf *outgoing_packet; |
||
129 |
|||
130 |
/* Buffer for the incoming packet currently being processed. */ |
||
131 |
struct sshbuf *incoming_packet; |
||
132 |
|||
133 |
/* Scratch buffer for packet compression/decompression. */ |
||
134 |
struct sshbuf *compression_buffer; |
||
135 |
|||
136 |
/* Incoming/outgoing compression dictionaries */ |
||
137 |
z_stream compression_in_stream; |
||
138 |
z_stream compression_out_stream; |
||
139 |
int compression_in_started; |
||
140 |
int compression_out_started; |
||
141 |
int compression_in_failures; |
||
142 |
int compression_out_failures; |
||
143 |
|||
144 |
/* |
||
145 |
* Flag indicating whether packet compression/decompression is |
||
146 |
* enabled. |
||
147 |
*/ |
||
148 |
int packet_compression; |
||
149 |
|||
150 |
/* default maximum packet size */ |
||
151 |
u_int max_packet_size; |
||
152 |
|||
153 |
/* Flag indicating whether this module has been initialized. */ |
||
154 |
int initialized; |
||
155 |
|||
156 |
/* Set to true if the connection is interactive. */ |
||
157 |
int interactive_mode; |
||
158 |
|||
159 |
/* Set to true if we are the server side. */ |
||
160 |
int server_side; |
||
161 |
|||
162 |
/* Set to true if we are authenticated. */ |
||
163 |
int after_authentication; |
||
164 |
|||
165 |
int keep_alive_timeouts; |
||
166 |
|||
167 |
/* The maximum time that we will wait to send or receive a packet */ |
||
168 |
int packet_timeout_ms; |
||
169 |
|||
170 |
/* Session key information for Encryption and MAC */ |
||
171 |
struct newkeys *newkeys[MODE_MAX]; |
||
172 |
struct packet_state p_read, p_send; |
||
173 |
|||
174 |
/* Volume-based rekeying */ |
||
175 |
u_int64_t max_blocks_in, max_blocks_out, rekey_limit; |
||
176 |
|||
177 |
/* Time-based rekeying */ |
||
178 |
u_int32_t rekey_interval; /* how often in seconds */ |
||
179 |
time_t rekey_time; /* time of last rekeying */ |
||
180 |
|||
181 |
/* roundup current message to extra_pad bytes */ |
||
182 |
u_char extra_pad; |
||
183 |
|||
184 |
/* XXX discard incoming data after MAC error */ |
||
185 |
u_int packet_discard; |
||
186 |
size_t packet_discard_mac_already; |
||
187 |
struct sshmac *packet_discard_mac; |
||
188 |
|||
189 |
/* Used in packet_read_poll2() */ |
||
190 |
u_int packlen; |
||
191 |
|||
192 |
/* Used in packet_send2 */ |
||
193 |
int rekeying; |
||
194 |
|||
195 |
/* Used in ssh_packet_send_mux() */ |
||
196 |
int mux; |
||
197 |
|||
198 |
/* Used in packet_set_interactive */ |
||
199 |
int set_interactive_called; |
||
200 |
|||
201 |
/* Used in packet_set_maxsize */ |
||
202 |
int set_maxsize_called; |
||
203 |
|||
204 |
/* One-off warning about weak ciphers */ |
||
205 |
int cipher_warning_done; |
||
206 |
|||
207 |
/* Hook for fuzzing inbound packets */ |
||
208 |
ssh_packet_hook_fn *hook_in; |
||
209 |
void *hook_in_ctx; |
||
210 |
|||
211 |
TAILQ_HEAD(, packet) outgoing; |
||
212 |
}; |
||
213 |
|||
214 |
struct ssh * |
||
215 |
ssh_alloc_session_state(void) |
||
216 |
{ |
||
217 |
struct ssh *ssh = NULL; |
||
218 |
struct session_state *state = NULL; |
||
219 |
|||
220 |
✓✗✓✗ |
3 |
if ((ssh = calloc(1, sizeof(*ssh))) == NULL || |
221 |
✓✗ | 1 |
(state = calloc(1, sizeof(*state))) == NULL || |
222 |
✓✗ | 1 |
(state->input = sshbuf_new()) == NULL || |
223 |
✓✗ | 1 |
(state->output = sshbuf_new()) == NULL || |
224 |
✓✗ | 1 |
(state->outgoing_packet = sshbuf_new()) == NULL || |
225 |
1 |
(state->incoming_packet = sshbuf_new()) == NULL) |
|
226 |
goto fail; |
||
227 |
1 |
TAILQ_INIT(&state->outgoing); |
|
228 |
1 |
TAILQ_INIT(&ssh->private_keys); |
|
229 |
1 |
TAILQ_INIT(&ssh->public_keys); |
|
230 |
1 |
state->connection_in = -1; |
|
231 |
1 |
state->connection_out = -1; |
|
232 |
1 |
state->max_packet_size = 32768; |
|
233 |
1 |
state->packet_timeout_ms = -1; |
|
234 |
1 |
state->p_send.packets = state->p_read.packets = 0; |
|
235 |
1 |
state->initialized = 1; |
|
236 |
/* |
||
237 |
* ssh_packet_send2() needs to queue packets until |
||
238 |
* we've done the initial key exchange. |
||
239 |
*/ |
||
240 |
1 |
state->rekeying = 1; |
|
241 |
1 |
ssh->state = state; |
|
242 |
1 |
return ssh; |
|
243 |
fail: |
||
244 |
if (state) { |
||
245 |
sshbuf_free(state->input); |
||
246 |
sshbuf_free(state->output); |
||
247 |
sshbuf_free(state->incoming_packet); |
||
248 |
sshbuf_free(state->outgoing_packet); |
||
249 |
free(state); |
||
250 |
} |
||
251 |
free(ssh); |
||
252 |
return NULL; |
||
253 |
1 |
} |
|
254 |
|||
255 |
void |
||
256 |
ssh_packet_set_input_hook(struct ssh *ssh, ssh_packet_hook_fn *hook, void *ctx) |
||
257 |
{ |
||
258 |
ssh->state->hook_in = hook; |
||
259 |
ssh->state->hook_in_ctx = ctx; |
||
260 |
} |
||
261 |
|||
262 |
/* Returns nonzero if rekeying is in progress */ |
||
263 |
int |
||
264 |
ssh_packet_is_rekeying(struct ssh *ssh) |
||
265 |
{ |
||
266 |
✓✗ | 1053177 |
return ssh->state->rekeying || |
267 |
✓✗ | 702118 |
(ssh->kex != NULL && ssh->kex->done == 0); |
268 |
} |
||
269 |
|||
270 |
/* |
||
271 |
* Sets the descriptors used for communication. |
||
272 |
*/ |
||
273 |
struct ssh * |
||
274 |
ssh_packet_set_connection(struct ssh *ssh, int fd_in, int fd_out) |
||
275 |
{ |
||
276 |
struct session_state *state; |
||
277 |
2 |
const struct sshcipher *none = cipher_by_name("none"); |
|
278 |
int r; |
||
279 |
|||
280 |
✗✓ | 1 |
if (none == NULL) { |
281 |
error("%s: cannot load cipher 'none'", __func__); |
||
282 |
return NULL; |
||
283 |
} |
||
284 |
✗✓ | 1 |
if (ssh == NULL) |
285 |
ssh = ssh_alloc_session_state(); |
||
286 |
✗✓ | 1 |
if (ssh == NULL) { |
287 |
error("%s: cound not allocate state", __func__); |
||
288 |
return NULL; |
||
289 |
} |
||
290 |
1 |
state = ssh->state; |
|
291 |
1 |
state->connection_in = fd_in; |
|
292 |
1 |
state->connection_out = fd_out; |
|
293 |
✗✓ | 2 |
if ((r = cipher_init(&state->send_context, none, |
294 |
✓✗ | 1 |
(const u_char *)"", 0, NULL, 0, CIPHER_ENCRYPT)) != 0 || |
295 |
1 |
(r = cipher_init(&state->receive_context, none, |
|
296 |
1 |
(const u_char *)"", 0, NULL, 0, CIPHER_DECRYPT)) != 0) { |
|
297 |
error("%s: cipher_init failed: %s", __func__, ssh_err(r)); |
||
298 |
free(ssh); /* XXX need ssh_free_session_state? */ |
||
299 |
return NULL; |
||
300 |
} |
||
301 |
1 |
state->newkeys[MODE_IN] = state->newkeys[MODE_OUT] = NULL; |
|
302 |
/* |
||
303 |
* Cache the IP address of the remote connection for use in error |
||
304 |
* messages that might be generated after the connection has closed. |
||
305 |
*/ |
||
306 |
1 |
(void)ssh_remote_ipaddr(ssh); |
|
307 |
1 |
return ssh; |
|
308 |
1 |
} |
|
309 |
|||
310 |
void |
||
311 |
ssh_packet_set_timeout(struct ssh *ssh, int timeout, int count) |
||
312 |
{ |
||
313 |
2 |
struct session_state *state = ssh->state; |
|
314 |
|||
315 |
✓✗ | 1 |
if (timeout <= 0 || count <= 0) { |
316 |
1 |
state->packet_timeout_ms = -1; |
|
317 |
1 |
return; |
|
318 |
} |
||
319 |
if ((INT_MAX / 1000) / count < timeout) |
||
320 |
state->packet_timeout_ms = INT_MAX; |
||
321 |
else |
||
322 |
state->packet_timeout_ms = timeout * count * 1000; |
||
323 |
1 |
} |
|
324 |
|||
325 |
void |
||
326 |
ssh_packet_set_mux(struct ssh *ssh) |
||
327 |
{ |
||
328 |
ssh->state->mux = 1; |
||
329 |
ssh->state->rekeying = 0; |
||
330 |
} |
||
331 |
|||
332 |
int |
||
333 |
ssh_packet_get_mux(struct ssh *ssh) |
||
334 |
{ |
||
335 |
2 |
return ssh->state->mux; |
|
336 |
} |
||
337 |
|||
338 |
int |
||
339 |
ssh_packet_set_log_preamble(struct ssh *ssh, const char *fmt, ...) |
||
340 |
{ |
||
341 |
va_list args; |
||
342 |
int r; |
||
343 |
|||
344 |
free(ssh->log_preamble); |
||
345 |
if (fmt == NULL) |
||
346 |
ssh->log_preamble = NULL; |
||
347 |
else { |
||
348 |
va_start(args, fmt); |
||
349 |
r = vasprintf(&ssh->log_preamble, fmt, args); |
||
350 |
va_end(args); |
||
351 |
if (r < 0 || ssh->log_preamble == NULL) |
||
352 |
return SSH_ERR_ALLOC_FAIL; |
||
353 |
} |
||
354 |
return 0; |
||
355 |
} |
||
356 |
|||
357 |
int |
||
358 |
ssh_packet_stop_discard(struct ssh *ssh) |
||
359 |
{ |
||
360 |
struct session_state *state = ssh->state; |
||
361 |
int r; |
||
362 |
|||
363 |
if (state->packet_discard_mac) { |
||
364 |
char buf[1024]; |
||
365 |
size_t dlen = PACKET_MAX_SIZE; |
||
366 |
|||
367 |
if (dlen > state->packet_discard_mac_already) |
||
368 |
dlen -= state->packet_discard_mac_already; |
||
369 |
memset(buf, 'a', sizeof(buf)); |
||
370 |
while (sshbuf_len(state->incoming_packet) < dlen) |
||
371 |
if ((r = sshbuf_put(state->incoming_packet, buf, |
||
372 |
sizeof(buf))) != 0) |
||
373 |
return r; |
||
374 |
(void) mac_compute(state->packet_discard_mac, |
||
375 |
state->p_read.seqnr, |
||
376 |
sshbuf_ptr(state->incoming_packet), dlen, |
||
377 |
NULL, 0); |
||
378 |
} |
||
379 |
logit("Finished discarding for %.200s port %d", |
||
380 |
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); |
||
381 |
return SSH_ERR_MAC_INVALID; |
||
382 |
} |
||
383 |
|||
384 |
static int |
||
385 |
ssh_packet_start_discard(struct ssh *ssh, struct sshenc *enc, |
||
386 |
struct sshmac *mac, size_t mac_already, u_int discard) |
||
387 |
{ |
||
388 |
struct session_state *state = ssh->state; |
||
389 |
int r; |
||
390 |
|||
391 |
if (enc == NULL || !cipher_is_cbc(enc->cipher) || (mac && mac->etm)) { |
||
392 |
if ((r = sshpkt_disconnect(ssh, "Packet corrupt")) != 0) |
||
393 |
return r; |
||
394 |
return SSH_ERR_MAC_INVALID; |
||
395 |
} |
||
396 |
/* |
||
397 |
* Record number of bytes over which the mac has already |
||
398 |
* been computed in order to minimize timing attacks. |
||
399 |
*/ |
||
400 |
if (mac && mac->enabled) { |
||
401 |
state->packet_discard_mac = mac; |
||
402 |
state->packet_discard_mac_already = mac_already; |
||
403 |
} |
||
404 |
if (sshbuf_len(state->input) >= discard) |
||
405 |
return ssh_packet_stop_discard(ssh); |
||
406 |
state->packet_discard = discard - sshbuf_len(state->input); |
||
407 |
return 0; |
||
408 |
} |
||
409 |
|||
410 |
/* Returns 1 if remote host is connected via socket, 0 if not. */ |
||
411 |
|||
412 |
int |
||
413 |
ssh_packet_connection_is_on_socket(struct ssh *ssh) |
||
414 |
{ |
||
415 |
8 |
struct session_state *state = ssh->state; |
|
416 |
4 |
struct sockaddr_storage from, to; |
|
417 |
4 |
socklen_t fromlen, tolen; |
|
418 |
|||
419 |
✓✗✗✓ |
8 |
if (state->connection_in == -1 || state->connection_out == -1) |
420 |
return 0; |
||
421 |
|||
422 |
/* filedescriptors in and out are the same, so it's a socket */ |
||
423 |
✓✗ | 4 |
if (state->connection_in == state->connection_out) |
424 |
4 |
return 1; |
|
425 |
fromlen = sizeof(from); |
||
426 |
memset(&from, 0, sizeof(from)); |
||
427 |
if (getpeername(state->connection_in, (struct sockaddr *)&from, |
||
428 |
&fromlen) < 0) |
||
429 |
return 0; |
||
430 |
tolen = sizeof(to); |
||
431 |
memset(&to, 0, sizeof(to)); |
||
432 |
if (getpeername(state->connection_out, (struct sockaddr *)&to, |
||
433 |
&tolen) < 0) |
||
434 |
return 0; |
||
435 |
if (fromlen != tolen || memcmp(&from, &to, fromlen) != 0) |
||
436 |
return 0; |
||
437 |
if (from.ss_family != AF_INET && from.ss_family != AF_INET6) |
||
438 |
return 0; |
||
439 |
return 1; |
||
440 |
4 |
} |
|
441 |
|||
442 |
void |
||
443 |
ssh_packet_get_bytes(struct ssh *ssh, u_int64_t *ibytes, u_int64_t *obytes) |
||
444 |
{ |
||
445 |
✓✗ | 2 |
if (ibytes) |
446 |
1 |
*ibytes = ssh->state->p_read.bytes; |
|
447 |
✓✗ | 1 |
if (obytes) |
448 |
1 |
*obytes = ssh->state->p_send.bytes; |
|
449 |
1 |
} |
|
450 |
|||
451 |
int |
||
452 |
ssh_packet_connection_af(struct ssh *ssh) |
||
453 |
{ |
||
454 |
2 |
struct sockaddr_storage to; |
|
455 |
1 |
socklen_t tolen = sizeof(to); |
|
456 |
|||
457 |
1 |
memset(&to, 0, sizeof(to)); |
|
458 |
✗✓ | 2 |
if (getsockname(ssh->state->connection_out, (struct sockaddr *)&to, |
459 |
1 |
&tolen) < 0) |
|
460 |
return 0; |
||
461 |
1 |
return to.ss_family; |
|
462 |
1 |
} |
|
463 |
|||
464 |
/* Sets the connection into non-blocking mode. */ |
||
465 |
|||
466 |
void |
||
467 |
ssh_packet_set_nonblocking(struct ssh *ssh) |
||
468 |
{ |
||
469 |
/* Set the socket into non-blocking mode. */ |
||
470 |
2 |
set_nonblock(ssh->state->connection_in); |
|
471 |
|||
472 |
✗✓ | 1 |
if (ssh->state->connection_out != ssh->state->connection_in) |
473 |
set_nonblock(ssh->state->connection_out); |
||
474 |
1 |
} |
|
475 |
|||
476 |
/* Returns the socket used for reading. */ |
||
477 |
|||
478 |
int |
||
479 |
ssh_packet_get_connection_in(struct ssh *ssh) |
||
480 |
{ |
||
481 |
4 |
return ssh->state->connection_in; |
|
482 |
} |
||
483 |
|||
484 |
/* Returns the descriptor used for writing. */ |
||
485 |
|||
486 |
int |
||
487 |
ssh_packet_get_connection_out(struct ssh *ssh) |
||
488 |
{ |
||
489 |
4 |
return ssh->state->connection_out; |
|
490 |
} |
||
491 |
|||
492 |
/* |
||
493 |
* Returns the IP-address of the remote host as a string. The returned |
||
494 |
* string must not be freed. |
||
495 |
*/ |
||
496 |
|||
497 |
const char * |
||
498 |
ssh_remote_ipaddr(struct ssh *ssh) |
||
499 |
{ |
||
500 |
6 |
const int sock = ssh->state->connection_in; |
|
501 |
|||
502 |
/* Check whether we have cached the ipaddr. */ |
||
503 |
✓✓ | 3 |
if (ssh->remote_ipaddr == NULL) { |
504 |
✓✗ | 1 |
if (ssh_packet_connection_is_on_socket(ssh)) { |
505 |
1 |
ssh->remote_ipaddr = get_peer_ipaddr(sock); |
|
506 |
1 |
ssh->remote_port = get_peer_port(sock); |
|
507 |
1 |
ssh->local_ipaddr = get_local_ipaddr(sock); |
|
508 |
1 |
ssh->local_port = get_local_port(sock); |
|
509 |
1 |
} else { |
|
510 |
ssh->remote_ipaddr = strdup("UNKNOWN"); |
||
511 |
ssh->remote_port = 65535; |
||
512 |
ssh->local_ipaddr = strdup("UNKNOWN"); |
||
513 |
ssh->local_port = 65535; |
||
514 |
} |
||
515 |
1 |
} |
|
516 |
3 |
return ssh->remote_ipaddr; |
|
517 |
} |
||
518 |
|||
519 |
/* Returns the port number of the remote host. */ |
||
520 |
|||
521 |
int |
||
522 |
ssh_remote_port(struct ssh *ssh) |
||
523 |
{ |
||
524 |
2 |
(void)ssh_remote_ipaddr(ssh); /* Will lookup and cache. */ |
|
525 |
1 |
return ssh->remote_port; |
|
526 |
} |
||
527 |
|||
528 |
/* |
||
529 |
* Returns the IP-address of the local host as a string. The returned |
||
530 |
* string must not be freed. |
||
531 |
*/ |
||
532 |
|||
533 |
const char * |
||
534 |
ssh_local_ipaddr(struct ssh *ssh) |
||
535 |
{ |
||
536 |
(void)ssh_remote_ipaddr(ssh); /* Will lookup and cache. */ |
||
537 |
return ssh->local_ipaddr; |
||
538 |
} |
||
539 |
|||
540 |
/* Returns the port number of the local host. */ |
||
541 |
|||
542 |
int |
||
543 |
ssh_local_port(struct ssh *ssh) |
||
544 |
{ |
||
545 |
(void)ssh_remote_ipaddr(ssh); /* Will lookup and cache. */ |
||
546 |
return ssh->local_port; |
||
547 |
} |
||
548 |
|||
549 |
/* Closes the connection and clears and frees internal data structures. */ |
||
550 |
|||
551 |
static void |
||
552 |
ssh_packet_close_internal(struct ssh *ssh, int do_close) |
||
553 |
{ |
||
554 |
2 |
struct session_state *state = ssh->state; |
|
555 |
u_int mode; |
||
556 |
|||
557 |
✗✓ | 1 |
if (!state->initialized) |
558 |
return; |
||
559 |
1 |
state->initialized = 0; |
|
560 |
✓✗ | 1 |
if (do_close) { |
561 |
✓✗ | 1 |
if (state->connection_in == state->connection_out) { |
562 |
1 |
close(state->connection_out); |
|
563 |
1 |
} else { |
|
564 |
close(state->connection_in); |
||
565 |
close(state->connection_out); |
||
566 |
} |
||
567 |
} |
||
568 |
1 |
sshbuf_free(state->input); |
|
569 |
1 |
sshbuf_free(state->output); |
|
570 |
1 |
sshbuf_free(state->outgoing_packet); |
|
571 |
1 |
sshbuf_free(state->incoming_packet); |
|
572 |
✓✓ | 6 |
for (mode = 0; mode < MODE_MAX; mode++) { |
573 |
2 |
kex_free_newkeys(state->newkeys[mode]); /* current keys */ |
|
574 |
2 |
state->newkeys[mode] = NULL; |
|
575 |
2 |
ssh_clear_newkeys(ssh, mode); /* next keys */ |
|
576 |
} |
||
577 |
/* comression state is in shared mem, so we can only release it once */ |
||
578 |
✓✗✗✓ |
2 |
if (do_close && state->compression_buffer) { |
579 |
sshbuf_free(state->compression_buffer); |
||
580 |
if (state->compression_out_started) { |
||
581 |
z_streamp stream = &state->compression_out_stream; |
||
582 |
debug("compress outgoing: " |
||
583 |
"raw data %llu, compressed %llu, factor %.2f", |
||
584 |
(unsigned long long)stream->total_in, |
||
585 |
(unsigned long long)stream->total_out, |
||
586 |
stream->total_in == 0 ? 0.0 : |
||
587 |
(double) stream->total_out / stream->total_in); |
||
588 |
if (state->compression_out_failures == 0) |
||
589 |
deflateEnd(stream); |
||
590 |
} |
||
591 |
if (state->compression_in_started) { |
||
592 |
z_streamp stream = &state->compression_in_stream; |
||
593 |
debug("compress incoming: " |
||
594 |
"raw data %llu, compressed %llu, factor %.2f", |
||
595 |
(unsigned long long)stream->total_out, |
||
596 |
(unsigned long long)stream->total_in, |
||
597 |
stream->total_out == 0 ? 0.0 : |
||
598 |
(double) stream->total_in / stream->total_out); |
||
599 |
if (state->compression_in_failures == 0) |
||
600 |
inflateEnd(stream); |
||
601 |
} |
||
602 |
} |
||
603 |
1 |
cipher_free(state->send_context); |
|
604 |
1 |
cipher_free(state->receive_context); |
|
605 |
1 |
state->send_context = state->receive_context = NULL; |
|
606 |
✓✗ | 1 |
if (do_close) { |
607 |
1 |
free(ssh->remote_ipaddr); |
|
608 |
1 |
ssh->remote_ipaddr = NULL; |
|
609 |
1 |
free(ssh->state); |
|
610 |
1 |
ssh->state = NULL; |
|
611 |
1 |
} |
|
612 |
2 |
} |
|
613 |
|||
614 |
void |
||
615 |
ssh_packet_close(struct ssh *ssh) |
||
616 |
{ |
||
617 |
2 |
ssh_packet_close_internal(ssh, 1); |
|
618 |
1 |
} |
|
619 |
|||
620 |
void |
||
621 |
ssh_packet_clear_keys(struct ssh *ssh) |
||
622 |
{ |
||
623 |
ssh_packet_close_internal(ssh, 0); |
||
624 |
} |
||
625 |
|||
626 |
/* Sets remote side protocol flags. */ |
||
627 |
|||
628 |
void |
||
629 |
ssh_packet_set_protocol_flags(struct ssh *ssh, u_int protocol_flags) |
||
630 |
{ |
||
631 |
ssh->state->remote_protocol_flags = protocol_flags; |
||
632 |
} |
||
633 |
|||
634 |
/* Returns the remote protocol flags set earlier by the above function. */ |
||
635 |
|||
636 |
u_int |
||
637 |
ssh_packet_get_protocol_flags(struct ssh *ssh) |
||
638 |
{ |
||
639 |
return ssh->state->remote_protocol_flags; |
||
640 |
} |
||
641 |
|||
642 |
/* |
||
643 |
* Starts packet compression from the next packet on in both directions. |
||
644 |
* Level is compression level 1 (fastest) - 9 (slow, best) as in gzip. |
||
645 |
*/ |
||
646 |
|||
647 |
static int |
||
648 |
ssh_packet_init_compression(struct ssh *ssh) |
||
649 |
{ |
||
650 |
if (!ssh->state->compression_buffer && |
||
651 |
((ssh->state->compression_buffer = sshbuf_new()) == NULL)) |
||
652 |
return SSH_ERR_ALLOC_FAIL; |
||
653 |
return 0; |
||
654 |
} |
||
655 |
|||
656 |
static int |
||
657 |
start_compression_out(struct ssh *ssh, int level) |
||
658 |
{ |
||
659 |
if (level < 1 || level > 9) |
||
660 |
return SSH_ERR_INVALID_ARGUMENT; |
||
661 |
debug("Enabling compression at level %d.", level); |
||
662 |
if (ssh->state->compression_out_started == 1) |
||
663 |
deflateEnd(&ssh->state->compression_out_stream); |
||
664 |
switch (deflateInit(&ssh->state->compression_out_stream, level)) { |
||
665 |
case Z_OK: |
||
666 |
ssh->state->compression_out_started = 1; |
||
667 |
break; |
||
668 |
case Z_MEM_ERROR: |
||
669 |
return SSH_ERR_ALLOC_FAIL; |
||
670 |
default: |
||
671 |
return SSH_ERR_INTERNAL_ERROR; |
||
672 |
} |
||
673 |
return 0; |
||
674 |
} |
||
675 |
|||
676 |
static int |
||
677 |
start_compression_in(struct ssh *ssh) |
||
678 |
{ |
||
679 |
if (ssh->state->compression_in_started == 1) |
||
680 |
inflateEnd(&ssh->state->compression_in_stream); |
||
681 |
switch (inflateInit(&ssh->state->compression_in_stream)) { |
||
682 |
case Z_OK: |
||
683 |
ssh->state->compression_in_started = 1; |
||
684 |
break; |
||
685 |
case Z_MEM_ERROR: |
||
686 |
return SSH_ERR_ALLOC_FAIL; |
||
687 |
default: |
||
688 |
return SSH_ERR_INTERNAL_ERROR; |
||
689 |
} |
||
690 |
return 0; |
||
691 |
} |
||
692 |
|||
693 |
int |
||
694 |
ssh_packet_start_compression(struct ssh *ssh, int level) |
||
695 |
{ |
||
696 |
int r; |
||
697 |
|||
698 |
if (ssh->state->packet_compression) |
||
699 |
return SSH_ERR_INTERNAL_ERROR; |
||
700 |
ssh->state->packet_compression = 1; |
||
701 |
if ((r = ssh_packet_init_compression(ssh)) != 0 || |
||
702 |
(r = start_compression_in(ssh)) != 0 || |
||
703 |
(r = start_compression_out(ssh, level)) != 0) |
||
704 |
return r; |
||
705 |
return 0; |
||
706 |
} |
||
707 |
|||
708 |
/* XXX remove need for separate compression buffer */ |
||
709 |
static int |
||
710 |
compress_buffer(struct ssh *ssh, struct sshbuf *in, struct sshbuf *out) |
||
711 |
{ |
||
712 |
u_char buf[4096]; |
||
713 |
int r, status; |
||
714 |
|||
715 |
if (ssh->state->compression_out_started != 1) |
||
716 |
return SSH_ERR_INTERNAL_ERROR; |
||
717 |
|||
718 |
/* This case is not handled below. */ |
||
719 |
if (sshbuf_len(in) == 0) |
||
720 |
return 0; |
||
721 |
|||
722 |
/* Input is the contents of the input buffer. */ |
||
723 |
if ((ssh->state->compression_out_stream.next_in = |
||
724 |
sshbuf_mutable_ptr(in)) == NULL) |
||
725 |
return SSH_ERR_INTERNAL_ERROR; |
||
726 |
ssh->state->compression_out_stream.avail_in = sshbuf_len(in); |
||
727 |
|||
728 |
/* Loop compressing until deflate() returns with avail_out != 0. */ |
||
729 |
do { |
||
730 |
/* Set up fixed-size output buffer. */ |
||
731 |
ssh->state->compression_out_stream.next_out = buf; |
||
732 |
ssh->state->compression_out_stream.avail_out = sizeof(buf); |
||
733 |
|||
734 |
/* Compress as much data into the buffer as possible. */ |
||
735 |
status = deflate(&ssh->state->compression_out_stream, |
||
736 |
Z_PARTIAL_FLUSH); |
||
737 |
switch (status) { |
||
738 |
case Z_MEM_ERROR: |
||
739 |
return SSH_ERR_ALLOC_FAIL; |
||
740 |
case Z_OK: |
||
741 |
/* Append compressed data to output_buffer. */ |
||
742 |
if ((r = sshbuf_put(out, buf, sizeof(buf) - |
||
743 |
ssh->state->compression_out_stream.avail_out)) != 0) |
||
744 |
return r; |
||
745 |
break; |
||
746 |
case Z_STREAM_ERROR: |
||
747 |
default: |
||
748 |
ssh->state->compression_out_failures++; |
||
749 |
return SSH_ERR_INVALID_FORMAT; |
||
750 |
} |
||
751 |
} while (ssh->state->compression_out_stream.avail_out == 0); |
||
752 |
return 0; |
||
753 |
} |
||
754 |
|||
755 |
static int |
||
756 |
uncompress_buffer(struct ssh *ssh, struct sshbuf *in, struct sshbuf *out) |
||
757 |
{ |
||
758 |
u_char buf[4096]; |
||
759 |
int r, status; |
||
760 |
|||
761 |
if (ssh->state->compression_in_started != 1) |
||
762 |
return SSH_ERR_INTERNAL_ERROR; |
||
763 |
|||
764 |
if ((ssh->state->compression_in_stream.next_in = |
||
765 |
sshbuf_mutable_ptr(in)) == NULL) |
||
766 |
return SSH_ERR_INTERNAL_ERROR; |
||
767 |
ssh->state->compression_in_stream.avail_in = sshbuf_len(in); |
||
768 |
|||
769 |
for (;;) { |
||
770 |
/* Set up fixed-size output buffer. */ |
||
771 |
ssh->state->compression_in_stream.next_out = buf; |
||
772 |
ssh->state->compression_in_stream.avail_out = sizeof(buf); |
||
773 |
|||
774 |
status = inflate(&ssh->state->compression_in_stream, |
||
775 |
Z_PARTIAL_FLUSH); |
||
776 |
switch (status) { |
||
777 |
case Z_OK: |
||
778 |
if ((r = sshbuf_put(out, buf, sizeof(buf) - |
||
779 |
ssh->state->compression_in_stream.avail_out)) != 0) |
||
780 |
return r; |
||
781 |
break; |
||
782 |
case Z_BUF_ERROR: |
||
783 |
/* |
||
784 |
* Comments in zlib.h say that we should keep calling |
||
785 |
* inflate() until we get an error. This appears to |
||
786 |
* be the error that we get. |
||
787 |
*/ |
||
788 |
return 0; |
||
789 |
case Z_DATA_ERROR: |
||
790 |
return SSH_ERR_INVALID_FORMAT; |
||
791 |
case Z_MEM_ERROR: |
||
792 |
return SSH_ERR_ALLOC_FAIL; |
||
793 |
case Z_STREAM_ERROR: |
||
794 |
default: |
||
795 |
ssh->state->compression_in_failures++; |
||
796 |
return SSH_ERR_INTERNAL_ERROR; |
||
797 |
} |
||
798 |
} |
||
799 |
/* NOTREACHED */ |
||
800 |
} |
||
801 |
|||
802 |
void |
||
803 |
ssh_clear_newkeys(struct ssh *ssh, int mode) |
||
804 |
{ |
||
805 |
✓✗✗✓ |
6 |
if (ssh->kex && ssh->kex->newkeys[mode]) { |
806 |
kex_free_newkeys(ssh->kex->newkeys[mode]); |
||
807 |
ssh->kex->newkeys[mode] = NULL; |
||
808 |
} |
||
809 |
2 |
} |
|
810 |
|||
811 |
int |
||
812 |
ssh_set_newkeys(struct ssh *ssh, int mode) |
||
813 |
{ |
||
814 |
4 |
struct session_state *state = ssh->state; |
|
815 |
struct sshenc *enc; |
||
816 |
struct sshmac *mac; |
||
817 |
struct sshcomp *comp; |
||
818 |
struct sshcipher_ctx **ccp; |
||
819 |
struct packet_state *ps; |
||
820 |
u_int64_t *max_blocks; |
||
821 |
const char *wmsg; |
||
822 |
int r, crypt_type; |
||
823 |
|||
824 |
2 |
debug2("set_newkeys: mode %d", mode); |
|
825 |
|||
826 |
✓✓ | 2 |
if (mode == MODE_OUT) { |
827 |
1 |
ccp = &state->send_context; |
|
828 |
crypt_type = CIPHER_ENCRYPT; |
||
829 |
1 |
ps = &state->p_send; |
|
830 |
1 |
max_blocks = &state->max_blocks_out; |
|
831 |
1 |
} else { |
|
832 |
1 |
ccp = &state->receive_context; |
|
833 |
crypt_type = CIPHER_DECRYPT; |
||
834 |
1 |
ps = &state->p_read; |
|
835 |
1 |
max_blocks = &state->max_blocks_in; |
|
836 |
} |
||
837 |
✗✓ | 2 |
if (state->newkeys[mode] != NULL) { |
838 |
debug("set_newkeys: rekeying, input %llu bytes %llu blocks, " |
||
839 |
"output %llu bytes %llu blocks", |
||
840 |
(unsigned long long)state->p_read.bytes, |
||
841 |
(unsigned long long)state->p_read.blocks, |
||
842 |
(unsigned long long)state->p_send.bytes, |
||
843 |
(unsigned long long)state->p_send.blocks); |
||
844 |
cipher_free(*ccp); |
||
845 |
*ccp = NULL; |
||
846 |
kex_free_newkeys(state->newkeys[mode]); |
||
847 |
state->newkeys[mode] = NULL; |
||
848 |
} |
||
849 |
/* note that both bytes and the seqnr are not reset */ |
||
850 |
2 |
ps->packets = ps->blocks = 0; |
|
851 |
/* move newkeys from kex to state */ |
||
852 |
✗✓ | 2 |
if ((state->newkeys[mode] = ssh->kex->newkeys[mode]) == NULL) |
853 |
return SSH_ERR_INTERNAL_ERROR; |
||
854 |
2 |
ssh->kex->newkeys[mode] = NULL; |
|
855 |
2 |
enc = &state->newkeys[mode]->enc; |
|
856 |
2 |
mac = &state->newkeys[mode]->mac; |
|
857 |
2 |
comp = &state->newkeys[mode]->comp; |
|
858 |
✗✓ | 2 |
if (cipher_authlen(enc->cipher) == 0) { |
859 |
if ((r = mac_init(mac)) != 0) |
||
860 |
return r; |
||
861 |
} |
||
862 |
2 |
mac->enabled = 1; |
|
863 |
DBG(debug("cipher_init_context: %d", mode)); |
||
864 |
✗✓ | 6 |
if ((r = cipher_init(ccp, enc->cipher, enc->key, enc->key_len, |
865 |
4 |
enc->iv, enc->iv_len, crypt_type)) != 0) |
|
866 |
return r; |
||
867 |
✓✗✗✓ |
4 |
if (!state->cipher_warning_done && |
868 |
2 |
(wmsg = cipher_warning_message(*ccp)) != NULL) { |
|
869 |
error("Warning: %s", wmsg); |
||
870 |
state->cipher_warning_done = 1; |
||
871 |
} |
||
872 |
/* Deleting the keys does not gain extra security */ |
||
873 |
/* explicit_bzero(enc->iv, enc->block_size); |
||
874 |
explicit_bzero(enc->key, enc->key_len); |
||
875 |
explicit_bzero(mac->key, mac->key_len); */ |
||
876 |
✓✗✗✗ |
2 |
if ((comp->type == COMP_ZLIB || |
877 |
✗✓ | 2 |
(comp->type == COMP_DELAYED && |
878 |
state->after_authentication)) && comp->enabled == 0) { |
||
879 |
if ((r = ssh_packet_init_compression(ssh)) < 0) |
||
880 |
return r; |
||
881 |
if (mode == MODE_OUT) { |
||
882 |
if ((r = start_compression_out(ssh, 6)) != 0) |
||
883 |
return r; |
||
884 |
} else { |
||
885 |
if ((r = start_compression_in(ssh)) != 0) |
||
886 |
return r; |
||
887 |
} |
||
888 |
comp->enabled = 1; |
||
889 |
} |
||
890 |
/* |
||
891 |
* The 2^(blocksize*2) limit is too expensive for 3DES, |
||
892 |
* so enforce a 1GB limit for small blocksizes. |
||
893 |
* See RFC4344 section 3.2. |
||
894 |
*/ |
||
895 |
✗✓ | 2 |
if (enc->block_size >= 16) |
896 |
*max_blocks = (u_int64_t)1 << (enc->block_size*2); |
||
897 |
else |
||
898 |
2 |
*max_blocks = ((u_int64_t)1 << 30) / enc->block_size; |
|
899 |
✗✓ | 2 |
if (state->rekey_limit) |
900 |
*max_blocks = MINIMUM(*max_blocks, |
||
901 |
state->rekey_limit / enc->block_size); |
||
902 |
2 |
debug("rekey after %llu blocks", (unsigned long long)*max_blocks); |
|
903 |
2 |
return 0; |
|
904 |
2 |
} |
|
905 |
|||
906 |
#define MAX_PACKETS (1U<<31) |
||
907 |
static int |
||
908 |
ssh_packet_need_rekeying(struct ssh *ssh, u_int outbound_packet_len) |
||
909 |
{ |
||
910 |
114936 |
struct session_state *state = ssh->state; |
|
911 |
u_int32_t out_blocks; |
||
912 |
|||
913 |
/* XXX client can't cope with rekeying pre-auth */ |
||
914 |
✓✓ | 57468 |
if (!state->after_authentication) |
915 |
9 |
return 0; |
|
916 |
|||
917 |
/* Haven't keyed yet or KEX in progress. */ |
||
918 |
✓✗✗✓ |
114918 |
if (ssh->kex == NULL || ssh_packet_is_rekeying(ssh)) |
919 |
return 0; |
||
920 |
|||
921 |
/* Peer can't rekey */ |
||
922 |
✗✓ | 57459 |
if (ssh->compat & SSH_BUG_NOREKEY) |
923 |
return 0; |
||
924 |
|||
925 |
/* |
||
926 |
* Permit one packet in or out per rekey - this allows us to |
||
927 |
* make progress when rekey limits are very small. |
||
928 |
*/ |
||
929 |
✗✓✗✗ |
57459 |
if (state->p_send.packets == 0 && state->p_read.packets == 0) |
930 |
return 0; |
||
931 |
|||
932 |
/* Time-based rekeying */ |
||
933 |
✗✓✗✗ |
57459 |
if (state->rekey_interval != 0 && |
934 |
(int64_t)state->rekey_time + state->rekey_interval <= monotime()) |
||
935 |
return 1; |
||
936 |
|||
937 |
/* |
||
938 |
* Always rekey when MAX_PACKETS sent in either direction |
||
939 |
* As per RFC4344 section 3.1 we do this after 2^31 packets. |
||
940 |
*/ |
||
941 |
✓✗✗✓ |
114918 |
if (state->p_send.packets > MAX_PACKETS || |
942 |
57459 |
state->p_read.packets > MAX_PACKETS) |
|
943 |
return 1; |
||
944 |
|||
945 |
/* Rekey after (cipher-specific) maxiumum blocks */ |
||
946 |
57459 |
out_blocks = ROUNDUP(outbound_packet_len, |
|
947 |
state->newkeys[MODE_OUT]->enc.block_size); |
||
948 |
✓✗ | 114918 |
return (state->max_blocks_out && |
949 |
✓✗ | 114918 |
(state->p_send.blocks + out_blocks > state->max_blocks_out)) || |
950 |
✓✗ | 57459 |
(state->max_blocks_in && |
951 |
57459 |
(state->p_read.blocks > state->max_blocks_in)); |
|
952 |
57468 |
} |
|
953 |
|||
954 |
/* |
||
955 |
* Delayed compression for SSH2 is enabled after authentication: |
||
956 |
* This happens on the server side after a SSH2_MSG_USERAUTH_SUCCESS is sent, |
||
957 |
* and on the client side after a SSH2_MSG_USERAUTH_SUCCESS is received. |
||
958 |
*/ |
||
959 |
static int |
||
960 |
ssh_packet_enable_delayed_compress(struct ssh *ssh) |
||
961 |
{ |
||
962 |
2 |
struct session_state *state = ssh->state; |
|
963 |
struct sshcomp *comp = NULL; |
||
964 |
int r, mode; |
||
965 |
|||
966 |
/* |
||
967 |
* Remember that we are past the authentication step, so rekeying |
||
968 |
* with COMP_DELAYED will turn on compression immediately. |
||
969 |
*/ |
||
970 |
1 |
state->after_authentication = 1; |
|
971 |
✓✓ | 6 |
for (mode = 0; mode < MODE_MAX; mode++) { |
972 |
/* protocol error: USERAUTH_SUCCESS received before NEWKEYS */ |
||
973 |
✓✗ | 2 |
if (state->newkeys[mode] == NULL) |
974 |
continue; |
||
975 |
2 |
comp = &state->newkeys[mode]->comp; |
|
976 |
✓✗✓✗ ✗✓ |
6 |
if (comp && !comp->enabled && comp->type == COMP_DELAYED) { |
977 |
if ((r = ssh_packet_init_compression(ssh)) != 0) |
||
978 |
return r; |
||
979 |
if (mode == MODE_OUT) { |
||
980 |
if ((r = start_compression_out(ssh, 6)) != 0) |
||
981 |
return r; |
||
982 |
} else { |
||
983 |
if ((r = start_compression_in(ssh)) != 0) |
||
984 |
return r; |
||
985 |
} |
||
986 |
comp->enabled = 1; |
||
987 |
} |
||
988 |
} |
||
989 |
1 |
return 0; |
|
990 |
1 |
} |
|
991 |
|||
992 |
/* Used to mute debug logging for noisy packet types */ |
||
993 |
int |
||
994 |
ssh_packet_log_type(u_char type) |
||
995 |
{ |
||
996 |
✓✓ | 114944 |
switch (type) { |
997 |
case SSH2_MSG_CHANNEL_DATA: |
||
998 |
case SSH2_MSG_CHANNEL_EXTENDED_DATA: |
||
999 |
case SSH2_MSG_CHANNEL_WINDOW_ADJUST: |
||
1000 |
57447 |
return 0; |
|
1001 |
default: |
||
1002 |
25 |
return 1; |
|
1003 |
} |
||
1004 |
57472 |
} |
|
1005 |
|||
1006 |
/* |
||
1007 |
* Finalize packet in SSH2 format (compress, mac, encrypt, enqueue) |
||
1008 |
*/ |
||
1009 |
int |
||
1010 |
ssh_packet_send2_wrapped(struct ssh *ssh) |
||
1011 |
{ |
||
1012 |
85304 |
struct session_state *state = ssh->state; |
|
1013 |
42652 |
u_char type, *cp, macbuf[SSH_DIGEST_MAX_LENGTH]; |
|
1014 |
u_char tmp, padlen, pad = 0; |
||
1015 |
u_int authlen = 0, aadlen = 0; |
||
1016 |
u_int len; |
||
1017 |
struct sshenc *enc = NULL; |
||
1018 |
struct sshmac *mac = NULL; |
||
1019 |
struct sshcomp *comp = NULL; |
||
1020 |
int r, block_size; |
||
1021 |
|||
1022 |
✓✓ | 42652 |
if (state->newkeys[MODE_OUT] != NULL) { |
1023 |
42649 |
enc = &state->newkeys[MODE_OUT]->enc; |
|
1024 |
42649 |
mac = &state->newkeys[MODE_OUT]->mac; |
|
1025 |
42649 |
comp = &state->newkeys[MODE_OUT]->comp; |
|
1026 |
/* disable mac for authenticated encryption */ |
||
1027 |
✓✗ | 42649 |
if ((authlen = cipher_authlen(enc->cipher)) != 0) |
1028 |
42649 |
mac = NULL; |
|
1029 |
} |
||
1030 |
✓✓ | 127953 |
block_size = enc ? enc->block_size : 8; |
1031 |
✗✓✗✗ ✗✗ |
127956 |
aadlen = (mac && mac->enabled && mac->etm) || authlen ? 4 : 0; |
1032 |
|||
1033 |
42652 |
type = (sshbuf_ptr(state->outgoing_packet))[5]; |
|
1034 |
✓✓ | 42652 |
if (ssh_packet_log_type(type)) |
1035 |
12 |
debug3("send packet: type %u", type); |
|
1036 |
#ifdef PACKET_DEBUG |
||
1037 |
fprintf(stderr, "plain: "); |
||
1038 |
sshbuf_dump(state->outgoing_packet, stderr); |
||
1039 |
#endif |
||
1040 |
|||
1041 |
✓✓✗✓ |
85301 |
if (comp && comp->enabled) { |
1042 |
len = sshbuf_len(state->outgoing_packet); |
||
1043 |
/* skip header, compress only payload */ |
||
1044 |
if ((r = sshbuf_consume(state->outgoing_packet, 5)) != 0) |
||
1045 |
goto out; |
||
1046 |
sshbuf_reset(state->compression_buffer); |
||
1047 |
if ((r = compress_buffer(ssh, state->outgoing_packet, |
||
1048 |
state->compression_buffer)) != 0) |
||
1049 |
goto out; |
||
1050 |
sshbuf_reset(state->outgoing_packet); |
||
1051 |
if ((r = sshbuf_put(state->outgoing_packet, |
||
1052 |
"\0\0\0\0\0", 5)) != 0 || |
||
1053 |
(r = sshbuf_putb(state->outgoing_packet, |
||
1054 |
state->compression_buffer)) != 0) |
||
1055 |
goto out; |
||
1056 |
DBG(debug("compression: raw %d compressed %zd", len, |
||
1057 |
sshbuf_len(state->outgoing_packet))); |
||
1058 |
} |
||
1059 |
|||
1060 |
/* sizeof (packet_len + pad_len + payload) */ |
||
1061 |
42652 |
len = sshbuf_len(state->outgoing_packet); |
|
1062 |
|||
1063 |
/* |
||
1064 |
* calc size of padding, alloc space, get random data, |
||
1065 |
* minimum padding is 4 bytes |
||
1066 |
*/ |
||
1067 |
42652 |
len -= aadlen; /* packet length is not encrypted for EtM modes */ |
|
1068 |
42652 |
padlen = block_size - (len % block_size); |
|
1069 |
✓✓ | 42652 |
if (padlen < 4) |
1070 |
3329 |
padlen += block_size; |
|
1071 |
✓✓ | 42652 |
if (state->extra_pad) { |
1072 |
tmp = state->extra_pad; |
||
1073 |
1 |
state->extra_pad = |
|
1074 |
1 |
ROUNDUP(state->extra_pad, block_size); |
|
1075 |
/* check if roundup overflowed */ |
||
1076 |
✗✓ | 1 |
if (state->extra_pad < tmp) |
1077 |
return SSH_ERR_INVALID_ARGUMENT; |
||
1078 |
1 |
tmp = (len + padlen) % state->extra_pad; |
|
1079 |
/* Check whether pad calculation below will underflow */ |
||
1080 |
✗✓ | 1 |
if (tmp > state->extra_pad) |
1081 |
return SSH_ERR_INVALID_ARGUMENT; |
||
1082 |
1 |
pad = state->extra_pad - tmp; |
|
1083 |
DBG(debug3("%s: adding %d (len %d padlen %d extra_pad %d)", |
||
1084 |
__func__, pad, len, padlen, state->extra_pad)); |
||
1085 |
tmp = padlen; |
||
1086 |
1 |
padlen += pad; |
|
1087 |
/* Check whether padlen calculation overflowed */ |
||
1088 |
✗✓ | 1 |
if (padlen < tmp) |
1089 |
return SSH_ERR_INVALID_ARGUMENT; /* overflow */ |
||
1090 |
1 |
state->extra_pad = 0; |
|
1091 |
1 |
} |
|
1092 |
✓✗ | 42652 |
if ((r = sshbuf_reserve(state->outgoing_packet, padlen, &cp)) != 0) |
1093 |
goto out; |
||
1094 |
✓✓✓✗ |
85301 |
if (enc && !cipher_ctx_is_plaintext(state->send_context)) { |
1095 |
/* random padding */ |
||
1096 |
42649 |
arc4random_buf(cp, padlen); |
|
1097 |
42649 |
} else { |
|
1098 |
/* clear padding */ |
||
1099 |
3 |
explicit_bzero(cp, padlen); |
|
1100 |
} |
||
1101 |
/* sizeof (packet_len + pad_len + payload + padding) */ |
||
1102 |
42652 |
len = sshbuf_len(state->outgoing_packet); |
|
1103 |
42652 |
cp = sshbuf_mutable_ptr(state->outgoing_packet); |
|
1104 |
✗✓ | 42652 |
if (cp == NULL) { |
1105 |
r = SSH_ERR_INTERNAL_ERROR; |
||
1106 |
goto out; |
||
1107 |
} |
||
1108 |
/* packet_length includes payload, padding and padding length field */ |
||
1109 |
42652 |
POKE_U32(cp, len - 4); |
|
1110 |
42652 |
cp[4] = padlen; |
|
1111 |
DBG(debug("send: len %d (includes padlen %d, aadlen %d)", |
||
1112 |
len, padlen, aadlen)); |
||
1113 |
|||
1114 |
/* compute MAC over seqnr and packet(length fields, payload, padding) */ |
||
1115 |
✗✓✗✗ ✗✗ |
42652 |
if (mac && mac->enabled && !mac->etm) { |
1116 |
if ((r = mac_compute(mac, state->p_send.seqnr, |
||
1117 |
sshbuf_ptr(state->outgoing_packet), len, |
||
1118 |
macbuf, sizeof(macbuf))) != 0) |
||
1119 |
goto out; |
||
1120 |
DBG(debug("done calc MAC out #%d", state->p_send.seqnr)); |
||
1121 |
} |
||
1122 |
/* encrypt packet and append to output buffer. */ |
||
1123 |
✓✗ | 127956 |
if ((r = sshbuf_reserve(state->output, |
1124 |
85304 |
sshbuf_len(state->outgoing_packet) + authlen, &cp)) != 0) |
|
1125 |
goto out; |
||
1126 |
✓✗ | 127956 |
if ((r = cipher_crypt(state->send_context, state->p_send.seqnr, cp, |
1127 |
42652 |
sshbuf_ptr(state->outgoing_packet), |
|
1128 |
85304 |
len - aadlen, aadlen, authlen)) != 0) |
|
1129 |
goto out; |
||
1130 |
/* append unencrypted MAC */ |
||
1131 |
✗✓✗✗ |
42652 |
if (mac && mac->enabled) { |
1132 |
if (mac->etm) { |
||
1133 |
/* EtM: compute mac over aadlen + cipher text */ |
||
1134 |
if ((r = mac_compute(mac, state->p_send.seqnr, |
||
1135 |
cp, len, macbuf, sizeof(macbuf))) != 0) |
||
1136 |
goto out; |
||
1137 |
DBG(debug("done calc MAC(EtM) out #%d", |
||
1138 |
state->p_send.seqnr)); |
||
1139 |
} |
||
1140 |
if ((r = sshbuf_put(state->output, macbuf, mac->mac_len)) != 0) |
||
1141 |
goto out; |
||
1142 |
} |
||
1143 |
#ifdef PACKET_DEBUG |
||
1144 |
fprintf(stderr, "encrypted: "); |
||
1145 |
sshbuf_dump(state->output, stderr); |
||
1146 |
#endif |
||
1147 |
/* increment sequence number for outgoing packets */ |
||
1148 |
✗✓ | 42652 |
if (++state->p_send.seqnr == 0) |
1149 |
logit("outgoing seqnr wraps around"); |
||
1150 |
✗✓ | 42652 |
if (++state->p_send.packets == 0) |
1151 |
if (!(ssh->compat & SSH_BUG_NOREKEY)) |
||
1152 |
return SSH_ERR_NEED_REKEY; |
||
1153 |
42652 |
state->p_send.blocks += len / block_size; |
|
1154 |
42652 |
state->p_send.bytes += len; |
|
1155 |
42652 |
sshbuf_reset(state->outgoing_packet); |
|
1156 |
|||
1157 |
✓✓ | 42652 |
if (type == SSH2_MSG_NEWKEYS) |
1158 |
1 |
r = ssh_set_newkeys(ssh, MODE_OUT); |
|
1159 |
✗✓✗✗ |
42651 |
else if (type == SSH2_MSG_USERAUTH_SUCCESS && state->server_side) |
1160 |
r = ssh_packet_enable_delayed_compress(ssh); |
||
1161 |
else |
||
1162 |
r = 0; |
||
1163 |
out: |
||
1164 |
42652 |
return r; |
|
1165 |
42652 |
} |
|
1166 |
|||
1167 |
/* returns non-zero if the specified packet type is usec by KEX */ |
||
1168 |
static int |
||
1169 |
ssh_packet_type_is_kex(u_char type) |
||
1170 |
{ |
||
1171 |
42655 |
return |
|
1172 |
✓✗ | 85310 |
type >= SSH2_MSG_TRANSPORT_MIN && |
1173 |
✓✓ | 42655 |
type <= SSH2_MSG_TRANSPORT_MAX && |
1174 |
✓✓ | 8 |
type != SSH2_MSG_SERVICE_REQUEST && |
1175 |
✓✗ | 42662 |
type != SSH2_MSG_SERVICE_ACCEPT && |
1176 |
7 |
type != SSH2_MSG_EXT_INFO; |
|
1177 |
} |
||
1178 |
|||
1179 |
int |
||
1180 |
ssh_packet_send2(struct ssh *ssh) |
||
1181 |
{ |
||
1182 |
85304 |
struct session_state *state = ssh->state; |
|
1183 |
struct packet *p; |
||
1184 |
u_char type; |
||
1185 |
int r, need_rekey; |
||
1186 |
|||
1187 |
✗✓ | 42652 |
if (sshbuf_len(state->outgoing_packet) < 6) |
1188 |
return SSH_ERR_INTERNAL_ERROR; |
||
1189 |
42652 |
type = sshbuf_ptr(state->outgoing_packet)[5]; |
|
1190 |
✓✓ | 127952 |
need_rekey = !ssh_packet_type_is_kex(type) && |
1191 |
42648 |
ssh_packet_need_rekeying(ssh, sshbuf_len(state->outgoing_packet)); |
|
1192 |
|||
1193 |
/* |
||
1194 |
* During rekeying we can only send key exchange messages. |
||
1195 |
* Queue everything else. |
||
1196 |
*/ |
||
1197 |
✓✗✓✓ ✗✓ |
85307 |
if ((need_rekey || state->rekeying) && !ssh_packet_type_is_kex(type)) { |
1198 |
if (need_rekey) |
||
1199 |
debug3("%s: rekex triggered", __func__); |
||
1200 |
debug("enqueue packet: %u", type); |
||
1201 |
p = calloc(1, sizeof(*p)); |
||
1202 |
if (p == NULL) |
||
1203 |
return SSH_ERR_ALLOC_FAIL; |
||
1204 |
p->type = type; |
||
1205 |
p->payload = state->outgoing_packet; |
||
1206 |
TAILQ_INSERT_TAIL(&state->outgoing, p, next); |
||
1207 |
state->outgoing_packet = sshbuf_new(); |
||
1208 |
if (state->outgoing_packet == NULL) |
||
1209 |
return SSH_ERR_ALLOC_FAIL; |
||
1210 |
if (need_rekey) { |
||
1211 |
/* |
||
1212 |
* This packet triggered a rekey, so send the |
||
1213 |
* KEXINIT now. |
||
1214 |
* NB. reenters this function via kex_start_rekex(). |
||
1215 |
*/ |
||
1216 |
return kex_start_rekex(ssh); |
||
1217 |
} |
||
1218 |
return 0; |
||
1219 |
} |
||
1220 |
|||
1221 |
/* rekeying starts with sending KEXINIT */ |
||
1222 |
✓✓ | 42652 |
if (type == SSH2_MSG_KEXINIT) |
1223 |
1 |
state->rekeying = 1; |
|
1224 |
|||
1225 |
✗✓ | 42652 |
if ((r = ssh_packet_send2_wrapped(ssh)) != 0) |
1226 |
return r; |
||
1227 |
|||
1228 |
/* after a NEWKEYS message we can send the complete queue */ |
||
1229 |
✓✓ | 42652 |
if (type == SSH2_MSG_NEWKEYS) { |
1230 |
1 |
state->rekeying = 0; |
|
1231 |
1 |
state->rekey_time = monotime(); |
|
1232 |
✗✓ | 2 |
while ((p = TAILQ_FIRST(&state->outgoing))) { |
1233 |
type = p->type; |
||
1234 |
/* |
||
1235 |
* If this packet triggers a rekex, then skip the |
||
1236 |
* remaining packets in the queue for now. |
||
1237 |
* NB. re-enters this function via kex_start_rekex. |
||
1238 |
*/ |
||
1239 |
if (ssh_packet_need_rekeying(ssh, |
||
1240 |
sshbuf_len(p->payload))) { |
||
1241 |
debug3("%s: queued packet triggered rekex", |
||
1242 |
__func__); |
||
1243 |
return kex_start_rekex(ssh); |
||
1244 |
} |
||
1245 |
debug("dequeue packet: %u", type); |
||
1246 |
sshbuf_free(state->outgoing_packet); |
||
1247 |
state->outgoing_packet = p->payload; |
||
1248 |
TAILQ_REMOVE(&state->outgoing, p, next); |
||
1249 |
memset(p, 0, sizeof(*p)); |
||
1250 |
free(p); |
||
1251 |
if ((r = ssh_packet_send2_wrapped(ssh)) != 0) |
||
1252 |
return r; |
||
1253 |
} |
||
1254 |
} |
||
1255 |
42652 |
return 0; |
|
1256 |
42652 |
} |
|
1257 |
|||
1258 |
/* |
||
1259 |
* Waits until a packet has been received, and returns its type. Note that |
||
1260 |
* no other data is processed until this returns, so this function should not |
||
1261 |
* be used during the interactive session. |
||
1262 |
*/ |
||
1263 |
|||
1264 |
int |
||
1265 |
ssh_packet_read_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) |
||
1266 |
{ |
||
1267 |
14 |
struct session_state *state = ssh->state; |
|
1268 |
7 |
int len, r, ms_remain; |
|
1269 |
fd_set *setp; |
||
1270 |
7 |
char buf[8192]; |
|
1271 |
7 |
struct timeval timeout, start, *timeoutp = NULL; |
|
1272 |
|||
1273 |
DBG(debug("packet_read()")); |
||
1274 |
|||
1275 |
7 |
setp = calloc(howmany(state->connection_in + 1, |
|
1276 |
NFDBITS), sizeof(fd_mask)); |
||
1277 |
✗✓ | 7 |
if (setp == NULL) |
1278 |
return SSH_ERR_ALLOC_FAIL; |
||
1279 |
|||
1280 |
/* |
||
1281 |
* Since we are blocking, ensure that all written packets have |
||
1282 |
* been sent. |
||
1283 |
*/ |
||
1284 |
✓✗ | 7 |
if ((r = ssh_packet_write_wait(ssh)) != 0) |
1285 |
goto out; |
||
1286 |
|||
1287 |
/* Stay in the loop until we have received a complete packet. */ |
||
1288 |
for (;;) { |
||
1289 |
/* Try to read a packet from the buffer. */ |
||
1290 |
12 |
r = ssh_packet_read_poll_seqnr(ssh, typep, seqnr_p); |
|
1291 |
✓✗ | 12 |
if (r != 0) |
1292 |
break; |
||
1293 |
/* If we got a packet, return it. */ |
||
1294 |
✓✓ | 12 |
if (*typep != SSH_MSG_NONE) |
1295 |
break; |
||
1296 |
/* |
||
1297 |
* Otherwise, wait for some data to arrive, add it to the |
||
1298 |
* buffer, and try again. |
||
1299 |
*/ |
||
1300 |
10 |
memset(setp, 0, howmany(state->connection_in + 1, |
|
1301 |
5 |
NFDBITS) * sizeof(fd_mask)); |
|
1302 |
5 |
FD_SET(state->connection_in, setp); |
|
1303 |
|||
1304 |
✗✓ | 5 |
if (state->packet_timeout_ms > 0) { |
1305 |
ms_remain = state->packet_timeout_ms; |
||
1306 |
timeoutp = &timeout; |
||
1307 |
} |
||
1308 |
/* Wait for some data to arrive. */ |
||
1309 |
for (;;) { |
||
1310 |
✗✓ | 5 |
if (state->packet_timeout_ms != -1) { |
1311 |
ms_to_timeval(&timeout, ms_remain); |
||
1312 |
gettimeofday(&start, NULL); |
||
1313 |
} |
||
1314 |
✗✓ | 10 |
if ((r = select(state->connection_in + 1, setp, |
1315 |
5 |
NULL, NULL, timeoutp)) >= 0) |
|
1316 |
break; |
||
1317 |
if (errno != EAGAIN && errno != EINTR) |
||
1318 |
break; |
||
1319 |
if (state->packet_timeout_ms == -1) |
||
1320 |
continue; |
||
1321 |
ms_subtract_diff(&start, &ms_remain); |
||
1322 |
if (ms_remain <= 0) { |
||
1323 |
r = 0; |
||
1324 |
break; |
||
1325 |
} |
||
1326 |
} |
||
1327 |
✗✓ | 5 |
if (r == 0) { |
1328 |
r = SSH_ERR_CONN_TIMEOUT; |
||
1329 |
goto out; |
||
1330 |
} |
||
1331 |
/* Read data from the socket. */ |
||
1332 |
5 |
len = read(state->connection_in, buf, sizeof(buf)); |
|
1333 |
✗✓ | 5 |
if (len == 0) { |
1334 |
r = SSH_ERR_CONN_CLOSED; |
||
1335 |
goto out; |
||
1336 |
} |
||
1337 |
✗✓ | 5 |
if (len < 0) { |
1338 |
r = SSH_ERR_SYSTEM_ERROR; |
||
1339 |
goto out; |
||
1340 |
} |
||
1341 |
|||
1342 |
/* Append it to the buffer. */ |
||
1343 |
✓✗ | 5 |
if ((r = ssh_packet_process_incoming(ssh, buf, len)) != 0) |
1344 |
goto out; |
||
1345 |
} |
||
1346 |
out: |
||
1347 |
7 |
free(setp); |
|
1348 |
7 |
return r; |
|
1349 |
7 |
} |
|
1350 |
|||
1351 |
int |
||
1352 |
ssh_packet_read(struct ssh *ssh) |
||
1353 |
{ |
||
1354 |
u_char type; |
||
1355 |
int r; |
||
1356 |
|||
1357 |
if ((r = ssh_packet_read_seqnr(ssh, &type, NULL)) != 0) |
||
1358 |
fatal("%s: %s", __func__, ssh_err(r)); |
||
1359 |
return type; |
||
1360 |
} |
||
1361 |
|||
1362 |
/* |
||
1363 |
* Waits until a packet has been received, verifies that its type matches |
||
1364 |
* that given, and gives a fatal error and exits if there is a mismatch. |
||
1365 |
*/ |
||
1366 |
|||
1367 |
int |
||
1368 |
ssh_packet_read_expect(struct ssh *ssh, u_int expected_type) |
||
1369 |
{ |
||
1370 |
int r; |
||
1371 |
u_char type; |
||
1372 |
|||
1373 |
if ((r = ssh_packet_read_seqnr(ssh, &type, NULL)) != 0) |
||
1374 |
return r; |
||
1375 |
if (type != expected_type) { |
||
1376 |
if ((r = sshpkt_disconnect(ssh, |
||
1377 |
"Protocol error: expected packet type %d, got %d", |
||
1378 |
expected_type, type)) != 0) |
||
1379 |
return r; |
||
1380 |
return SSH_ERR_PROTOCOL_ERROR; |
||
1381 |
} |
||
1382 |
return 0; |
||
1383 |
} |
||
1384 |
|||
1385 |
static int |
||
1386 |
ssh_packet_read_poll2_mux(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) |
||
1387 |
{ |
||
1388 |
struct session_state *state = ssh->state; |
||
1389 |
const u_char *cp; |
||
1390 |
size_t need; |
||
1391 |
int r; |
||
1392 |
|||
1393 |
if (ssh->kex) |
||
1394 |
return SSH_ERR_INTERNAL_ERROR; |
||
1395 |
*typep = SSH_MSG_NONE; |
||
1396 |
cp = sshbuf_ptr(state->input); |
||
1397 |
if (state->packlen == 0) { |
||
1398 |
if (sshbuf_len(state->input) < 4 + 1) |
||
1399 |
return 0; /* packet is incomplete */ |
||
1400 |
state->packlen = PEEK_U32(cp); |
||
1401 |
if (state->packlen < 4 + 1 || |
||
1402 |
state->packlen > PACKET_MAX_SIZE) |
||
1403 |
return SSH_ERR_MESSAGE_INCOMPLETE; |
||
1404 |
} |
||
1405 |
need = state->packlen + 4; |
||
1406 |
if (sshbuf_len(state->input) < need) |
||
1407 |
return 0; /* packet is incomplete */ |
||
1408 |
sshbuf_reset(state->incoming_packet); |
||
1409 |
if ((r = sshbuf_put(state->incoming_packet, cp + 4, |
||
1410 |
state->packlen)) != 0 || |
||
1411 |
(r = sshbuf_consume(state->input, need)) != 0 || |
||
1412 |
(r = sshbuf_get_u8(state->incoming_packet, NULL)) != 0 || |
||
1413 |
(r = sshbuf_get_u8(state->incoming_packet, typep)) != 0) |
||
1414 |
return r; |
||
1415 |
if (ssh_packet_log_type(*typep)) |
||
1416 |
debug3("%s: type %u", __func__, *typep); |
||
1417 |
/* sshbuf_dump(state->incoming_packet, stderr); */ |
||
1418 |
/* reset for next packet */ |
||
1419 |
state->packlen = 0; |
||
1420 |
return r; |
||
1421 |
} |
||
1422 |
|||
1423 |
int |
||
1424 |
ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) |
||
1425 |
{ |
||
1426 |
176452 |
struct session_state *state = ssh->state; |
|
1427 |
u_int padlen, need; |
||
1428 |
88226 |
u_char *cp; |
|
1429 |
u_int maclen, aadlen = 0, authlen = 0, block_size; |
||
1430 |
struct sshenc *enc = NULL; |
||
1431 |
struct sshmac *mac = NULL; |
||
1432 |
struct sshcomp *comp = NULL; |
||
1433 |
int r; |
||
1434 |
|||
1435 |
✗✓ | 88226 |
if (state->mux) |
1436 |
return ssh_packet_read_poll2_mux(ssh, typep, seqnr_p); |
||
1437 |
|||
1438 |
88226 |
*typep = SSH_MSG_NONE; |
|
1439 |
|||
1440 |
✗✓ | 88226 |
if (state->packet_discard) |
1441 |
return 0; |
||
1442 |
|||
1443 |
✓✓ | 88226 |
if (state->newkeys[MODE_IN] != NULL) { |
1444 |
88221 |
enc = &state->newkeys[MODE_IN]->enc; |
|
1445 |
88221 |
mac = &state->newkeys[MODE_IN]->mac; |
|
1446 |
88221 |
comp = &state->newkeys[MODE_IN]->comp; |
|
1447 |
/* disable mac for authenticated encryption */ |
||
1448 |
✓✗ | 88221 |
if ((authlen = cipher_authlen(enc->cipher)) != 0) |
1449 |
88221 |
mac = NULL; |
|
1450 |
} |
||
1451 |
✗✓✗✗ |
176452 |
maclen = mac && mac->enabled ? mac->mac_len : 0; |
1452 |
✓✓ | 264673 |
block_size = enc ? enc->block_size : 8; |
1453 |
✗✓✗✗ ✗✗ |
264678 |
aadlen = (mac && mac->enabled && mac->etm) || authlen ? 4 : 0; |
1454 |
|||
1455 |
✓✓✓✗ |
176447 |
if (aadlen && state->packlen == 0) { |
1456 |
✓✓ | 264663 |
if (cipher_get_length(state->receive_context, |
1457 |
88221 |
&state->packlen, state->p_read.seqnr, |
|
1458 |
176442 |
sshbuf_ptr(state->input), sshbuf_len(state->input)) != 0) |
|
1459 |
73404 |
return 0; |
|
1460 |
✓✗✗✓ |
29634 |
if (state->packlen < 1 + 4 || |
1461 |
14817 |
state->packlen > PACKET_MAX_SIZE) { |
|
1462 |
#ifdef PACKET_DEBUG |
||
1463 |
sshbuf_dump(state->input, stderr); |
||
1464 |
#endif |
||
1465 |
logit("Bad packet length %u.", state->packlen); |
||
1466 |
if ((r = sshpkt_disconnect(ssh, "Packet corrupt")) != 0) |
||
1467 |
return r; |
||
1468 |
return SSH_ERR_CONN_CORRUPT; |
||
1469 |
} |
||
1470 |
14817 |
sshbuf_reset(state->incoming_packet); |
|
1471 |
✓✗ | 14822 |
} else if (state->packlen == 0) { |
1472 |
/* |
||
1473 |
* check if input size is less than the cipher block size, |
||
1474 |
* decrypt first block and extract length of incoming packet |
||
1475 |
*/ |
||
1476 |
✓✓ | 5 |
if (sshbuf_len(state->input) < block_size) |
1477 |
2 |
return 0; |
|
1478 |
3 |
sshbuf_reset(state->incoming_packet); |
|
1479 |
✓✗ | 6 |
if ((r = sshbuf_reserve(state->incoming_packet, block_size, |
1480 |
3 |
&cp)) != 0) |
|
1481 |
goto out; |
||
1482 |
✓✗ | 9 |
if ((r = cipher_crypt(state->receive_context, |
1483 |
3 |
state->p_send.seqnr, cp, sshbuf_ptr(state->input), |
|
1484 |
3 |
block_size, 0, 0)) != 0) |
|
1485 |
goto out; |
||
1486 |
3 |
state->packlen = PEEK_U32(sshbuf_ptr(state->incoming_packet)); |
|
1487 |
✓✗✗✓ |
6 |
if (state->packlen < 1 + 4 || |
1488 |
3 |
state->packlen > PACKET_MAX_SIZE) { |
|
1489 |
#ifdef PACKET_DEBUG |
||
1490 |
fprintf(stderr, "input: \n"); |
||
1491 |
sshbuf_dump(state->input, stderr); |
||
1492 |
fprintf(stderr, "incoming_packet: \n"); |
||
1493 |
sshbuf_dump(state->incoming_packet, stderr); |
||
1494 |
#endif |
||
1495 |
logit("Bad packet length %u.", state->packlen); |
||
1496 |
return ssh_packet_start_discard(ssh, enc, mac, 0, |
||
1497 |
PACKET_MAX_SIZE); |
||
1498 |
} |
||
1499 |
✓✗ | 3 |
if ((r = sshbuf_consume(state->input, block_size)) != 0) |
1500 |
goto out; |
||
1501 |
} |
||
1502 |
DBG(debug("input: packet len %u", state->packlen+4)); |
||
1503 |
|||
1504 |
✓✓ | 14820 |
if (aadlen) { |
1505 |
/* only the payload is encrypted */ |
||
1506 |
need = state->packlen; |
||
1507 |
14817 |
} else { |
|
1508 |
/* |
||
1509 |
* the payload size and the payload are encrypted, but we |
||
1510 |
* have a partial packet of block_size bytes |
||
1511 |
*/ |
||
1512 |
3 |
need = 4 + state->packlen - block_size; |
|
1513 |
} |
||
1514 |
DBG(debug("partial packet: block %d, need %d, maclen %d, authlen %d," |
||
1515 |
" aadlen %d", block_size, need, maclen, authlen, aadlen)); |
||
1516 |
✗✓ | 14820 |
if (need % block_size != 0) { |
1517 |
logit("padding error: need %d block %d mod %d", |
||
1518 |
need, block_size, need % block_size); |
||
1519 |
return ssh_packet_start_discard(ssh, enc, mac, 0, |
||
1520 |
PACKET_MAX_SIZE - block_size); |
||
1521 |
} |
||
1522 |
/* |
||
1523 |
* check if the entire packet has been received and |
||
1524 |
* decrypt into incoming_packet: |
||
1525 |
* 'aadlen' bytes are unencrypted, but authenticated. |
||
1526 |
* 'need' bytes are encrypted, followed by either |
||
1527 |
* 'authlen' bytes of authentication tag or |
||
1528 |
* 'maclen' bytes of message authentication code. |
||
1529 |
*/ |
||
1530 |
✗✓ | 14820 |
if (sshbuf_len(state->input) < aadlen + need + authlen + maclen) |
1531 |
return 0; /* packet is incomplete */ |
||
1532 |
#ifdef PACKET_DEBUG |
||
1533 |
fprintf(stderr, "read_poll enc/full: "); |
||
1534 |
sshbuf_dump(state->input, stderr); |
||
1535 |
#endif |
||
1536 |
/* EtM: check mac over encrypted input */ |
||
1537 |
✗✓✗✗ ✗✗ |
14820 |
if (mac && mac->enabled && mac->etm) { |
1538 |
if ((r = mac_check(mac, state->p_read.seqnr, |
||
1539 |
sshbuf_ptr(state->input), aadlen + need, |
||
1540 |
sshbuf_ptr(state->input) + aadlen + need + authlen, |
||
1541 |
maclen)) != 0) { |
||
1542 |
if (r == SSH_ERR_MAC_INVALID) |
||
1543 |
logit("Corrupted MAC on input."); |
||
1544 |
goto out; |
||
1545 |
} |
||
1546 |
} |
||
1547 |
✓✗ | 29640 |
if ((r = sshbuf_reserve(state->incoming_packet, aadlen + need, |
1548 |
14820 |
&cp)) != 0) |
|
1549 |
goto out; |
||
1550 |
✓✗ | 44460 |
if ((r = cipher_crypt(state->receive_context, state->p_read.seqnr, cp, |
1551 |
29640 |
sshbuf_ptr(state->input), need, aadlen, authlen)) != 0) |
|
1552 |
goto out; |
||
1553 |
✓✗ | 14820 |
if ((r = sshbuf_consume(state->input, aadlen + need + authlen)) != 0) |
1554 |
goto out; |
||
1555 |
✗✓✗✗ |
14820 |
if (mac && mac->enabled) { |
1556 |
/* Not EtM: check MAC over cleartext */ |
||
1557 |
if (!mac->etm && (r = mac_check(mac, state->p_read.seqnr, |
||
1558 |
sshbuf_ptr(state->incoming_packet), |
||
1559 |
sshbuf_len(state->incoming_packet), |
||
1560 |
sshbuf_ptr(state->input), maclen)) != 0) { |
||
1561 |
if (r != SSH_ERR_MAC_INVALID) |
||
1562 |
goto out; |
||
1563 |
logit("Corrupted MAC on input."); |
||
1564 |
if (need + block_size > PACKET_MAX_SIZE) |
||
1565 |
return SSH_ERR_INTERNAL_ERROR; |
||
1566 |
return ssh_packet_start_discard(ssh, enc, mac, |
||
1567 |
sshbuf_len(state->incoming_packet), |
||
1568 |
PACKET_MAX_SIZE - need - block_size); |
||
1569 |
} |
||
1570 |
/* Remove MAC from input buffer */ |
||
1571 |
DBG(debug("MAC #%d ok", state->p_read.seqnr)); |
||
1572 |
if ((r = sshbuf_consume(state->input, mac->mac_len)) != 0) |
||
1573 |
goto out; |
||
1574 |
} |
||
1575 |
✓✗ | 14820 |
if (seqnr_p != NULL) |
1576 |
14820 |
*seqnr_p = state->p_read.seqnr; |
|
1577 |
✗✓ | 14820 |
if (++state->p_read.seqnr == 0) |
1578 |
logit("incoming seqnr wraps around"); |
||
1579 |
✗✓ | 14820 |
if (++state->p_read.packets == 0) |
1580 |
if (!(ssh->compat & SSH_BUG_NOREKEY)) |
||
1581 |
return SSH_ERR_NEED_REKEY; |
||
1582 |
14820 |
state->p_read.blocks += (state->packlen + 4) / block_size; |
|
1583 |
14820 |
state->p_read.bytes += state->packlen + 4; |
|
1584 |
|||
1585 |
/* get padlen */ |
||
1586 |
14820 |
padlen = sshbuf_ptr(state->incoming_packet)[4]; |
|
1587 |
DBG(debug("input: padlen %d", padlen)); |
||
1588 |
✗✓ | 14820 |
if (padlen < 4) { |
1589 |
if ((r = sshpkt_disconnect(ssh, |
||
1590 |
"Corrupted padlen %d on input.", padlen)) != 0 || |
||
1591 |
(r = ssh_packet_write_wait(ssh)) != 0) |
||
1592 |
return r; |
||
1593 |
return SSH_ERR_CONN_CORRUPT; |
||
1594 |
} |
||
1595 |
|||
1596 |
/* skip packet size + padlen, discard padding */ |
||
1597 |
✓✗✓✗ |
29640 |
if ((r = sshbuf_consume(state->incoming_packet, 4 + 1)) != 0 || |
1598 |
14820 |
((r = sshbuf_consume_end(state->incoming_packet, padlen)) != 0)) |
|
1599 |
goto out; |
||
1600 |
|||
1601 |
DBG(debug("input: len before de-compress %zd", |
||
1602 |
sshbuf_len(state->incoming_packet))); |
||
1603 |
✓✓✗✓ |
29637 |
if (comp && comp->enabled) { |
1604 |
sshbuf_reset(state->compression_buffer); |
||
1605 |
if ((r = uncompress_buffer(ssh, state->incoming_packet, |
||
1606 |
state->compression_buffer)) != 0) |
||
1607 |
goto out; |
||
1608 |
sshbuf_reset(state->incoming_packet); |
||
1609 |
if ((r = sshbuf_putb(state->incoming_packet, |
||
1610 |
state->compression_buffer)) != 0) |
||
1611 |
goto out; |
||
1612 |
DBG(debug("input: len after de-compress %zd", |
||
1613 |
sshbuf_len(state->incoming_packet))); |
||
1614 |
} |
||
1615 |
/* |
||
1616 |
* get packet type, implies consume. |
||
1617 |
* return length of payload (without type field) |
||
1618 |
*/ |
||
1619 |
✓✗ | 14820 |
if ((r = sshbuf_get_u8(state->incoming_packet, typep)) != 0) |
1620 |
goto out; |
||
1621 |
✓✓ | 14820 |
if (ssh_packet_log_type(*typep)) |
1622 |
13 |
debug3("receive packet: type %u", *typep); |
|
1623 |
✓✗✗✓ |
29640 |
if (*typep < SSH2_MSG_MIN || *typep >= SSH2_MSG_LOCAL_MIN) { |
1624 |
if ((r = sshpkt_disconnect(ssh, |
||
1625 |
"Invalid ssh2 packet type: %d", *typep)) != 0 || |
||
1626 |
(r = ssh_packet_write_wait(ssh)) != 0) |
||
1627 |
return r; |
||
1628 |
return SSH_ERR_PROTOCOL_ERROR; |
||
1629 |
} |
||
1630 |
✗✓✗✗ |
14820 |
if (state->hook_in != NULL && |
1631 |
(r = state->hook_in(ssh, state->incoming_packet, typep, |
||
1632 |
state->hook_in_ctx)) != 0) |
||
1633 |
return r; |
||
1634 |
✓✓✓✗ |
14821 |
if (*typep == SSH2_MSG_USERAUTH_SUCCESS && !state->server_side) |
1635 |
1 |
r = ssh_packet_enable_delayed_compress(ssh); |
|
1636 |
else |
||
1637 |
r = 0; |
||
1638 |
#ifdef PACKET_DEBUG |
||
1639 |
fprintf(stderr, "read/plain[%d]:\r\n", *typep); |
||
1640 |
sshbuf_dump(state->incoming_packet, stderr); |
||
1641 |
#endif |
||
1642 |
/* reset for next packet */ |
||
1643 |
14820 |
state->packlen = 0; |
|
1644 |
|||
1645 |
/* do we need to rekey? */ |
||
1646 |
✗✓ | 14820 |
if (ssh_packet_need_rekeying(ssh, 0)) { |
1647 |
debug3("%s: rekex triggered", __func__); |
||
1648 |
if ((r = kex_start_rekex(ssh)) != 0) |
||
1649 |
return r; |
||
1650 |
} |
||
1651 |
out: |
||
1652 |
14820 |
return r; |
|
1653 |
88226 |
} |
|
1654 |
|||
1655 |
int |
||
1656 |
ssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) |
||
1657 |
{ |
||
1658 |
176452 |
struct session_state *state = ssh->state; |
|
1659 |
88226 |
u_int reason, seqnr; |
|
1660 |
int r; |
||
1661 |
88226 |
u_char *msg; |
|
1662 |
|||
1663 |
88226 |
for (;;) { |
|
1664 |
88226 |
msg = NULL; |
|
1665 |
88226 |
r = ssh_packet_read_poll2(ssh, typep, seqnr_p); |
|
1666 |
✗✓ | 88226 |
if (r != 0) |
1667 |
return r; |
||
1668 |
✓✓ | 88226 |
if (*typep) { |
1669 |
14820 |
state->keep_alive_timeouts = 0; |
|
1670 |
DBG(debug("received packet type %d", *typep)); |
||
1671 |
14820 |
} |
|
1672 |
✗✗✗✗ ✓ |
88226 |
switch (*typep) { |
1673 |
case SSH2_MSG_IGNORE: |
||
1674 |
debug3("Received SSH2_MSG_IGNORE"); |
||
1675 |
break; |
||
1676 |
case SSH2_MSG_DEBUG: |
||
1677 |
if ((r = sshpkt_get_u8(ssh, NULL)) != 0 || |
||
1678 |
(r = sshpkt_get_string(ssh, &msg, NULL)) != 0 || |
||
1679 |
(r = sshpkt_get_string(ssh, NULL, NULL)) != 0) { |
||
1680 |
free(msg); |
||
1681 |
return r; |
||
1682 |
} |
||
1683 |
debug("Remote: %.900s", msg); |
||
1684 |
free(msg); |
||
1685 |
break; |
||
1686 |
case SSH2_MSG_DISCONNECT: |
||
1687 |
if ((r = sshpkt_get_u32(ssh, &reason)) != 0 || |
||
1688 |
(r = sshpkt_get_string(ssh, &msg, NULL)) != 0) |
||
1689 |
return r; |
||
1690 |
/* Ignore normal client exit notifications */ |
||
1691 |
do_log2(ssh->state->server_side && |
||
1692 |
reason == SSH2_DISCONNECT_BY_APPLICATION ? |
||
1693 |
SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR, |
||
1694 |
"Received disconnect from %s port %d:" |
||
1695 |
"%u: %.400s", ssh_remote_ipaddr(ssh), |
||
1696 |
ssh_remote_port(ssh), reason, msg); |
||
1697 |
free(msg); |
||
1698 |
return SSH_ERR_DISCONNECTED; |
||
1699 |
case SSH2_MSG_UNIMPLEMENTED: |
||
1700 |
if ((r = sshpkt_get_u32(ssh, &seqnr)) != 0) |
||
1701 |
return r; |
||
1702 |
debug("Received SSH2_MSG_UNIMPLEMENTED for %u", |
||
1703 |
seqnr); |
||
1704 |
break; |
||
1705 |
default: |
||
1706 |
88226 |
return 0; |
|
1707 |
} |
||
1708 |
} |
||
1709 |
88226 |
} |
|
1710 |
|||
1711 |
/* |
||
1712 |
* Buffers the given amount of input characters. This is intended to be used |
||
1713 |
* together with packet_read_poll. |
||
1714 |
*/ |
||
1715 |
|||
1716 |
int |
||
1717 |
ssh_packet_process_incoming(struct ssh *ssh, const char *buf, u_int len) |
||
1718 |
{ |
||
1719 |
28810 |
struct session_state *state = ssh->state; |
|
1720 |
int r; |
||
1721 |
|||
1722 |
✗✓ | 14405 |
if (state->packet_discard) { |
1723 |
state->keep_alive_timeouts = 0; /* ?? */ |
||
1724 |
if (len >= state->packet_discard) { |
||
1725 |
if ((r = ssh_packet_stop_discard(ssh)) != 0) |
||
1726 |
return r; |
||
1727 |
} |
||
1728 |
state->packet_discard -= len; |
||
1729 |
return 0; |
||
1730 |
} |
||
1731 |
✗✓ | 14405 |
if ((r = sshbuf_put(ssh->state->input, buf, len)) != 0) |
1732 |
return r; |
||
1733 |
|||
1734 |
14405 |
return 0; |
|
1735 |
14405 |
} |
|
1736 |
|||
1737 |
int |
||
1738 |
ssh_packet_remaining(struct ssh *ssh) |
||
1739 |
{ |
||
1740 |
29628 |
return sshbuf_len(ssh->state->incoming_packet); |
|
1741 |
} |
||
1742 |
|||
1743 |
/* |
||
1744 |
* Sends a diagnostic message from the server to the client. This message |
||
1745 |
* can be sent at any time (but not while constructing another message). The |
||
1746 |
* message is printed immediately, but only if the client is being executed |
||
1747 |
* in verbose mode. These messages are primarily intended to ease debugging |
||
1748 |
* authentication problems. The length of the formatted message must not |
||
1749 |
* exceed 1024 bytes. This will automatically call ssh_packet_write_wait. |
||
1750 |
*/ |
||
1751 |
void |
||
1752 |
ssh_packet_send_debug(struct ssh *ssh, const char *fmt,...) |
||
1753 |
{ |
||
1754 |
char buf[1024]; |
||
1755 |
va_list args; |
||
1756 |
int r; |
||
1757 |
|||
1758 |
if ((ssh->compat & SSH_BUG_DEBUG)) |
||
1759 |
return; |
||
1760 |
|||
1761 |
va_start(args, fmt); |
||
1762 |
vsnprintf(buf, sizeof(buf), fmt, args); |
||
1763 |
va_end(args); |
||
1764 |
|||
1765 |
if ((r = sshpkt_start(ssh, SSH2_MSG_DEBUG)) != 0 || |
||
1766 |
(r = sshpkt_put_u8(ssh, 0)) != 0 || /* always display */ |
||
1767 |
(r = sshpkt_put_cstring(ssh, buf)) != 0 || |
||
1768 |
(r = sshpkt_put_cstring(ssh, "")) != 0 || |
||
1769 |
(r = sshpkt_send(ssh)) != 0 || |
||
1770 |
(r = ssh_packet_write_wait(ssh)) != 0) |
||
1771 |
fatal("%s: %s", __func__, ssh_err(r)); |
||
1772 |
} |
||
1773 |
|||
1774 |
static void |
||
1775 |
fmt_connection_id(struct ssh *ssh, char *s, size_t l) |
||
1776 |
{ |
||
1777 |
snprintf(s, l, "%.200s%s%s port %d", |
||
1778 |
ssh->log_preamble ? ssh->log_preamble : "", |
||
1779 |
ssh->log_preamble ? " " : "", |
||
1780 |
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); |
||
1781 |
} |
||
1782 |
|||
1783 |
/* |
||
1784 |
* Pretty-print connection-terminating errors and exit. |
||
1785 |
*/ |
||
1786 |
void |
||
1787 |
sshpkt_fatal(struct ssh *ssh, const char *tag, int r) |
||
1788 |
{ |
||
1789 |
char remote_id[512]; |
||
1790 |
|||
1791 |
fmt_connection_id(ssh, remote_id, sizeof(remote_id)); |
||
1792 |
|||
1793 |
switch (r) { |
||
1794 |
case SSH_ERR_CONN_CLOSED: |
||
1795 |
ssh_packet_clear_keys(ssh); |
||
1796 |
logdie("Connection closed by %s", remote_id); |
||
1797 |
case SSH_ERR_CONN_TIMEOUT: |
||
1798 |
ssh_packet_clear_keys(ssh); |
||
1799 |
logdie("Connection %s %s timed out", |
||
1800 |
ssh->state->server_side ? "from" : "to", remote_id); |
||
1801 |
case SSH_ERR_DISCONNECTED: |
||
1802 |
ssh_packet_clear_keys(ssh); |
||
1803 |
logdie("Disconnected from %s", remote_id); |
||
1804 |
case SSH_ERR_SYSTEM_ERROR: |
||
1805 |
if (errno == ECONNRESET) { |
||
1806 |
ssh_packet_clear_keys(ssh); |
||
1807 |
logdie("Connection reset by %s", remote_id); |
||
1808 |
} |
||
1809 |
/* FALLTHROUGH */ |
||
1810 |
case SSH_ERR_NO_CIPHER_ALG_MATCH: |
||
1811 |
case SSH_ERR_NO_MAC_ALG_MATCH: |
||
1812 |
case SSH_ERR_NO_COMPRESS_ALG_MATCH: |
||
1813 |
case SSH_ERR_NO_KEX_ALG_MATCH: |
||
1814 |
case SSH_ERR_NO_HOSTKEY_ALG_MATCH: |
||
1815 |
if (ssh && ssh->kex && ssh->kex->failed_choice) { |
||
1816 |
ssh_packet_clear_keys(ssh); |
||
1817 |
logdie("Unable to negotiate with %s: %s. " |
||
1818 |
"Their offer: %s", remote_id, ssh_err(r), |
||
1819 |
ssh->kex->failed_choice); |
||
1820 |
} |
||
1821 |
/* FALLTHROUGH */ |
||
1822 |
default: |
||
1823 |
ssh_packet_clear_keys(ssh); |
||
1824 |
logdie("%s%sConnection %s %s: %s", |
||
1825 |
tag != NULL ? tag : "", tag != NULL ? ": " : "", |
||
1826 |
ssh->state->server_side ? "from" : "to", |
||
1827 |
remote_id, ssh_err(r)); |
||
1828 |
} |
||
1829 |
} |
||
1830 |
|||
1831 |
/* |
||
1832 |
* Logs the error plus constructs and sends a disconnect packet, closes the |
||
1833 |
* connection, and exits. This function never returns. The error message |
||
1834 |
* should not contain a newline. The length of the formatted message must |
||
1835 |
* not exceed 1024 bytes. |
||
1836 |
*/ |
||
1837 |
void |
||
1838 |
ssh_packet_disconnect(struct ssh *ssh, const char *fmt,...) |
||
1839 |
{ |
||
1840 |
char buf[1024], remote_id[512]; |
||
1841 |
va_list args; |
||
1842 |
static int disconnecting = 0; |
||
1843 |
int r; |
||
1844 |
|||
1845 |
if (disconnecting) /* Guard against recursive invocations. */ |
||
1846 |
fatal("packet_disconnect called recursively."); |
||
1847 |
disconnecting = 1; |
||
1848 |
|||
1849 |
/* |
||
1850 |
* Format the message. Note that the caller must make sure the |
||
1851 |
* message is of limited size. |
||
1852 |
*/ |
||
1853 |
fmt_connection_id(ssh, remote_id, sizeof(remote_id)); |
||
1854 |
va_start(args, fmt); |
||
1855 |
vsnprintf(buf, sizeof(buf), fmt, args); |
||
1856 |
va_end(args); |
||
1857 |
|||
1858 |
/* Display the error locally */ |
||
1859 |
logit("Disconnecting %s: %.100s", remote_id, buf); |
||
1860 |
|||
1861 |
/* |
||
1862 |
* Send the disconnect message to the other side, and wait |
||
1863 |
* for it to get sent. |
||
1864 |
*/ |
||
1865 |
if ((r = sshpkt_disconnect(ssh, "%s", buf)) != 0) |
||
1866 |
sshpkt_fatal(ssh, __func__, r); |
||
1867 |
|||
1868 |
if ((r = ssh_packet_write_wait(ssh)) != 0) |
||
1869 |
sshpkt_fatal(ssh, __func__, r); |
||
1870 |
|||
1871 |
/* Close the connection. */ |
||
1872 |
ssh_packet_close(ssh); |
||
1873 |
cleanup_exit(255); |
||
1874 |
} |
||
1875 |
|||
1876 |
/* |
||
1877 |
* Checks if there is any buffered output, and tries to write some of |
||
1878 |
* the output. |
||
1879 |
*/ |
||
1880 |
int |
||
1881 |
ssh_packet_write_poll(struct ssh *ssh) |
||
1882 |
{ |
||
1883 |
84292 |
struct session_state *state = ssh->state; |
|
1884 |
42146 |
int len = sshbuf_len(state->output); |
|
1885 |
int r; |
||
1886 |
|||
1887 |
✓✓ | 42146 |
if (len > 0) { |
1888 |
84290 |
len = write(state->connection_out, |
|
1889 |
42145 |
sshbuf_ptr(state->output), len); |
|
1890 |
✗✓ | 42145 |
if (len == -1) { |
1891 |
if (errno == EINTR || errno == EAGAIN) |
||
1892 |
return 0; |
||
1893 |
return SSH_ERR_SYSTEM_ERROR; |
||
1894 |
} |
||
1895 |
✗✓ | 42145 |
if (len == 0) |
1896 |
return SSH_ERR_CONN_CLOSED; |
||
1897 |
✗✓ | 42145 |
if ((r = sshbuf_consume(state->output, len)) != 0) |
1898 |
return r; |
||
1899 |
} |
||
1900 |
42146 |
return 0; |
|
1901 |
42146 |
} |
|
1902 |
|||
1903 |
/* |
||
1904 |
* Calls packet_write_poll repeatedly until all pending output data has been |
||
1905 |
* written. |
||
1906 |
*/ |
||
1907 |
int |
||
1908 |
ssh_packet_write_wait(struct ssh *ssh) |
||
1909 |
{ |
||
1910 |
fd_set *setp; |
||
1911 |
16 |
int ret, r, ms_remain = 0; |
|
1912 |
8 |
struct timeval start, timeout, *timeoutp = NULL; |
|
1913 |
8 |
struct session_state *state = ssh->state; |
|
1914 |
|||
1915 |
8 |
setp = calloc(howmany(state->connection_out + 1, |
|
1916 |
NFDBITS), sizeof(fd_mask)); |
||
1917 |
✗✓ | 8 |
if (setp == NULL) |
1918 |
return SSH_ERR_ALLOC_FAIL; |
||
1919 |
✗✓ | 8 |
if ((r = ssh_packet_write_poll(ssh)) != 0) { |
1920 |
free(setp); |
||
1921 |
return r; |
||
1922 |
} |
||
1923 |
✗✓ | 8 |
while (ssh_packet_have_data_to_write(ssh)) { |
1924 |
memset(setp, 0, howmany(state->connection_out + 1, |
||
1925 |
NFDBITS) * sizeof(fd_mask)); |
||
1926 |
FD_SET(state->connection_out, setp); |
||
1927 |
|||
1928 |
if (state->packet_timeout_ms > 0) { |
||
1929 |
ms_remain = state->packet_timeout_ms; |
||
1930 |
timeoutp = &timeout; |
||
1931 |
} |
||
1932 |
for (;;) { |
||
1933 |
if (state->packet_timeout_ms != -1) { |
||
1934 |
ms_to_timeval(&timeout, ms_remain); |
||
1935 |
gettimeofday(&start, NULL); |
||
1936 |
} |
||
1937 |
if ((ret = select(state->connection_out + 1, |
||
1938 |
NULL, setp, NULL, timeoutp)) >= 0) |
||
1939 |
break; |
||
1940 |
if (errno != EAGAIN && errno != EINTR) |
||
1941 |
break; |
||
1942 |
if (state->packet_timeout_ms == -1) |
||
1943 |
continue; |
||
1944 |
ms_subtract_diff(&start, &ms_remain); |
||
1945 |
if (ms_remain <= 0) { |
||
1946 |
ret = 0; |
||
1947 |
break; |
||
1948 |
} |
||
1949 |
} |
||
1950 |
if (ret == 0) { |
||
1951 |
free(setp); |
||
1952 |
return SSH_ERR_CONN_TIMEOUT; |
||
1953 |
} |
||
1954 |
if ((r = ssh_packet_write_poll(ssh)) != 0) { |
||
1955 |
free(setp); |
||
1956 |
return r; |
||
1957 |
} |
||
1958 |
} |
||
1959 |
8 |
free(setp); |
|
1960 |
8 |
return 0; |
|
1961 |
8 |
} |
|
1962 |
|||
1963 |
/* Returns true if there is buffered data to write to the connection. */ |
||
1964 |
|||
1965 |
int |
||
1966 |
ssh_packet_have_data_to_write(struct ssh *ssh) |
||
1967 |
{ |
||
1968 |
146818 |
return sshbuf_len(ssh->state->output) != 0; |
|
1969 |
} |
||
1970 |
|||
1971 |
/* Returns true if there is not too much data to write to the connection. */ |
||
1972 |
|||
1973 |
int |
||
1974 |
ssh_packet_not_very_much_data_to_write(struct ssh *ssh) |
||
1975 |
{ |
||
1976 |
✗✓ | 220200 |
if (ssh->state->interactive_mode) |
1977 |
73400 |
return sshbuf_len(ssh->state->output) < 16384; |
|
1978 |
else |
||
1979 |
73400 |
return sshbuf_len(ssh->state->output) < 128 * 1024; |
|
1980 |
73400 |
} |
|
1981 |
|||
1982 |
void |
||
1983 |
ssh_packet_set_tos(struct ssh *ssh, int tos) |
||
1984 |
{ |
||
1985 |
✓✗ | 1 |
if (!ssh_packet_connection_is_on_socket(ssh) || tos == INT_MAX) |
1986 |
return; |
||
1987 |
✓✗✓ | 2 |
switch (ssh_packet_connection_af(ssh)) { |
1988 |
case AF_INET: |
||
1989 |
1 |
debug3("%s: set IP_TOS 0x%02x", __func__, tos); |
|
1990 |
✗✓ | 3 |
if (setsockopt(ssh->state->connection_in, |
1991 |
2 |
IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) |
|
1992 |
error("setsockopt IP_TOS %d: %.100s:", |
||
1993 |
tos, strerror(errno)); |
||
1994 |
break; |
||
1995 |
case AF_INET6: |
||
1996 |
debug3("%s: set IPV6_TCLASS 0x%02x", __func__, tos); |
||
1997 |
if (setsockopt(ssh->state->connection_in, |
||
1998 |
IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof(tos)) < 0) |
||
1999 |
error("setsockopt IPV6_TCLASS %d: %.100s:", |
||
2000 |
tos, strerror(errno)); |
||
2001 |
break; |
||
2002 |
} |
||
2003 |
1 |
} |
|
2004 |
|||
2005 |
/* Informs that the current session is interactive. Sets IP flags for that. */ |
||
2006 |
|||
2007 |
void |
||
2008 |
ssh_packet_set_interactive(struct ssh *ssh, int interactive, int qos_interactive, int qos_bulk) |
||
2009 |
{ |
||
2010 |
4 |
struct session_state *state = ssh->state; |
|
2011 |
|||
2012 |
✓✓ | 2 |
if (state->set_interactive_called) |
2013 |
1 |
return; |
|
2014 |
1 |
state->set_interactive_called = 1; |
|
2015 |
|||
2016 |
/* Record that we are in interactive mode. */ |
||
2017 |
1 |
state->interactive_mode = interactive; |
|
2018 |
|||
2019 |
/* Only set socket options if using a socket. */ |
||
2020 |
✗✓ | 1 |
if (!ssh_packet_connection_is_on_socket(ssh)) |
2021 |
return; |
||
2022 |
1 |
set_nodelay(state->connection_in); |
|
2023 |
1 |
ssh_packet_set_tos(ssh, interactive ? qos_interactive : |
|
2024 |
qos_bulk); |
||
2025 |
3 |
} |
|
2026 |
|||
2027 |
/* Returns true if the current connection is interactive. */ |
||
2028 |
|||
2029 |
int |
||
2030 |
ssh_packet_is_interactive(struct ssh *ssh) |
||
2031 |
{ |
||
2032 |
return ssh->state->interactive_mode; |
||
2033 |
} |
||
2034 |
|||
2035 |
int |
||
2036 |
ssh_packet_set_maxsize(struct ssh *ssh, u_int s) |
||
2037 |
{ |
||
2038 |
struct session_state *state = ssh->state; |
||
2039 |
|||
2040 |
if (state->set_maxsize_called) { |
||
2041 |
logit("packet_set_maxsize: called twice: old %d new %d", |
||
2042 |
state->max_packet_size, s); |
||
2043 |
return -1; |
||
2044 |
} |
||
2045 |
if (s < 4 * 1024 || s > 1024 * 1024) { |
||
2046 |
logit("packet_set_maxsize: bad size %d", s); |
||
2047 |
return -1; |
||
2048 |
} |
||
2049 |
state->set_maxsize_called = 1; |
||
2050 |
debug("packet_set_maxsize: setting to %d", s); |
||
2051 |
state->max_packet_size = s; |
||
2052 |
return s; |
||
2053 |
} |
||
2054 |
|||
2055 |
int |
||
2056 |
ssh_packet_inc_alive_timeouts(struct ssh *ssh) |
||
2057 |
{ |
||
2058 |
return ++ssh->state->keep_alive_timeouts; |
||
2059 |
} |
||
2060 |
|||
2061 |
void |
||
2062 |
ssh_packet_set_alive_timeouts(struct ssh *ssh, int ka) |
||
2063 |
{ |
||
2064 |
2 |
ssh->state->keep_alive_timeouts = ka; |
|
2065 |
1 |
} |
|
2066 |
|||
2067 |
u_int |
||
2068 |
ssh_packet_get_maxsize(struct ssh *ssh) |
||
2069 |
{ |
||
2070 |
return ssh->state->max_packet_size; |
||
2071 |
} |
||
2072 |
|||
2073 |
void |
||
2074 |
ssh_packet_set_rekey_limits(struct ssh *ssh, u_int64_t bytes, u_int32_t seconds) |
||
2075 |
{ |
||
2076 |
debug3("rekey after %llu bytes, %u seconds", (unsigned long long)bytes, |
||
2077 |
(unsigned int)seconds); |
||
2078 |
ssh->state->rekey_limit = bytes; |
||
2079 |
ssh->state->rekey_interval = seconds; |
||
2080 |
} |
||
2081 |
|||
2082 |
time_t |
||
2083 |
ssh_packet_get_rekey_timeout(struct ssh *ssh) |
||
2084 |
{ |
||
2085 |
time_t seconds; |
||
2086 |
|||
2087 |
seconds = ssh->state->rekey_time + ssh->state->rekey_interval - |
||
2088 |
monotime(); |
||
2089 |
return (seconds <= 0 ? 1 : seconds); |
||
2090 |
} |
||
2091 |
|||
2092 |
void |
||
2093 |
ssh_packet_set_server(struct ssh *ssh) |
||
2094 |
{ |
||
2095 |
ssh->state->server_side = 1; |
||
2096 |
} |
||
2097 |
|||
2098 |
void |
||
2099 |
ssh_packet_set_authenticated(struct ssh *ssh) |
||
2100 |
{ |
||
2101 |
ssh->state->after_authentication = 1; |
||
2102 |
} |
||
2103 |
|||
2104 |
void * |
||
2105 |
ssh_packet_get_input(struct ssh *ssh) |
||
2106 |
{ |
||
2107 |
return (void *)ssh->state->input; |
||
2108 |
} |
||
2109 |
|||
2110 |
void * |
||
2111 |
ssh_packet_get_output(struct ssh *ssh) |
||
2112 |
{ |
||
2113 |
return (void *)ssh->state->output; |
||
2114 |
} |
||
2115 |
|||
2116 |
/* Reset after_authentication and reset compression in post-auth privsep */ |
||
2117 |
static int |
||
2118 |
ssh_packet_set_postauth(struct ssh *ssh) |
||
2119 |
{ |
||
2120 |
int r; |
||
2121 |
|||
2122 |
debug("%s: called", __func__); |
||
2123 |
/* This was set in net child, but is not visible in user child */ |
||
2124 |
ssh->state->after_authentication = 1; |
||
2125 |
ssh->state->rekeying = 0; |
||
2126 |
if ((r = ssh_packet_enable_delayed_compress(ssh)) != 0) |
||
2127 |
return r; |
||
2128 |
return 0; |
||
2129 |
} |
||
2130 |
|||
2131 |
/* Packet state (de-)serialization for privsep */ |
||
2132 |
|||
2133 |
/* turn kex into a blob for packet state serialization */ |
||
2134 |
static int |
||
2135 |
kex_to_blob(struct sshbuf *m, struct kex *kex) |
||
2136 |
{ |
||
2137 |
int r; |
||
2138 |
|||
2139 |
if ((r = sshbuf_put_string(m, kex->session_id, |
||
2140 |
kex->session_id_len)) != 0 || |
||
2141 |
(r = sshbuf_put_u32(m, kex->we_need)) != 0 || |
||
2142 |
(r = sshbuf_put_u32(m, kex->hostkey_type)) != 0 || |
||
2143 |
(r = sshbuf_put_u32(m, kex->kex_type)) != 0 || |
||
2144 |
(r = sshbuf_put_stringb(m, kex->my)) != 0 || |
||
2145 |
(r = sshbuf_put_stringb(m, kex->peer)) != 0 || |
||
2146 |
(r = sshbuf_put_u32(m, kex->flags)) != 0 || |
||
2147 |
(r = sshbuf_put_cstring(m, kex->client_version_string)) != 0 || |
||
2148 |
(r = sshbuf_put_cstring(m, kex->server_version_string)) != 0) |
||
2149 |
return r; |
||
2150 |
return 0; |
||
2151 |
} |
||
2152 |
|||
2153 |
/* turn key exchange results into a blob for packet state serialization */ |
||
2154 |
static int |
||
2155 |
newkeys_to_blob(struct sshbuf *m, struct ssh *ssh, int mode) |
||
2156 |
{ |
||
2157 |
struct sshbuf *b; |
||
2158 |
struct sshcipher_ctx *cc; |
||
2159 |
struct sshcomp *comp; |
||
2160 |
struct sshenc *enc; |
||
2161 |
struct sshmac *mac; |
||
2162 |
struct newkeys *newkey; |
||
2163 |
int r; |
||
2164 |
|||
2165 |
if ((newkey = ssh->state->newkeys[mode]) == NULL) |
||
2166 |
return SSH_ERR_INTERNAL_ERROR; |
||
2167 |
enc = &newkey->enc; |
||
2168 |
mac = &newkey->mac; |
||
2169 |
comp = &newkey->comp; |
||
2170 |
cc = (mode == MODE_OUT) ? ssh->state->send_context : |
||
2171 |
ssh->state->receive_context; |
||
2172 |
if ((r = cipher_get_keyiv(cc, enc->iv, enc->iv_len)) != 0) |
||
2173 |
return r; |
||
2174 |
if ((b = sshbuf_new()) == NULL) |
||
2175 |
return SSH_ERR_ALLOC_FAIL; |
||
2176 |
if ((r = sshbuf_put_cstring(b, enc->name)) != 0 || |
||
2177 |
(r = sshbuf_put_u32(b, enc->enabled)) != 0 || |
||
2178 |
(r = sshbuf_put_u32(b, enc->block_size)) != 0 || |
||
2179 |
(r = sshbuf_put_string(b, enc->key, enc->key_len)) != 0 || |
||
2180 |
(r = sshbuf_put_string(b, enc->iv, enc->iv_len)) != 0) |
||
2181 |
goto out; |
||
2182 |
if (cipher_authlen(enc->cipher) == 0) { |
||
2183 |
if ((r = sshbuf_put_cstring(b, mac->name)) != 0 || |
||
2184 |
(r = sshbuf_put_u32(b, mac->enabled)) != 0 || |
||
2185 |
(r = sshbuf_put_string(b, mac->key, mac->key_len)) != 0) |
||
2186 |
goto out; |
||
2187 |
} |
||
2188 |
if ((r = sshbuf_put_u32(b, comp->type)) != 0 || |
||
2189 |
(r = sshbuf_put_cstring(b, comp->name)) != 0) |
||
2190 |
goto out; |
||
2191 |
r = sshbuf_put_stringb(m, b); |
||
2192 |
out: |
||
2193 |
sshbuf_free(b); |
||
2194 |
return r; |
||
2195 |
} |
||
2196 |
|||
2197 |
/* serialize packet state into a blob */ |
||
2198 |
int |
||
2199 |
ssh_packet_get_state(struct ssh *ssh, struct sshbuf *m) |
||
2200 |
{ |
||
2201 |
struct session_state *state = ssh->state; |
||
2202 |
int r; |
||
2203 |
|||
2204 |
if ((r = kex_to_blob(m, ssh->kex)) != 0 || |
||
2205 |
(r = newkeys_to_blob(m, ssh, MODE_OUT)) != 0 || |
||
2206 |
(r = newkeys_to_blob(m, ssh, MODE_IN)) != 0 || |
||
2207 |
(r = sshbuf_put_u64(m, state->rekey_limit)) != 0 || |
||
2208 |
(r = sshbuf_put_u32(m, state->rekey_interval)) != 0 || |
||
2209 |
(r = sshbuf_put_u32(m, state->p_send.seqnr)) != 0 || |
||
2210 |
(r = sshbuf_put_u64(m, state->p_send.blocks)) != 0 || |
||
2211 |
(r = sshbuf_put_u32(m, state->p_send.packets)) != 0 || |
||
2212 |
(r = sshbuf_put_u64(m, state->p_send.bytes)) != 0 || |
||
2213 |
(r = sshbuf_put_u32(m, state->p_read.seqnr)) != 0 || |
||
2214 |
(r = sshbuf_put_u64(m, state->p_read.blocks)) != 0 || |
||
2215 |
(r = sshbuf_put_u32(m, state->p_read.packets)) != 0 || |
||
2216 |
(r = sshbuf_put_u64(m, state->p_read.bytes)) != 0 || |
||
2217 |
(r = sshbuf_put_stringb(m, state->input)) != 0 || |
||
2218 |
(r = sshbuf_put_stringb(m, state->output)) != 0) |
||
2219 |
return r; |
||
2220 |
|||
2221 |
return 0; |
||
2222 |
} |
||
2223 |
|||
2224 |
/* restore key exchange results from blob for packet state de-serialization */ |
||
2225 |
static int |
||
2226 |
newkeys_from_blob(struct sshbuf *m, struct ssh *ssh, int mode) |
||
2227 |
{ |
||
2228 |
struct sshbuf *b = NULL; |
||
2229 |
struct sshcomp *comp; |
||
2230 |
struct sshenc *enc; |
||
2231 |
struct sshmac *mac; |
||
2232 |
struct newkeys *newkey = NULL; |
||
2233 |
size_t keylen, ivlen, maclen; |
||
2234 |
int r; |
||
2235 |
|||
2236 |
if ((newkey = calloc(1, sizeof(*newkey))) == NULL) { |
||
2237 |
r = SSH_ERR_ALLOC_FAIL; |
||
2238 |
goto out; |
||
2239 |
} |
||
2240 |
if ((r = sshbuf_froms(m, &b)) != 0) |
||
2241 |
goto out; |
||
2242 |
#ifdef DEBUG_PK |
||
2243 |
sshbuf_dump(b, stderr); |
||
2244 |
#endif |
||
2245 |
enc = &newkey->enc; |
||
2246 |
mac = &newkey->mac; |
||
2247 |
comp = &newkey->comp; |
||
2248 |
|||
2249 |
if ((r = sshbuf_get_cstring(b, &enc->name, NULL)) != 0 || |
||
2250 |
(r = sshbuf_get_u32(b, (u_int *)&enc->enabled)) != 0 || |
||
2251 |
(r = sshbuf_get_u32(b, &enc->block_size)) != 0 || |
||
2252 |
(r = sshbuf_get_string(b, &enc->key, &keylen)) != 0 || |
||
2253 |
(r = sshbuf_get_string(b, &enc->iv, &ivlen)) != 0) |
||
2254 |
goto out; |
||
2255 |
if ((enc->cipher = cipher_by_name(enc->name)) == NULL) { |
||
2256 |
r = SSH_ERR_INVALID_FORMAT; |
||
2257 |
goto out; |
||
2258 |
} |
||
2259 |
if (cipher_authlen(enc->cipher) == 0) { |
||
2260 |
if ((r = sshbuf_get_cstring(b, &mac->name, NULL)) != 0) |
||
2261 |
goto out; |
||
2262 |
if ((r = mac_setup(mac, mac->name)) != 0) |
||
2263 |
goto out; |
||
2264 |
if ((r = sshbuf_get_u32(b, (u_int *)&mac->enabled)) != 0 || |
||
2265 |
(r = sshbuf_get_string(b, &mac->key, &maclen)) != 0) |
||
2266 |
goto out; |
||
2267 |
if (maclen > mac->key_len) { |
||
2268 |
r = SSH_ERR_INVALID_FORMAT; |
||
2269 |
goto out; |
||
2270 |
} |
||
2271 |
mac->key_len = maclen; |
||
2272 |
} |
||
2273 |
if ((r = sshbuf_get_u32(b, &comp->type)) != 0 || |
||
2274 |
(r = sshbuf_get_cstring(b, &comp->name, NULL)) != 0) |
||
2275 |
goto out; |
||
2276 |
if (sshbuf_len(b) != 0) { |
||
2277 |
r = SSH_ERR_INVALID_FORMAT; |
||
2278 |
goto out; |
||
2279 |
} |
||
2280 |
enc->key_len = keylen; |
||
2281 |
enc->iv_len = ivlen; |
||
2282 |
ssh->kex->newkeys[mode] = newkey; |
||
2283 |
newkey = NULL; |
||
2284 |
r = 0; |
||
2285 |
out: |
||
2286 |
free(newkey); |
||
2287 |
sshbuf_free(b); |
||
2288 |
return r; |
||
2289 |
} |
||
2290 |
|||
2291 |
/* restore kex from blob for packet state de-serialization */ |
||
2292 |
static int |
||
2293 |
kex_from_blob(struct sshbuf *m, struct kex **kexp) |
||
2294 |
{ |
||
2295 |
struct kex *kex; |
||
2296 |
int r; |
||
2297 |
|||
2298 |
if ((kex = calloc(1, sizeof(struct kex))) == NULL || |
||
2299 |
(kex->my = sshbuf_new()) == NULL || |
||
2300 |
(kex->peer = sshbuf_new()) == NULL) { |
||
2301 |
r = SSH_ERR_ALLOC_FAIL; |
||
2302 |
goto out; |
||
2303 |
} |
||
2304 |
if ((r = sshbuf_get_string(m, &kex->session_id, &kex->session_id_len)) != 0 || |
||
2305 |
(r = sshbuf_get_u32(m, &kex->we_need)) != 0 || |
||
2306 |
(r = sshbuf_get_u32(m, (u_int *)&kex->hostkey_type)) != 0 || |
||
2307 |
(r = sshbuf_get_u32(m, &kex->kex_type)) != 0 || |
||
2308 |
(r = sshbuf_get_stringb(m, kex->my)) != 0 || |
||
2309 |
(r = sshbuf_get_stringb(m, kex->peer)) != 0 || |
||
2310 |
(r = sshbuf_get_u32(m, &kex->flags)) != 0 || |
||
2311 |
(r = sshbuf_get_cstring(m, &kex->client_version_string, NULL)) != 0 || |
||
2312 |
(r = sshbuf_get_cstring(m, &kex->server_version_string, NULL)) != 0) |
||
2313 |
goto out; |
||
2314 |
kex->server = 1; |
||
2315 |
kex->done = 1; |
||
2316 |
r = 0; |
||
2317 |
out: |
||
2318 |
if (r != 0 || kexp == NULL) { |
||
2319 |
if (kex != NULL) { |
||
2320 |
sshbuf_free(kex->my); |
||
2321 |
sshbuf_free(kex->peer); |
||
2322 |
free(kex); |
||
2323 |
} |
||
2324 |
if (kexp != NULL) |
||
2325 |
*kexp = NULL; |
||
2326 |
} else { |
||
2327 |
*kexp = kex; |
||
2328 |
} |
||
2329 |
return r; |
||
2330 |
} |
||
2331 |
|||
2332 |
/* |
||
2333 |
* Restore packet state from content of blob 'm' (de-serialization). |
||
2334 |
* Note that 'm' will be partially consumed on parsing or any other errors. |
||
2335 |
*/ |
||
2336 |
int |
||
2337 |
ssh_packet_set_state(struct ssh *ssh, struct sshbuf *m) |
||
2338 |
{ |
||
2339 |
struct session_state *state = ssh->state; |
||
2340 |
const u_char *input, *output; |
||
2341 |
size_t ilen, olen; |
||
2342 |
int r; |
||
2343 |
|||
2344 |
if ((r = kex_from_blob(m, &ssh->kex)) != 0 || |
||
2345 |
(r = newkeys_from_blob(m, ssh, MODE_OUT)) != 0 || |
||
2346 |
(r = newkeys_from_blob(m, ssh, MODE_IN)) != 0 || |
||
2347 |
(r = sshbuf_get_u64(m, &state->rekey_limit)) != 0 || |
||
2348 |
(r = sshbuf_get_u32(m, &state->rekey_interval)) != 0 || |
||
2349 |
(r = sshbuf_get_u32(m, &state->p_send.seqnr)) != 0 || |
||
2350 |
(r = sshbuf_get_u64(m, &state->p_send.blocks)) != 0 || |
||
2351 |
(r = sshbuf_get_u32(m, &state->p_send.packets)) != 0 || |
||
2352 |
(r = sshbuf_get_u64(m, &state->p_send.bytes)) != 0 || |
||
2353 |
(r = sshbuf_get_u32(m, &state->p_read.seqnr)) != 0 || |
||
2354 |
(r = sshbuf_get_u64(m, &state->p_read.blocks)) != 0 || |
||
2355 |
(r = sshbuf_get_u32(m, &state->p_read.packets)) != 0 || |
||
2356 |
(r = sshbuf_get_u64(m, &state->p_read.bytes)) != 0) |
||
2357 |
return r; |
||
2358 |
/* |
||
2359 |
* We set the time here so that in post-auth privsep slave we |
||
2360 |
* count from the completion of the authentication. |
||
2361 |
*/ |
||
2362 |
state->rekey_time = monotime(); |
||
2363 |
/* XXX ssh_set_newkeys overrides p_read.packets? XXX */ |
||
2364 |
if ((r = ssh_set_newkeys(ssh, MODE_IN)) != 0 || |
||
2365 |
(r = ssh_set_newkeys(ssh, MODE_OUT)) != 0) |
||
2366 |
return r; |
||
2367 |
|||
2368 |
if ((r = ssh_packet_set_postauth(ssh)) != 0) |
||
2369 |
return r; |
||
2370 |
|||
2371 |
sshbuf_reset(state->input); |
||
2372 |
sshbuf_reset(state->output); |
||
2373 |
if ((r = sshbuf_get_string_direct(m, &input, &ilen)) != 0 || |
||
2374 |
(r = sshbuf_get_string_direct(m, &output, &olen)) != 0 || |
||
2375 |
(r = sshbuf_put(state->input, input, ilen)) != 0 || |
||
2376 |
(r = sshbuf_put(state->output, output, olen)) != 0) |
||
2377 |
return r; |
||
2378 |
|||
2379 |
if (sshbuf_len(m)) |
||
2380 |
return SSH_ERR_INVALID_FORMAT; |
||
2381 |
debug3("%s: done", __func__); |
||
2382 |
return 0; |
||
2383 |
} |
||
2384 |
|||
2385 |
/* NEW API */ |
||
2386 |
|||
2387 |
/* put data to the outgoing packet */ |
||
2388 |
|||
2389 |
int |
||
2390 |
sshpkt_put(struct ssh *ssh, const void *v, size_t len) |
||
2391 |
{ |
||
2392 |
return sshbuf_put(ssh->state->outgoing_packet, v, len); |
||
2393 |
} |
||
2394 |
|||
2395 |
int |
||
2396 |
sshpkt_putb(struct ssh *ssh, const struct sshbuf *b) |
||
2397 |
{ |
||
2398 |
2 |
return sshbuf_putb(ssh->state->outgoing_packet, b); |
|
2399 |
} |
||
2400 |
|||
2401 |
int |
||
2402 |
sshpkt_put_u8(struct ssh *ssh, u_char val) |
||
2403 |
{ |
||
2404 |
6 |
return sshbuf_put_u8(ssh->state->outgoing_packet, val); |
|
2405 |
} |
||
2406 |
|||
2407 |
int |
||
2408 |
sshpkt_put_u32(struct ssh *ssh, u_int32_t val) |
||
2409 |
{ |
||
2410 |
85294 |
return sshbuf_put_u32(ssh->state->outgoing_packet, val); |
|
2411 |
} |
||
2412 |
|||
2413 |
int |
||
2414 |
sshpkt_put_u64(struct ssh *ssh, u_int64_t val) |
||
2415 |
{ |
||
2416 |
return sshbuf_put_u64(ssh->state->outgoing_packet, val); |
||
2417 |
} |
||
2418 |
|||
2419 |
int |
||
2420 |
sshpkt_put_string(struct ssh *ssh, const void *v, size_t len) |
||
2421 |
{ |
||
2422 |
85284 |
return sshbuf_put_string(ssh->state->outgoing_packet, v, len); |
|
2423 |
} |
||
2424 |
|||
2425 |
int |
||
2426 |
sshpkt_put_cstring(struct ssh *ssh, const void *v) |
||
2427 |
{ |
||
2428 |
26 |
return sshbuf_put_cstring(ssh->state->outgoing_packet, v); |
|
2429 |
} |
||
2430 |
|||
2431 |
int |
||
2432 |
sshpkt_put_stringb(struct ssh *ssh, const struct sshbuf *v) |
||
2433 |
{ |
||
2434 |
return sshbuf_put_stringb(ssh->state->outgoing_packet, v); |
||
2435 |
} |
||
2436 |
|||
2437 |
#ifdef WITH_OPENSSL |
||
2438 |
int |
||
2439 |
sshpkt_put_ec(struct ssh *ssh, const EC_POINT *v, const EC_GROUP *g) |
||
2440 |
{ |
||
2441 |
return sshbuf_put_ec(ssh->state->outgoing_packet, v, g); |
||
2442 |
} |
||
2443 |
|||
2444 |
|||
2445 |
int |
||
2446 |
sshpkt_put_bignum2(struct ssh *ssh, const BIGNUM *v) |
||
2447 |
{ |
||
2448 |
return sshbuf_put_bignum2(ssh->state->outgoing_packet, v); |
||
2449 |
} |
||
2450 |
#endif /* WITH_OPENSSL */ |
||
2451 |
|||
2452 |
/* fetch data from the incoming packet */ |
||
2453 |
|||
2454 |
int |
||
2455 |
sshpkt_get(struct ssh *ssh, void *valp, size_t len) |
||
2456 |
{ |
||
2457 |
return sshbuf_get(ssh->state->incoming_packet, valp, len); |
||
2458 |
} |
||
2459 |
|||
2460 |
int |
||
2461 |
sshpkt_get_u8(struct ssh *ssh, u_char *valp) |
||
2462 |
{ |
||
2463 |
40 |
return sshbuf_get_u8(ssh->state->incoming_packet, valp); |
|
2464 |
} |
||
2465 |
|||
2466 |
int |
||
2467 |
sshpkt_get_u32(struct ssh *ssh, u_int32_t *valp) |
||
2468 |
{ |
||
2469 |
40260 |
return sshbuf_get_u32(ssh->state->incoming_packet, valp); |
|
2470 |
} |
||
2471 |
|||
2472 |
int |
||
2473 |
sshpkt_get_u64(struct ssh *ssh, u_int64_t *valp) |
||
2474 |
{ |
||
2475 |
return sshbuf_get_u64(ssh->state->incoming_packet, valp); |
||
2476 |
} |
||
2477 |
|||
2478 |
int |
||
2479 |
sshpkt_get_string(struct ssh *ssh, u_char **valp, size_t *lenp) |
||
2480 |
{ |
||
2481 |
32 |
return sshbuf_get_string(ssh->state->incoming_packet, valp, lenp); |
|
2482 |
} |
||
2483 |
|||
2484 |
int |
||
2485 |
sshpkt_get_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp) |
||
2486 |
{ |
||
2487 |
18990 |
return sshbuf_get_string_direct(ssh->state->incoming_packet, valp, lenp); |
|
2488 |
} |
||
2489 |
|||
2490 |
int |
||
2491 |
sshpkt_peek_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp) |
||
2492 |
{ |
||
2493 |
return sshbuf_peek_string_direct(ssh->state->incoming_packet, valp, lenp); |
||
2494 |
} |
||
2495 |
|||
2496 |
int |
||
2497 |
sshpkt_get_cstring(struct ssh *ssh, char **valp, size_t *lenp) |
||
2498 |
{ |
||
2499 |
6 |
return sshbuf_get_cstring(ssh->state->incoming_packet, valp, lenp); |
|
2500 |
} |
||
2501 |
|||
2502 |
#ifdef WITH_OPENSSL |
||
2503 |
int |
||
2504 |
sshpkt_get_ec(struct ssh *ssh, EC_POINT *v, const EC_GROUP *g) |
||
2505 |
{ |
||
2506 |
return sshbuf_get_ec(ssh->state->incoming_packet, v, g); |
||
2507 |
} |
||
2508 |
|||
2509 |
|||
2510 |
int |
||
2511 |
sshpkt_get_bignum2(struct ssh *ssh, BIGNUM *v) |
||
2512 |
{ |
||
2513 |
return sshbuf_get_bignum2(ssh->state->incoming_packet, v); |
||
2514 |
} |
||
2515 |
#endif /* WITH_OPENSSL */ |
||
2516 |
|||
2517 |
int |
||
2518 |
sshpkt_get_end(struct ssh *ssh) |
||
2519 |
{ |
||
2520 |
✗✓ | 10 |
if (sshbuf_len(ssh->state->incoming_packet) > 0) |
2521 |
return SSH_ERR_UNEXPECTED_TRAILING_DATA; |
||
2522 |
5 |
return 0; |
|
2523 |
5 |
} |
|
2524 |
|||
2525 |
const u_char * |
||
2526 |
sshpkt_ptr(struct ssh *ssh, size_t *lenp) |
||
2527 |
{ |
||
2528 |
✓✗ | 2 |
if (lenp != NULL) |
2529 |
1 |
*lenp = sshbuf_len(ssh->state->incoming_packet); |
|
2530 |
1 |
return sshbuf_ptr(ssh->state->incoming_packet); |
|
2531 |
} |
||
2532 |
|||
2533 |
/* start a new packet */ |
||
2534 |
|||
2535 |
int |
||
2536 |
sshpkt_start(struct ssh *ssh, u_char type) |
||
2537 |
{ |
||
2538 |
85304 |
u_char buf[6]; /* u32 packet length, u8 pad len, u8 type */ |
|
2539 |
|||
2540 |
DBG(debug("packet_start[%d]", type)); |
||
2541 |
42652 |
memset(buf, 0, sizeof(buf)); |
|
2542 |
42652 |
buf[sizeof(buf) - 1] = type; |
|
2543 |
42652 |
sshbuf_reset(ssh->state->outgoing_packet); |
|
2544 |
85304 |
return sshbuf_put(ssh->state->outgoing_packet, buf, sizeof(buf)); |
|
2545 |
42652 |
} |
|
2546 |
|||
2547 |
static int |
||
2548 |
ssh_packet_send_mux(struct ssh *ssh) |
||
2549 |
{ |
||
2550 |
struct session_state *state = ssh->state; |
||
2551 |
u_char type, *cp; |
||
2552 |
size_t len; |
||
2553 |
int r; |
||
2554 |
|||
2555 |
if (ssh->kex) |
||
2556 |
return SSH_ERR_INTERNAL_ERROR; |
||
2557 |
len = sshbuf_len(state->outgoing_packet); |
||
2558 |
if (len < 6) |
||
2559 |
return SSH_ERR_INTERNAL_ERROR; |
||
2560 |
cp = sshbuf_mutable_ptr(state->outgoing_packet); |
||
2561 |
type = cp[5]; |
||
2562 |
if (ssh_packet_log_type(type)) |
||
2563 |
debug3("%s: type %u", __func__, type); |
||
2564 |
/* drop everything, but the connection protocol */ |
||
2565 |
if (type >= SSH2_MSG_CONNECTION_MIN && |
||
2566 |
type <= SSH2_MSG_CONNECTION_MAX) { |
||
2567 |
POKE_U32(cp, len - 4); |
||
2568 |
if ((r = sshbuf_putb(state->output, |
||
2569 |
state->outgoing_packet)) != 0) |
||
2570 |
return r; |
||
2571 |
/* sshbuf_dump(state->output, stderr); */ |
||
2572 |
} |
||
2573 |
sshbuf_reset(state->outgoing_packet); |
||
2574 |
return 0; |
||
2575 |
} |
||
2576 |
|||
2577 |
/* |
||
2578 |
* 9.2. Ignored Data Message |
||
2579 |
* |
||
2580 |
* byte SSH_MSG_IGNORE |
||
2581 |
* string data |
||
2582 |
* |
||
2583 |
* All implementations MUST understand (and ignore) this message at any |
||
2584 |
* time (after receiving the protocol version). No implementation is |
||
2585 |
* required to send them. This message can be used as an additional |
||
2586 |
* protection measure against advanced traffic analysis techniques. |
||
2587 |
*/ |
||
2588 |
int |
||
2589 |
sshpkt_msg_ignore(struct ssh *ssh, u_int nbytes) |
||
2590 |
{ |
||
2591 |
u_int32_t rnd = 0; |
||
2592 |
int r; |
||
2593 |
u_int i; |
||
2594 |
|||
2595 |
if ((r = sshpkt_start(ssh, SSH2_MSG_IGNORE)) != 0 || |
||
2596 |
(r = sshpkt_put_u32(ssh, nbytes)) != 0) |
||
2597 |
return r; |
||
2598 |
for (i = 0; i < nbytes; i++) { |
||
2599 |
if (i % 4 == 0) |
||
2600 |
rnd = arc4random(); |
||
2601 |
if ((r = sshpkt_put_u8(ssh, (u_char)rnd & 0xff)) != 0) |
||
2602 |
return r; |
||
2603 |
rnd >>= 8; |
||
2604 |
} |
||
2605 |
return 0; |
||
2606 |
} |
||
2607 |
|||
2608 |
/* send it */ |
||
2609 |
|||
2610 |
int |
||
2611 |
sshpkt_send(struct ssh *ssh) |
||
2612 |
{ |
||
2613 |
✓✗✗✓ |
127956 |
if (ssh->state && ssh->state->mux) |
2614 |
return ssh_packet_send_mux(ssh); |
||
2615 |
42652 |
return ssh_packet_send2(ssh); |
|
2616 |
42652 |
} |
|
2617 |
|||
2618 |
int |
||
2619 |
sshpkt_disconnect(struct ssh *ssh, const char *fmt,...) |
||
2620 |
{ |
||
2621 |
char buf[1024]; |
||
2622 |
va_list args; |
||
2623 |
int r; |
||
2624 |
|||
2625 |
va_start(args, fmt); |
||
2626 |
vsnprintf(buf, sizeof(buf), fmt, args); |
||
2627 |
va_end(args); |
||
2628 |
|||
2629 |
if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT)) != 0 || |
||
2630 |
(r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_PROTOCOL_ERROR)) != 0 || |
||
2631 |
(r = sshpkt_put_cstring(ssh, buf)) != 0 || |
||
2632 |
(r = sshpkt_put_cstring(ssh, "")) != 0 || |
||
2633 |
(r = sshpkt_send(ssh)) != 0) |
||
2634 |
return r; |
||
2635 |
return 0; |
||
2636 |
} |
||
2637 |
|||
2638 |
/* roundup current message to pad bytes */ |
||
2639 |
int |
||
2640 |
sshpkt_add_padding(struct ssh *ssh, u_char pad) |
||
2641 |
{ |
||
2642 |
2 |
ssh->state->extra_pad = pad; |
|
2643 |
1 |
return 0; |
|
2644 |
} |
Generated by: GCOVR (Version 3.3) |