1
by Matt Johnston
Import upstream version 0.42 |
1 |
/*
|
2 |
* Dropbear - a SSH2 server
|
|
3 |
*
|
|
4 |
* Copyright (c) 2002,2003 Matt Johnston
|
|
5 |
* All rights reserved.
|
|
6 |
*
|
|
7 |
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8 |
* of this software and associated documentation files (the "Software"), to deal
|
|
9 |
* in the Software without restriction, including without limitation the rights
|
|
10 |
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11 |
* copies of the Software, and to permit persons to whom the Software is
|
|
12 |
* furnished to do so, subject to the following conditions:
|
|
13 |
*
|
|
14 |
* The above copyright notice and this permission notice shall be included in
|
|
15 |
* all copies or substantial portions of the Software.
|
|
16 |
*
|
|
17 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18 |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19 |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20 |
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21 |
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22 |
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
23 |
* SOFTWARE. */
|
|
24 |
||
25 |
#include "includes.h" |
|
26 |
#include "packet.h" |
|
27 |
#include "session.h" |
|
28 |
#include "dbutil.h" |
|
29 |
#include "ssh.h" |
|
30 |
#include "algo.h" |
|
31 |
#include "buffer.h" |
|
32 |
#include "kex.h" |
|
33 |
#include "random.h" |
|
34 |
#include "service.h" |
|
35 |
#include "auth.h" |
|
36 |
#include "channel.h" |
|
37 |
||
38 |
static void read_packet_init(); |
|
39 |
static void writemac(buffer * outputbuffer, buffer * clearwritebuf); |
|
40 |
static int checkmac(buffer* hashbuf, buffer* readbuf); |
|
41 |
||
42 |
#define ZLIB_COMPRESS_INCR 20 /* this is 12 bytes + 0.1% of 8000 bytes */ |
|
43 |
#define ZLIB_DECOMPRESS_INCR 100
|
|
44 |
#ifndef DISABLE_ZLIB
|
|
45 |
static buffer* buf_decompress(buffer* buf, unsigned int len); |
|
46 |
static void buf_compress(buffer * dest, buffer * src, unsigned int len); |
|
47 |
#endif
|
|
48 |
||
49 |
/* non-blocking function writing out a current encrypted packet */
|
|
50 |
void write_packet() { |
|
51 |
||
52 |
int len, written; |
|
1.1.1
by Gerrit Pape
Import upstream version 0.43 |
53 |
buffer * writebuf = NULL; |
1
by Matt Johnston
Import upstream version 0.42 |
54 |
|
1.2.1
by Gerrit Pape
Import upstream version 0.45 |
55 |
TRACE(("enter write_packet")) |
1.2.2
by Matt Johnston
Import upstream version 0.47 |
56 |
dropbear_assert(!isempty(&ses.writequeue)); |
1
by Matt Johnston
Import upstream version 0.42 |
57 |
|
58 |
/* Get the next buffer in the queue of encrypted packets to write*/
|
|
59 |
writebuf = (buffer*)examine(&ses.writequeue); |
|
60 |
||
61 |
len = writebuf->len - writebuf->pos; |
|
1.2.2
by Matt Johnston
Import upstream version 0.47 |
62 |
dropbear_assert(len > 0); |
1
by Matt Johnston
Import upstream version 0.42 |
63 |
/* Try to write as much as possible */
|
1.4.2
by Gerrit Pape
Import upstream version 0.52 |
64 |
written = write(ses.sock_out, buf_getptr(writebuf, len), len); |
1
by Matt Johnston
Import upstream version 0.42 |
65 |
|
66 |
if (written < 0) { |
|
67 |
if (errno == EINTR) { |
|
1.2.1
by Gerrit Pape
Import upstream version 0.45 |
68 |
TRACE(("leave writepacket: EINTR")) |
1
by Matt Johnston
Import upstream version 0.42 |
69 |
return; |
70 |
} else { |
|
71 |
dropbear_exit("error writing"); |
|
72 |
}
|
|
73 |
}
|
|
1.3.3
by Gerrit Pape
Import upstream version 0.50 |
74 |
|
1.4.2
by Gerrit Pape
Import upstream version 0.52 |
75 |
ses.last_trx_packet_time = time(NULL); |
1.3.3
by Gerrit Pape
Import upstream version 0.50 |
76 |
ses.last_packet_time = time(NULL); |
1
by Matt Johnston
Import upstream version 0.42 |
77 |
|
78 |
if (written == 0) { |
|
1.2.1
by Gerrit Pape
Import upstream version 0.45 |
79 |
ses.remoteclosed(); |
1
by Matt Johnston
Import upstream version 0.42 |
80 |
}
|
81 |
||
82 |
if (written == len) { |
|
83 |
/* We've finished with the packet, free it */
|
|
84 |
dequeue(&ses.writequeue); |
|
85 |
buf_free(writebuf); |
|
1.2.1
by Gerrit Pape
Import upstream version 0.45 |
86 |
writebuf = NULL; |
1
by Matt Johnston
Import upstream version 0.42 |
87 |
} else { |
88 |
/* More packet left to write, leave it in the queue for later */
|
|
89 |
buf_incrpos(writebuf, written); |
|
90 |
}
|
|
91 |
||
1.2.1
by Gerrit Pape
Import upstream version 0.45 |
92 |
TRACE(("leave write_packet")) |
1
by Matt Johnston
Import upstream version 0.42 |
93 |
}
|
94 |
||
95 |
/* Non-blocking function reading available portion of a packet into the
|
|
96 |
* ses's buffer, decrypting the length if encrypted, decrypting the
|
|
97 |
* full portion if possible */
|
|
98 |
void read_packet() { |
|
99 |
||
100 |
int len; |
|
101 |
unsigned int maxlen; |
|
102 |
unsigned char blocksize; |
|
103 |
||
1.2.1
by Gerrit Pape
Import upstream version 0.45 |
104 |
TRACE(("enter read_packet")) |
1
by Matt Johnston
Import upstream version 0.42 |
105 |
blocksize = ses.keys->recv_algo_crypt->blocksize; |
106 |
||
107 |
if (ses.readbuf == NULL || ses.readbuf->len < blocksize) { |
|
108 |
/* In the first blocksize of a packet */
|
|
109 |
||
110 |
/* Read the first blocksize of the packet, so we can decrypt it and
|
|
111 |
* find the length of the whole packet */
|
|
112 |
read_packet_init(); |
|
113 |
||
114 |
/* If we don't have the length of decryptreadbuf, we didn't read
|
|
115 |
* a whole blocksize and should exit */
|
|
116 |
if (ses.decryptreadbuf->len == 0) { |
|
1.2.1
by Gerrit Pape
Import upstream version 0.45 |
117 |
TRACE(("leave read_packet: packetinit done")) |
1
by Matt Johnston
Import upstream version 0.42 |
118 |
return; |
119 |
}
|
|
120 |
}
|
|
121 |
||
122 |
/* Attempt to read the remainder of the packet, note that there
|
|
123 |
* mightn't be any available (EAGAIN) */
|
|
1.2.2
by Matt Johnston
Import upstream version 0.47 |
124 |
dropbear_assert(ses.readbuf != NULL); |
1
by Matt Johnston
Import upstream version 0.42 |
125 |
maxlen = ses.readbuf->len - ses.readbuf->pos; |
1.4.2
by Gerrit Pape
Import upstream version 0.52 |
126 |
len = read(ses.sock_in, buf_getptr(ses.readbuf, maxlen), maxlen); |
1
by Matt Johnston
Import upstream version 0.42 |
127 |
|
128 |
if (len == 0) { |
|
1.2.1
by Gerrit Pape
Import upstream version 0.45 |
129 |
ses.remoteclosed(); |
1
by Matt Johnston
Import upstream version 0.42 |
130 |
}
|
131 |
||
132 |
if (len < 0) { |
|
133 |
if (errno == EINTR || errno == EAGAIN) { |
|
1.2.1
by Gerrit Pape
Import upstream version 0.45 |
134 |
TRACE(("leave read_packet: EINTR or EAGAIN")) |
1
by Matt Johnston
Import upstream version 0.42 |
135 |
return; |
136 |
} else { |
|
137 |
dropbear_exit("error reading: %s", strerror(errno)); |
|
138 |
}
|
|
139 |
}
|
|
140 |
||
141 |
buf_incrpos(ses.readbuf, len); |
|
142 |
||
143 |
if ((unsigned int)len == maxlen) { |
|
144 |
/* The whole packet has been read */
|
|
145 |
decrypt_packet(); |
|
1.2.1
by Gerrit Pape
Import upstream version 0.45 |
146 |
/* The main select() loop process_packet() to
|
1
by Matt Johnston
Import upstream version 0.42 |
147 |
* handle the packet contents... */
|
148 |
}
|
|
1.2.1
by Gerrit Pape
Import upstream version 0.45 |
149 |
TRACE(("leave read_packet")) |
1
by Matt Johnston
Import upstream version 0.42 |
150 |
}
|
151 |
||
152 |
/* Function used to read the initial portion of a packet, and determine the
|
|
153 |
* length. Only called during the first BLOCKSIZE of a packet. */
|
|
154 |
static void read_packet_init() { |
|
155 |
||
156 |
unsigned int maxlen; |
|
157 |
int len; |
|
158 |
unsigned char blocksize; |
|
159 |
unsigned char macsize; |
|
160 |
||
161 |
||
162 |
blocksize = ses.keys->recv_algo_crypt->blocksize; |
|
163 |
macsize = ses.keys->recv_algo_mac->hashsize; |
|
164 |
||
165 |
if (ses.readbuf == NULL) { |
|
166 |
/* start of a new packet */
|
|
167 |
ses.readbuf = buf_new(INIT_READBUF); |
|
1.2.2
by Matt Johnston
Import upstream version 0.47 |
168 |
dropbear_assert(ses.decryptreadbuf == NULL); |
1
by Matt Johnston
Import upstream version 0.42 |
169 |
ses.decryptreadbuf = buf_new(blocksize); |
170 |
}
|
|
171 |
||
172 |
maxlen = blocksize - ses.readbuf->pos; |
|
173 |
||
174 |
/* read the rest of the packet if possible */
|
|
1.4.2
by Gerrit Pape
Import upstream version 0.52 |
175 |
len = read(ses.sock_in, buf_getwriteptr(ses.readbuf, maxlen), |
1
by Matt Johnston
Import upstream version 0.42 |
176 |
maxlen); |
177 |
if (len == 0) { |
|
1.2.1
by Gerrit Pape
Import upstream version 0.45 |
178 |
ses.remoteclosed(); |
1
by Matt Johnston
Import upstream version 0.42 |
179 |
}
|
180 |
if (len < 0) { |
|
181 |
if (errno == EINTR) { |
|
1.2.1
by Gerrit Pape
Import upstream version 0.45 |
182 |
TRACE(("leave read_packet_init: EINTR")) |
1
by Matt Johnston
Import upstream version 0.42 |
183 |
return; |
184 |
}
|
|
185 |
dropbear_exit("error reading: %s", strerror(errno)); |
|
186 |
}
|
|
187 |
||
188 |
buf_incrwritepos(ses.readbuf, len); |
|
189 |
||
190 |
if ((unsigned int)len != maxlen) { |
|
191 |
/* don't have enough bytes to determine length, get next time */
|
|
192 |
return; |
|
193 |
}
|
|
194 |
||
195 |
/* now we have the first block, need to get packet length, so we decrypt
|
|
196 |
* the first block (only need first 4 bytes) */
|
|
197 |
buf_setpos(ses.readbuf, 0); |
|
1.4.2
by Gerrit Pape
Import upstream version 0.52 |
198 |
if (ses.keys->recv_crypt_mode->decrypt(buf_getptr(ses.readbuf, blocksize), |
199 |
buf_getwriteptr(ses.decryptreadbuf,blocksize), |
|
200 |
blocksize, |
|
201 |
&ses.keys->recv_cipher_state) != CRYPT_OK) { |
|
202 |
dropbear_exit("error decrypting"); |
|
1
by Matt Johnston
Import upstream version 0.42 |
203 |
}
|
204 |
buf_setlen(ses.decryptreadbuf, blocksize); |
|
205 |
len = buf_getint(ses.decryptreadbuf) + 4 + macsize; |
|
206 |
||
207 |
buf_setpos(ses.readbuf, blocksize); |
|
208 |
||
209 |
/* check packet length */
|
|
1.3.3
by Gerrit Pape
Import upstream version 0.50 |
210 |
if ((len > RECV_MAX_PACKET_LEN) || |
1
by Matt Johnston
Import upstream version 0.42 |
211 |
(len < MIN_PACKET_LEN + macsize) || |
212 |
((len - macsize) % blocksize != 0)) { |
|
1.2.2
by Matt Johnston
Import upstream version 0.47 |
213 |
dropbear_exit("bad packet size %d", len); |
1
by Matt Johnston
Import upstream version 0.42 |
214 |
}
|
215 |
||
216 |
buf_resize(ses.readbuf, len); |
|
217 |
buf_setlen(ses.readbuf, len); |
|
218 |
||
219 |
}
|
|
220 |
||
221 |
/* handle the received packet */
|
|
222 |
void decrypt_packet() { |
|
223 |
||
224 |
unsigned char blocksize; |
|
225 |
unsigned char macsize; |
|
226 |
unsigned int padlen; |
|
227 |
unsigned int len; |
|
228 |
||
1.2.1
by Gerrit Pape
Import upstream version 0.45 |
229 |
TRACE(("enter decrypt_packet")) |
1
by Matt Johnston
Import upstream version 0.42 |
230 |
blocksize = ses.keys->recv_algo_crypt->blocksize; |
231 |
macsize = ses.keys->recv_algo_mac->hashsize; |
|
232 |
||
233 |
ses.kexstate.datarecv += ses.readbuf->len; |
|
234 |
||
235 |
/* we've already decrypted the first blocksize in read_packet_init */
|
|
236 |
buf_setpos(ses.readbuf, blocksize); |
|
237 |
||
238 |
buf_resize(ses.decryptreadbuf, ses.readbuf->len - macsize); |
|
239 |
buf_setlen(ses.decryptreadbuf, ses.decryptreadbuf->size); |
|
240 |
buf_setpos(ses.decryptreadbuf, blocksize); |
|
241 |
||
1.4.2
by Gerrit Pape
Import upstream version 0.52 |
242 |
/* decrypt it */
|
243 |
while (ses.readbuf->pos < ses.readbuf->len - macsize) { |
|
244 |
if (ses.keys->recv_crypt_mode->decrypt( |
|
245 |
buf_getptr(ses.readbuf, blocksize), |
|
246 |
buf_getwriteptr(ses.decryptreadbuf, blocksize), |
|
247 |
blocksize, |
|
248 |
&ses.keys->recv_cipher_state) != CRYPT_OK) { |
|
249 |
dropbear_exit("error decrypting"); |
|
1
by Matt Johnston
Import upstream version 0.42 |
250 |
}
|
1.4.2
by Gerrit Pape
Import upstream version 0.52 |
251 |
buf_incrpos(ses.readbuf, blocksize); |
252 |
buf_incrwritepos(ses.decryptreadbuf, blocksize); |
|
1
by Matt Johnston
Import upstream version 0.42 |
253 |
}
|
254 |
||
255 |
/* check the hmac */
|
|
256 |
buf_setpos(ses.readbuf, ses.readbuf->len - macsize); |
|
257 |
if (checkmac(ses.readbuf, ses.decryptreadbuf) != DROPBEAR_SUCCESS) { |
|
258 |
dropbear_exit("Integrity error"); |
|
259 |
}
|
|
260 |
||
261 |
/* readbuf no longer required */
|
|
262 |
buf_free(ses.readbuf); |
|
263 |
ses.readbuf = NULL; |
|
264 |
||
265 |
/* get padding length */
|
|
266 |
buf_setpos(ses.decryptreadbuf, PACKET_PADDING_OFF); |
|
267 |
padlen = buf_getbyte(ses.decryptreadbuf); |
|
268 |
||
269 |
/* payload length */
|
|
270 |
/* - 4 - 1 is for LEN and PADLEN values */
|
|
271 |
len = ses.decryptreadbuf->len - padlen - 4 - 1; |
|
1.3.3
by Gerrit Pape
Import upstream version 0.50 |
272 |
if ((len > RECV_MAX_PAYLOAD_LEN) || (len < 1)) { |
1
by Matt Johnston
Import upstream version 0.42 |
273 |
dropbear_exit("bad packet size"); |
274 |
}
|
|
275 |
||
276 |
buf_setpos(ses.decryptreadbuf, PACKET_PAYLOAD_OFF); |
|
277 |
||
278 |
#ifndef DISABLE_ZLIB
|
|
1.4.2
by Gerrit Pape
Import upstream version 0.52 |
279 |
if (is_compress_recv()) { |
1
by Matt Johnston
Import upstream version 0.42 |
280 |
/* decompress */
|
281 |
ses.payload = buf_decompress(ses.decryptreadbuf, len); |
|
282 |
} else |
|
283 |
#endif
|
|
284 |
{
|
|
285 |
/* copy payload */
|
|
286 |
ses.payload = buf_new(len); |
|
287 |
memcpy(ses.payload->data, buf_getptr(ses.decryptreadbuf, len), len); |
|
288 |
buf_incrlen(ses.payload, len); |
|
289 |
}
|
|
290 |
||
291 |
buf_free(ses.decryptreadbuf); |
|
292 |
ses.decryptreadbuf = NULL; |
|
293 |
buf_setpos(ses.payload, 0); |
|
294 |
||
295 |
ses.recvseq++; |
|
296 |
||
1.2.1
by Gerrit Pape
Import upstream version 0.45 |
297 |
TRACE(("leave decrypt_packet")) |
1
by Matt Johnston
Import upstream version 0.42 |
298 |
}
|
299 |
||
300 |
/* Checks the mac in hashbuf, for the data in readbuf.
|
|
301 |
* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
|
|
302 |
static int checkmac(buffer* macbuf, buffer* sourcebuf) { |
|
303 |
||
1.2.2
by Matt Johnston
Import upstream version 0.47 |
304 |
unsigned int macsize; |
1
by Matt Johnston
Import upstream version 0.42 |
305 |
hmac_state hmac; |
306 |
unsigned char tempbuf[MAX_MAC_LEN]; |
|
1.2.2
by Matt Johnston
Import upstream version 0.47 |
307 |
unsigned long bufsize; |
308 |
unsigned int len; |
|
1
by Matt Johnston
Import upstream version 0.42 |
309 |
|
310 |
macsize = ses.keys->recv_algo_mac->hashsize; |
|
311 |
if (macsize == 0) { |
|
312 |
return DROPBEAR_SUCCESS; |
|
313 |
}
|
|
314 |
||
315 |
/* calculate the mac */
|
|
316 |
if (hmac_init(&hmac, |
|
317 |
find_hash(ses.keys->recv_algo_mac->hashdesc->name), |
|
318 |
ses.keys->recvmackey, |
|
319 |
ses.keys->recv_algo_mac->keysize) |
|
320 |
!= CRYPT_OK) { |
|
321 |
dropbear_exit("HMAC error"); |
|
322 |
}
|
|
323 |
||
324 |
/* sequence number */
|
|
325 |
STORE32H(ses.recvseq, tempbuf); |
|
326 |
if (hmac_process(&hmac, tempbuf, 4) != CRYPT_OK) { |
|
327 |
dropbear_exit("HMAC error"); |
|
328 |
}
|
|
329 |
||
330 |
buf_setpos(sourcebuf, 0); |
|
331 |
len = sourcebuf->len; |
|
332 |
if (hmac_process(&hmac, buf_getptr(sourcebuf, len), len) != CRYPT_OK) { |
|
333 |
dropbear_exit("HMAC error"); |
|
334 |
}
|
|
335 |
||
1.2.2
by Matt Johnston
Import upstream version 0.47 |
336 |
bufsize = sizeof(tempbuf); |
337 |
if (hmac_done(&hmac, tempbuf, &bufsize) != CRYPT_OK) { |
|
1
by Matt Johnston
Import upstream version 0.42 |
338 |
dropbear_exit("HMAC error"); |
339 |
}
|
|
340 |
||
341 |
/* compare the hash */
|
|
342 |
if (memcmp(tempbuf, buf_getptr(macbuf, macsize), macsize) != 0) { |
|
343 |
return DROPBEAR_FAILURE; |
|
344 |
} else { |
|
345 |
return DROPBEAR_SUCCESS; |
|
346 |
}
|
|
347 |
}
|
|
348 |
||
349 |
#ifndef DISABLE_ZLIB
|
|
350 |
/* returns a pointer to a newly created buffer */
|
|
351 |
static buffer* buf_decompress(buffer* buf, unsigned int len) { |
|
352 |
||
353 |
int result; |
|
354 |
buffer * ret; |
|
355 |
z_streamp zstream; |
|
356 |
||
357 |
zstream = ses.keys->recv_zstream; |
|
358 |
ret = buf_new(len); |
|
359 |
||
360 |
zstream->avail_in = len; |
|
361 |
zstream->next_in = buf_getptr(buf, len); |
|
362 |
||
363 |
/* decompress the payload, incrementally resizing the output buffer */
|
|
364 |
while (1) { |
|
365 |
||
366 |
zstream->avail_out = ret->size - ret->pos; |
|
367 |
zstream->next_out = buf_getwriteptr(ret, zstream->avail_out); |
|
368 |
||
369 |
result = inflate(zstream, Z_SYNC_FLUSH); |
|
370 |
||
371 |
buf_setlen(ret, ret->size - zstream->avail_out); |
|
372 |
buf_setpos(ret, ret->len); |
|
373 |
||
374 |
if (result != Z_BUF_ERROR && result != Z_OK) { |
|
375 |
dropbear_exit("zlib error"); |
|
376 |
}
|
|
377 |
||
378 |
if (zstream->avail_in == 0 && |
|
379 |
(zstream->avail_out != 0 || result == Z_BUF_ERROR)) { |
|
380 |
/* we can only exit if avail_out hasn't all been used,
|
|
381 |
* and there's no remaining input */
|
|
382 |
return ret; |
|
383 |
}
|
|
384 |
||
385 |
if (zstream->avail_out == 0) { |
|
386 |
buf_resize(ret, ret->size + ZLIB_DECOMPRESS_INCR); |
|
387 |
}
|
|
388 |
}
|
|
389 |
}
|
|
390 |
#endif
|
|
391 |
||
392 |
||
1.3.3
by Gerrit Pape
Import upstream version 0.50 |
393 |
/* returns 1 if the packet is a valid type during kex (see 7.1 of rfc4253) */
|
394 |
static int packet_is_okay_kex(unsigned char type) { |
|
395 |
if (type >= SSH_MSG_USERAUTH_REQUEST) { |
|
396 |
return 0; |
|
397 |
}
|
|
398 |
if (type == SSH_MSG_SERVICE_REQUEST || type == SSH_MSG_SERVICE_ACCEPT) { |
|
399 |
return 0; |
|
400 |
}
|
|
401 |
if (type == SSH_MSG_KEXINIT) { |
|
402 |
/* XXX should this die horribly if !dataallowed ?? */
|
|
403 |
return 0; |
|
404 |
}
|
|
405 |
return 1; |
|
406 |
}
|
|
407 |
||
408 |
static void enqueue_reply_packet() { |
|
409 |
struct packetlist * new_item = NULL; |
|
410 |
new_item = m_malloc(sizeof(struct packetlist)); |
|
411 |
new_item->next = NULL; |
|
412 |
||
413 |
new_item->payload = buf_newcopy(ses.writepayload); |
|
414 |
buf_setpos(ses.writepayload, 0); |
|
415 |
buf_setlen(ses.writepayload, 0); |
|
416 |
||
417 |
if (ses.reply_queue_tail) { |
|
418 |
ses.reply_queue_tail->next = new_item; |
|
419 |
} else { |
|
420 |
ses.reply_queue_head = new_item; |
|
421 |
}
|
|
422 |
ses.reply_queue_tail = new_item; |
|
423 |
TRACE(("leave enqueue_reply_packet")) |
|
424 |
}
|
|
425 |
||
426 |
void maybe_flush_reply_queue() { |
|
427 |
struct packetlist *tmp_item = NULL, *curr_item = NULL; |
|
428 |
if (!ses.dataallowed) |
|
429 |
{
|
|
430 |
TRACE(("maybe_empty_reply_queue - no data allowed")) |
|
431 |
return; |
|
432 |
}
|
|
433 |
||
434 |
for (curr_item = ses.reply_queue_head; curr_item; ) { |
|
435 |
CHECKCLEARTOWRITE(); |
|
436 |
buf_putbytes(ses.writepayload, |
|
437 |
curr_item->payload->data, curr_item->payload->len); |
|
438 |
||
439 |
buf_free(curr_item->payload); |
|
440 |
tmp_item = curr_item; |
|
441 |
curr_item = curr_item->next; |
|
442 |
m_free(tmp_item); |
|
443 |
encrypt_packet(); |
|
444 |
}
|
|
445 |
ses.reply_queue_head = ses.reply_queue_tail = NULL; |
|
446 |
}
|
|
1.2.1
by Gerrit Pape
Import upstream version 0.45 |
447 |
|
1
by Matt Johnston
Import upstream version 0.42 |
448 |
/* encrypt the writepayload, putting into writebuf, ready for write_packet()
|
449 |
* to put on the wire */
|
|
450 |
void encrypt_packet() { |
|
451 |
||
452 |
unsigned char padlen; |
|
453 |
unsigned char blocksize, macsize; |
|
454 |
buffer * writebuf; /* the packet which will go on the wire */ |
|
455 |
buffer * clearwritebuf; /* unencrypted, possibly compressed */ |
|
1.3.3
by Gerrit Pape
Import upstream version 0.50 |
456 |
unsigned char type; |
1.4.2
by Gerrit Pape
Import upstream version 0.52 |
457 |
unsigned int clear_len; |
1
by Matt Johnston
Import upstream version 0.42 |
458 |
|
1.3.3
by Gerrit Pape
Import upstream version 0.50 |
459 |
type = ses.writepayload->data[0]; |
1.2.1
by Gerrit Pape
Import upstream version 0.45 |
460 |
TRACE(("enter encrypt_packet()")) |
1.3.3
by Gerrit Pape
Import upstream version 0.50 |
461 |
TRACE(("encrypt_packet type is %d", type)) |
462 |
||
463 |
if (!ses.dataallowed && !packet_is_okay_kex(type)) { |
|
464 |
/* During key exchange only particular packets are allowed.
|
|
465 |
Since this type isn't OK we just enqueue it to send
|
|
466 |
after the KEX, see maybe_flush_reply_queue */
|
|
467 |
enqueue_reply_packet(); |
|
468 |
return; |
|
469 |
}
|
|
470 |
||
1
by Matt Johnston
Import upstream version 0.42 |
471 |
blocksize = ses.keys->trans_algo_crypt->blocksize; |
472 |
macsize = ses.keys->trans_algo_mac->hashsize; |
|
473 |
||
474 |
/* Encrypted packet len is payload+5, then worst case is if we are 3 away
|
|
475 |
* from a blocksize multiple. In which case we need to pad to the
|
|
476 |
* multiple, then add another blocksize (or MIN_PACKET_LEN) */
|
|
1.4.2
by Gerrit Pape
Import upstream version 0.52 |
477 |
clear_len = (ses.writepayload->len+4+1) + MIN_PACKET_LEN + 3; |
478 |
||
1
by Matt Johnston
Import upstream version 0.42 |
479 |
#ifndef DISABLE_ZLIB
|
1.4.2
by Gerrit Pape
Import upstream version 0.52 |
480 |
clear_len += ZLIB_COMPRESS_INCR; /* bit of a kludge, but we can't know len*/ |
1
by Matt Johnston
Import upstream version 0.42 |
481 |
#endif
|
1.4.2
by Gerrit Pape
Import upstream version 0.52 |
482 |
clearwritebuf = buf_new(clear_len); |
1
by Matt Johnston
Import upstream version 0.42 |
483 |
buf_setlen(clearwritebuf, PACKET_PAYLOAD_OFF); |
484 |
buf_setpos(clearwritebuf, PACKET_PAYLOAD_OFF); |
|
485 |
||
486 |
buf_setpos(ses.writepayload, 0); |
|
487 |
||
488 |
#ifndef DISABLE_ZLIB
|
|
489 |
/* compression */
|
|
1.4.2
by Gerrit Pape
Import upstream version 0.52 |
490 |
if (is_compress_trans()) { |
1
by Matt Johnston
Import upstream version 0.42 |
491 |
buf_compress(clearwritebuf, ses.writepayload, ses.writepayload->len); |
492 |
} else |
|
493 |
#endif
|
|
494 |
{
|
|
495 |
memcpy(buf_getwriteptr(clearwritebuf, ses.writepayload->len), |
|
496 |
buf_getptr(ses.writepayload, ses.writepayload->len), |
|
497 |
ses.writepayload->len); |
|
498 |
buf_incrwritepos(clearwritebuf, ses.writepayload->len); |
|
499 |
}
|
|
500 |
||
501 |
/* finished with payload */
|
|
502 |
buf_setpos(ses.writepayload, 0); |
|
503 |
buf_setlen(ses.writepayload, 0); |
|
504 |
||
505 |
/* length of padding - packet length must be a multiple of blocksize,
|
|
506 |
* with a minimum of 4 bytes of padding */
|
|
507 |
padlen = blocksize - (clearwritebuf->len) % blocksize; |
|
508 |
if (padlen < 4) { |
|
509 |
padlen += blocksize; |
|
510 |
}
|
|
511 |
/* check for min packet length */
|
|
512 |
if (clearwritebuf->len + padlen < MIN_PACKET_LEN) { |
|
513 |
padlen += blocksize; |
|
514 |
}
|
|
515 |
||
516 |
buf_setpos(clearwritebuf, 0); |
|
517 |
/* packet length excluding the packetlength uint32 */
|
|
518 |
buf_putint(clearwritebuf, clearwritebuf->len + padlen - 4); |
|
519 |
||
520 |
/* padding len */
|
|
521 |
buf_putbyte(clearwritebuf, padlen); |
|
522 |
/* actual padding */
|
|
523 |
buf_setpos(clearwritebuf, clearwritebuf->len); |
|
524 |
buf_incrlen(clearwritebuf, padlen); |
|
525 |
genrandom(buf_getptr(clearwritebuf, padlen), padlen); |
|
526 |
||
527 |
/* do the actual encryption */
|
|
528 |
buf_setpos(clearwritebuf, 0); |
|
529 |
/* create a new writebuffer, this is freed when it has been put on the
|
|
530 |
* wire by writepacket() */
|
|
531 |
writebuf = buf_new(clearwritebuf->len + macsize); |
|
532 |
||
1.4.2
by Gerrit Pape
Import upstream version 0.52 |
533 |
/* encrypt it */
|
534 |
while (clearwritebuf->pos < clearwritebuf->len) { |
|
535 |
if (ses.keys->trans_crypt_mode->encrypt( |
|
536 |
buf_getptr(clearwritebuf, blocksize), |
|
537 |
buf_getwriteptr(writebuf, blocksize), |
|
538 |
blocksize, |
|
539 |
&ses.keys->trans_cipher_state) != CRYPT_OK) { |
|
540 |
dropbear_exit("error encrypting"); |
|
1
by Matt Johnston
Import upstream version 0.42 |
541 |
}
|
1.4.2
by Gerrit Pape
Import upstream version 0.52 |
542 |
buf_incrpos(clearwritebuf, blocksize); |
543 |
buf_incrwritepos(writebuf, blocksize); |
|
1
by Matt Johnston
Import upstream version 0.42 |
544 |
}
|
545 |
||
546 |
/* now add a hmac and we're done */
|
|
547 |
writemac(writebuf, clearwritebuf); |
|
548 |
||
549 |
/* clearwritebuf is finished with */
|
|
550 |
buf_free(clearwritebuf); |
|
1.2.1
by Gerrit Pape
Import upstream version 0.45 |
551 |
clearwritebuf = NULL; |
1
by Matt Johnston
Import upstream version 0.42 |
552 |
|
553 |
/* enqueue the packet for sending */
|
|
554 |
buf_setpos(writebuf, 0); |
|
555 |
enqueue(&ses.writequeue, (void*)writebuf); |
|
556 |
||
557 |
/* Update counts */
|
|
558 |
ses.kexstate.datatrans += writebuf->len; |
|
559 |
ses.transseq++; |
|
560 |
||
1.2.1
by Gerrit Pape
Import upstream version 0.45 |
561 |
TRACE(("leave encrypt_packet()")) |
1
by Matt Johnston
Import upstream version 0.42 |
562 |
}
|
563 |
||
564 |
||
565 |
/* Create the packet mac, and append H(seqno|clearbuf) to the output */
|
|
566 |
static void writemac(buffer * outputbuffer, buffer * clearwritebuf) { |
|
567 |
||
1.2.2
by Matt Johnston
Import upstream version 0.47 |
568 |
unsigned int macsize; |
1
by Matt Johnston
Import upstream version 0.42 |
569 |
unsigned char seqbuf[4]; |
1.2.2
by Matt Johnston
Import upstream version 0.47 |
570 |
unsigned char tempbuf[MAX_MAC_LEN]; |
571 |
unsigned long bufsize; |
|
1
by Matt Johnston
Import upstream version 0.42 |
572 |
hmac_state hmac; |
573 |
||
1.2.1
by Gerrit Pape
Import upstream version 0.45 |
574 |
TRACE(("enter writemac")) |
1
by Matt Johnston
Import upstream version 0.42 |
575 |
|
576 |
macsize = ses.keys->trans_algo_mac->hashsize; |
|
577 |
if (macsize > 0) { |
|
578 |
/* calculate the mac */
|
|
579 |
if (hmac_init(&hmac, |
|
580 |
find_hash(ses.keys->trans_algo_mac->hashdesc->name), |
|
581 |
ses.keys->transmackey, |
|
582 |
ses.keys->trans_algo_mac->keysize) != CRYPT_OK) { |
|
583 |
dropbear_exit("HMAC error"); |
|
584 |
}
|
|
585 |
||
586 |
/* sequence number */
|
|
587 |
STORE32H(ses.transseq, seqbuf); |
|
588 |
if (hmac_process(&hmac, seqbuf, 4) != CRYPT_OK) { |
|
589 |
dropbear_exit("HMAC error"); |
|
590 |
}
|
|
591 |
||
592 |
/* the actual contents */
|
|
593 |
buf_setpos(clearwritebuf, 0); |
|
594 |
if (hmac_process(&hmac, |
|
595 |
buf_getptr(clearwritebuf, |
|
596 |
clearwritebuf->len), |
|
597 |
clearwritebuf->len) != CRYPT_OK) { |
|
598 |
dropbear_exit("HMAC error"); |
|
599 |
}
|
|
600 |
||
1.2.2
by Matt Johnston
Import upstream version 0.47 |
601 |
bufsize = sizeof(tempbuf); |
602 |
if (hmac_done(&hmac, tempbuf, &bufsize) |
|
1
by Matt Johnston
Import upstream version 0.42 |
603 |
!= CRYPT_OK) { |
604 |
dropbear_exit("HMAC error"); |
|
605 |
}
|
|
1.2.2
by Matt Johnston
Import upstream version 0.47 |
606 |
buf_putbytes(outputbuffer, tempbuf, macsize); |
1
by Matt Johnston
Import upstream version 0.42 |
607 |
}
|
1.2.1
by Gerrit Pape
Import upstream version 0.45 |
608 |
TRACE(("leave writemac")) |
1
by Matt Johnston
Import upstream version 0.42 |
609 |
}
|
610 |
||
611 |
#ifndef DISABLE_ZLIB
|
|
612 |
/* compresses len bytes from src, outputting to dest (starting from the
|
|
613 |
* respective current positions. */
|
|
614 |
static void buf_compress(buffer * dest, buffer * src, unsigned int len) { |
|
615 |
||
616 |
unsigned int endpos = src->pos + len; |
|
617 |
int result; |
|
618 |
||
1.2.1
by Gerrit Pape
Import upstream version 0.45 |
619 |
TRACE(("enter buf_compress")) |
1
by Matt Johnston
Import upstream version 0.42 |
620 |
|
621 |
while (1) { |
|
622 |
||
623 |
ses.keys->trans_zstream->avail_in = endpos - src->pos; |
|
624 |
ses.keys->trans_zstream->next_in = |
|
625 |
buf_getptr(src, ses.keys->trans_zstream->avail_in); |
|
626 |
||
627 |
ses.keys->trans_zstream->avail_out = dest->size - dest->pos; |
|
628 |
ses.keys->trans_zstream->next_out = |
|
629 |
buf_getwriteptr(dest, ses.keys->trans_zstream->avail_out); |
|
630 |
||
631 |
result = deflate(ses.keys->trans_zstream, Z_SYNC_FLUSH); |
|
632 |
||
633 |
buf_setpos(src, endpos - ses.keys->trans_zstream->avail_in); |
|
634 |
buf_setlen(dest, dest->size - ses.keys->trans_zstream->avail_out); |
|
635 |
buf_setpos(dest, dest->len); |
|
636 |
||
637 |
if (result != Z_OK) { |
|
638 |
dropbear_exit("zlib error"); |
|
639 |
}
|
|
640 |
||
641 |
if (ses.keys->trans_zstream->avail_in == 0) { |
|
642 |
break; |
|
643 |
}
|
|
644 |
||
1.2.2
by Matt Johnston
Import upstream version 0.47 |
645 |
dropbear_assert(ses.keys->trans_zstream->avail_out == 0); |
1
by Matt Johnston
Import upstream version 0.42 |
646 |
|
647 |
/* the buffer has been filled, we must extend. This only happens in
|
|
648 |
* unusual circumstances where the data grows in size after deflate(),
|
|
649 |
* but it is possible */
|
|
650 |
buf_resize(dest, dest->size + ZLIB_COMPRESS_INCR); |
|
651 |
||
652 |
}
|
|
1.2.1
by Gerrit Pape
Import upstream version 0.45 |
653 |
TRACE(("leave buf_compress")) |
1
by Matt Johnston
Import upstream version 0.42 |
654 |
}
|
655 |
#endif
|