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