1 /* Copyright (C) 2007 The Written Word, Inc. All rights reserved.
2 * Author: Daniel Stenberg <daniel@haxx.se>
4 * Redistribution and use in source and binary forms,
5 * with or without modification, are permitted provided
6 * that the following conditions are met:
8 * Redistributions of source code must retain the above
9 * copyright notice, this list of conditions and the
10 * following disclaimer.
12 * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials
15 * provided with the distribution.
17 * Neither the name of the copyright holder nor the names
18 * of any other contributors may be used to endorse or
19 * promote products derived from this software without
20 * specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
23 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
34 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
37 * This file handles reading and writing to the SECSH transport layer. RFC4253.
40 #include "libssh2_priv.h"
46 #define MAX_BLOCKSIZE 32 /* MUST fit biggest crypto block size we use/get */
47 #define MAX_MACSIZE 20 /* MUST fit biggest MAC length we support */
50 #define UNPRINTABLE_CHAR '.'
52 debugdump(LIBSSH2_SESSION
* session
,
53 const char *desc
, unsigned char *ptr
, unsigned long size
)
57 FILE *stream
= stdout
;
58 unsigned int width
= 0x10;
60 if (!(session
->showmask
& (1 << LIBSSH2_DBG_TRANS
))) {
61 /* not asked for, bail out */
65 fprintf(stream
, "=> %s (%d bytes)\n", desc
, (int) size
);
67 for(i
= 0; i
< size
; i
+= width
) {
69 fprintf(stream
, "%04lx: ", (long)i
);
71 /* hex not disabled, show it */
72 for(c
= 0; c
< width
; c
++) {
74 fprintf(stream
, "%02x ", ptr
[i
+ c
]);
79 for(c
= 0; (c
< width
) && (i
+ c
< size
); c
++) {
81 (ptr
[i
+ c
] >= 0x20) &&
82 (ptr
[i
+ c
] < 0x80) ? ptr
[i
+ c
] : UNPRINTABLE_CHAR
);
84 fputc('\n', stream
); /* newline */
89 #define debugdump(a,x,y,z)
93 /* decrypt() decrypts 'len' bytes from 'source' to 'dest'.
95 * returns PACKET_NONE on success and PACKET_FAIL on failure
99 decrypt(LIBSSH2_SESSION
* session
, unsigned char *source
,
100 unsigned char *dest
, int len
)
102 struct transportpacket
*p
= &session
->packet
;
103 int blocksize
= session
->remote
.crypt
->blocksize
;
105 /* if we get called with a len that isn't an even number of blocksizes
106 we risk losing those extra bytes */
107 assert((len
% blocksize
) == 0);
109 while (len
>= blocksize
) {
110 if (session
->remote
.crypt
->crypt(session
, source
,
111 &session
->remote
.crypt_abstract
)) {
112 libssh2_error(session
, LIBSSH2_ERROR_DECRYPT
,
113 (char *) "Error decrypting packet", 0);
114 LIBSSH2_FREE(session
, p
->payload
);
118 /* if the crypt() function would write to a given address it
119 wouldn't have to memcpy() and we could avoid this memcpy()
121 memcpy(dest
, source
, blocksize
);
123 len
-= blocksize
; /* less bytes left */
124 dest
+= blocksize
; /* advance write pointer */
125 source
+= blocksize
; /* advance read pointer */
127 return PACKET_NONE
; /* all is fine */
131 * fullpacket() gets called when a full packet has been received and properly
135 fullpacket(LIBSSH2_SESSION
* session
, int encrypted
/* 1 or 0 */ )
137 unsigned char macbuf
[MAX_MACSIZE
];
138 struct transportpacket
*p
= &session
->packet
;
141 if (session
->fullpacket_state
== libssh2_NB_state_idle
) {
142 session
->fullpacket_macstate
= LIBSSH2_MAC_CONFIRMED
;
143 session
->fullpacket_payload_len
= p
->packet_length
- 1;
147 /* Calculate MAC hash */
148 session
->remote
.mac
->hash(session
, macbuf
, /* store hash here */
149 session
->remote
.seqno
,
152 session
->fullpacket_payload_len
,
153 &session
->remote
.mac_abstract
);
155 /* Compare the calculated hash with the MAC we just read from
156 * the network. The read one is at the very end of the payload
157 * buffer. Note that 'payload_len' here is the packet_length
158 * field which includes the padding but not the MAC.
160 if (memcmp(macbuf
, p
->payload
+ session
->fullpacket_payload_len
,
161 session
->remote
.mac
->mac_len
)) {
162 session
->fullpacket_macstate
= LIBSSH2_MAC_INVALID
;
166 session
->remote
.seqno
++;
168 /* ignore the padding */
169 session
->fullpacket_payload_len
-= p
->padding_length
;
171 /* Check for and deal with decompression */
172 if (session
->remote
.comp
&& strcmp(session
->remote
.comp
->name
, "none")) {
174 unsigned long data_len
;
175 int free_payload
= 1;
177 if (session
->remote
.comp
->comp(session
, 0,
179 LIBSSH2_PACKET_MAXDECOMP
,
182 session
->fullpacket_payload_len
,
183 &session
->remote
.comp_abstract
)) {
184 LIBSSH2_FREE(session
, p
->payload
);
189 LIBSSH2_FREE(session
, p
->payload
);
191 session
->fullpacket_payload_len
= data_len
;
193 if (data
== p
->payload
) {
194 /* It's not to be freed, because the
195 * compression layer reused payload, So let's
198 session
->fullpacket_payload_len
= data_len
;
200 /* No comp_method actually lets this happen,
201 * but let's prepare for the future */
203 LIBSSH2_FREE(session
, p
->payload
);
205 /* We need a freeable struct otherwise the
206 * brigade won't know what to do with it */
207 p
->payload
= LIBSSH2_ALLOC(session
, data_len
);
209 libssh2_error(session
, LIBSSH2_ERROR_ALLOC
, (char *)
210 "Unable to allocate memory for copy of uncompressed data",
212 return PACKET_ENOMEM
;
214 memcpy(p
->payload
, data
, data_len
);
215 session
->fullpacket_payload_len
= data_len
;
220 session
->fullpacket_packet_type
= p
->payload
[0];
222 debugdump(session
, "libssh2_packet_read() plain",
223 p
->payload
, session
->fullpacket_payload_len
);
225 session
->fullpacket_state
= libssh2_NB_state_created
;
228 if (session
->fullpacket_state
== libssh2_NB_state_created
) {
229 rc
= libssh2_packet_add(session
, p
->payload
,
230 session
->fullpacket_payload_len
,
231 session
->fullpacket_macstate
);
232 if (rc
== PACKET_EAGAIN
) {
233 return PACKET_EAGAIN
;
239 session
->fullpacket_state
= libssh2_NB_state_idle
;
241 return session
->fullpacket_packet_type
;
245 /* {{{ libssh2_packet_read
246 * Collect a packet into the input brigade
247 * block only controls whether or not to wait for a packet to start,
248 * Once a packet starts, libssh2 will block until it is complete
250 * Returns packet type added to input brigade (PACKET_NONE if nothing added),
251 * or PACKET_FAIL on failure and PACKET_EAGAIN if it couldn't process a full
256 * This function reads the binary stream as specified in chapter 6 of RFC4253
257 * "The Secure Shell (SSH) Transport Layer Protocol"
260 libssh2_packet_read(LIBSSH2_SESSION
* session
)
263 struct transportpacket
*p
= &session
->packet
;
268 unsigned char block
[MAX_BLOCKSIZE
];
273 * =============================== NOTE ===============================
274 * I know this is very ugly and not a really good use of "goto", but
275 * this case statement would be even uglier to do it any other way
277 if (session
->readPack_state
== libssh2_NB_state_jump1
) {
278 session
->readPack_state
= libssh2_NB_state_idle
;
279 encrypted
= session
->readPack_encrypted
;
280 goto libssh2_packet_read_point1
;
284 if (session
->socket_state
== LIBSSH2_SOCKET_DISCONNECTED
) {
288 if (session
->state
& LIBSSH2_STATE_NEWKEYS
) {
289 blocksize
= session
->remote
.crypt
->blocksize
;
291 encrypted
= 0; /* not encrypted */
292 blocksize
= 5; /* not strictly true, but we can use 5 here to
293 make the checks below work fine still */
296 /* read/use a whole big chunk into a temporary area stored in
297 the LIBSSH2_SESSION struct. We will decrypt data from that
298 buffer into the packet buffer so this temp one doesn't have
299 to be able to keep a whole SSH packet, just be large enough
300 so that we can read big chunks from the network layer. */
302 /* how much data there is remaining in the buffer to deal with
303 before we should read more from the network */
304 remainbuf
= p
->writeidx
- p
->readidx
;
306 /* if remainbuf turns negative we have a bad internal error */
307 assert(remainbuf
>= 0);
309 if (remainbuf
< blocksize
) {
310 /* If we have less than a blocksize left, it is too
311 little data to deal with, read more */
314 /* move any remainder to the start of the buffer so
315 that we can do a full refill */
317 memmove(p
->buf
, &p
->buf
[p
->readidx
], remainbuf
);
319 p
->writeidx
= remainbuf
;
321 /* nothing to move, just zero the indexes */
322 p
->readidx
= p
->writeidx
= 0;
325 /* now read a big chunk from the network into the temp buffer */
327 recv(session
->socket_fd
, &p
->buf
[remainbuf
],
328 PACKETBUFSIZE
- remainbuf
,
329 LIBSSH2_SOCKET_RECV_FLAGS(session
));
331 /* check if this is due to EAGAIN and return the special
332 return code if so, error out normally otherwise */
334 switch (WSAGetLastError()) {
344 case WSAECONNABORTED
:
353 if ((nread
< 0) && (errno
== EAGAIN
)) {
354 return PACKET_EAGAIN
;
358 debugdump(session
, "libssh2_packet_read() raw",
359 &p
->buf
[remainbuf
], nread
);
360 /* advance write pointer */
361 p
->writeidx
+= nread
;
363 /* update remainbuf counter */
364 remainbuf
= p
->writeidx
- p
->readidx
;
367 /* how much data to deal with from the buffer */
368 numbytes
= remainbuf
;
371 /* No payload package area allocated yet. To know the
372 size of this payload, we need to decrypt the first
375 if (numbytes
< blocksize
) {
376 /* we can't act on anything less than blocksize, but this
377 check is only done for the initial block since once we have
378 got the start of a block we can in fact deal with fractions
380 return PACKET_EAGAIN
;
384 rc
= decrypt(session
, &p
->buf
[p
->readidx
], block
, blocksize
);
385 if (rc
!= PACKET_NONE
) {
388 /* save the first 5 bytes of the decrypted package, to be
389 used in the hash calculation later down. */
390 memcpy(p
->init
, &p
->buf
[p
->readidx
], 5);
392 /* the data is plain, just copy it verbatim to
393 the working block buffer */
394 memcpy(block
, &p
->buf
[p
->readidx
], blocksize
);
397 /* advance the read pointer */
398 p
->readidx
+= blocksize
;
400 /* we now have the initial blocksize bytes decrypted,
401 * and we can extract packet and padding length from it
403 p
->packet_length
= libssh2_ntohu32(block
);
404 p
->padding_length
= block
[4];
406 /* total_num is the number of bytes following the initial
407 (5 bytes) packet length and padding length fields */
409 p
->packet_length
- 1 +
410 (encrypted
? session
->remote
.mac
->mac_len
: 0);
412 /* RFC4253 section 6.1 Maximum Packet Length says:
414 * "All implementations MUST be able to process
415 * packets with uncompressed payload length of 32768
416 * bytes or less and total packet size of 35000 bytes
417 * or less (including length, padding length, payload,
418 * padding, and MAC.)."
420 if (p
->total_num
> LIBSSH2_PACKET_MAXPAYLOAD
) {
421 return PACKET_TOOBIG
;
424 /* Get a packet handle put data into. We get one to
425 hold all data, including padding and MAC. */
426 p
->payload
= LIBSSH2_ALLOC(session
, p
->total_num
);
428 return PACKET_ENOMEM
;
430 /* init write pointer to start of payload buffer */
431 p
->wptr
= p
->payload
;
434 /* copy the data from index 5 to the end of
435 the blocksize from the temporary buffer to
436 the start of the decrypted buffer */
437 memcpy(p
->wptr
, &block
[5], blocksize
- 5);
438 p
->wptr
+= blocksize
- 5; /* advance write pointer */
441 /* init the data_num field to the number of bytes of
442 the package read so far */
443 p
->data_num
= p
->wptr
- p
->payload
;
445 /* we already dealt with a blocksize worth of data */
446 numbytes
-= blocksize
;
449 /* how much there is left to add to the current payload
451 remainpack
= p
->total_num
- p
->data_num
;
453 if (numbytes
> remainpack
) {
454 /* if we have more data in the buffer than what is going into this
455 particular packet, we limit this round to this packet only */
456 numbytes
= remainpack
;
460 /* At the end of the incoming stream, there is a MAC,
461 and we don't want to decrypt that since we need it
462 "raw". We MUST however decrypt the padding data
463 since it is used for the hash later on. */
464 int skip
= session
->remote
.mac
->mac_len
;
466 /* if what we have plus numbytes is bigger than the
467 total minus the skip margin, we should lower the
468 amount to decrypt even more */
469 if ((p
->data_num
+ numbytes
) > (p
->total_num
- skip
)) {
470 numdecrypt
= (p
->total_num
- skip
) - p
->data_num
;
473 numdecrypt
= numbytes
;
474 frac
= numdecrypt
% blocksize
;
476 /* not an aligned amount of blocks,
479 /* and make it no unencrypted data
485 /* unencrypted data should not be decrypted at all */
489 /* if there are bytes to decrypt, do that */
490 if (numdecrypt
> 0) {
491 /* now decrypt the lot */
492 rc
= decrypt(session
, &p
->buf
[p
->readidx
], p
->wptr
, numdecrypt
);
493 if (rc
!= PACKET_NONE
) {
497 /* advance the read pointer */
498 p
->readidx
+= numdecrypt
;
499 /* advance write pointer */
500 p
->wptr
+= numdecrypt
;
501 /* increse data_num */
502 p
->data_num
+= numdecrypt
;
504 /* bytes left to take care of without decryption */
505 numbytes
-= numdecrypt
;
508 /* if there are bytes to copy that aren't decrypted, simply
509 copy them as-is to the target buffer */
511 memcpy(p
->wptr
, &p
->buf
[p
->readidx
], numbytes
);
513 /* advance the read pointer */
514 p
->readidx
+= numbytes
;
515 /* advance write pointer */
517 /* increse data_num */
518 p
->data_num
+= numbytes
;
521 /* now check how much data there's left to read to finish the
523 remainpack
= p
->total_num
- p
->data_num
;
526 /* we have a full packet */
527 libssh2_packet_read_point1
:
528 rc
= fullpacket(session
, encrypted
);
529 if (rc
== PACKET_EAGAIN
) {
530 session
->readPack_encrypted
= encrypted
;
531 session
->readPack_state
= libssh2_NB_state_jump1
;
532 return PACKET_EAGAIN
;
535 p
->total_num
= 0; /* no packet buffer available */
539 } while (1); /* loop */
541 return PACKET_FAIL
; /* we never reach this point */
549 send_existing(LIBSSH2_SESSION
* session
, unsigned char *data
,
550 unsigned long data_len
, ssize_t
* ret
)
554 struct transportpacket
*p
= &session
->packet
;
561 /* send as much as possible of the existing packet */
562 if ((data
!= p
->odata
) || (data_len
!= p
->olen
)) {
563 /* When we are about to complete the sending of a packet, it is vital
564 that the caller doesn't try to send a new/different packet since
565 we don't add this one up until the previous one has been sent. To
566 make the caller really notice his/hers flaw, we return error for
568 return PACKET_BADUSE
;
571 *ret
= 1; /* set to make our parent return */
573 /* number of bytes left to send */
574 length
= p
->ototal_num
- p
->osent
;
576 rc
= send(session
->socket_fd
, &p
->outbuf
[p
->osent
], length
,
577 LIBSSH2_SOCKET_SEND_FLAGS(session
));
580 /* the remainder of the package was sent */
581 LIBSSH2_FREE(session
, p
->outbuf
);
585 /* nothing was sent */
586 if (errno
!= EAGAIN
) {
590 return PACKET_EAGAIN
;
593 debugdump(session
, "libssh2_packet_write send()", &p
->outbuf
[p
->osent
],
595 p
->osent
+= length
; /* we sent away this much data */
600 /* {{{ libssh2_packet_write
601 * Send a packet, encrypting it and adding a MAC code if necessary
602 * Returns 0 on success, non-zero on failure.
604 * Returns PACKET_EAGAIN if it would block - and if it does so, you should
605 * call this function again as soon as it is likely that more data can be
606 * sent, and this function should then be called with the same argument set
607 * (same data pointer and same data_len) until zero or failure is returned.
610 libssh2_packet_write(LIBSSH2_SESSION
* session
, unsigned char *data
,
611 unsigned long data_len
)
614 (session
->state
& LIBSSH2_STATE_NEWKEYS
) ? session
->local
.crypt
->
620 #ifdef RANDOM_PADDING
622 int seed
= data
[0]; /* FIXME: make this random */
624 struct transportpacket
*p
= &session
->packet
;
629 unsigned char *orgdata
= data
;
630 unsigned long orgdata_len
= data_len
;
632 debugdump(session
, "libssh2_packet_write plain", data
, data_len
);
634 /* FIRST, check if we have a pending write to complete */
635 rc
= send_existing(session
, data
, data_len
, &ret
);
640 encrypted
= (session
->state
& LIBSSH2_STATE_NEWKEYS
) ? 1 : 0;
642 /* check if we should compress */
643 if (encrypted
&& strcmp(session
->local
.comp
->name
, "none")) {
644 if (session
->local
.comp
->
645 comp(session
, 1, &data
, &data_len
, LIBSSH2_PACKET_MAXCOMP
,
646 &free_data
, data
, data_len
, &session
->local
.comp_abstract
)) {
647 return PACKET_COMPRESS
; /* compression failure */
651 /* RFC4253 says: Note that the length of the concatenation of
652 'packet_length', 'padding_length', 'payload', and 'random padding'
653 MUST be a multiple of the cipher block size or 8, whichever is
656 /* Plain math: (4 + 1 + packet_length + padding_length) % blocksize == 0 */
658 packet_length
= data_len
+ 1 + 4; /* 1 is for padding_length field
659 4 for the packet_length field */
661 /* at this point we have it all except the padding */
663 /* first figure out our minimum padding amount to make it an even
665 padding_length
= blocksize
- (packet_length
% blocksize
);
667 /* if the padding becomes too small we add another blocksize worth
668 of it (taken from the original libssh2 where it didn't have any
670 if (padding_length
< 4) {
671 padding_length
+= blocksize
;
673 #ifdef RANDOM_PADDING
674 /* FIXME: we can add padding here, but that also makes the packets
677 /* now we can add 'blocksize' to the padding_length N number of times
678 (to "help thwart traffic analysis") but it must be less than 255 in
680 rand_max
= (255 - padding_length
) / blocksize
+ 1;
681 padding_length
+= blocksize
* (seed
% rand_max
);
684 packet_length
+= padding_length
;
686 /* append the MAC length to the total_length size */
688 packet_length
+ (encrypted
? session
->local
.mac
->mac_len
: 0);
690 /* allocate memory to store the outgoing packet in, in case we can't
691 send the whole one and thus need to keep it after this function
693 p
->outbuf
= LIBSSH2_ALLOC(session
, total_length
);
695 return PACKET_ENOMEM
;
698 /* store packet_length, which is the size of the whole packet except
699 the MAC and the packet_length field itself */
700 libssh2_htonu32(p
->outbuf
, packet_length
- 4);
701 /* store padding_length */
702 p
->outbuf
[4] = padding_length
;
703 /* copy the payload data */
704 memcpy(p
->outbuf
+ 5, data
, data_len
);
705 /* fill the padding area with random junk */
706 libssh2_random(p
->outbuf
+ 5 + data_len
, padding_length
);
708 LIBSSH2_FREE(session
, data
);
712 /* Calculate MAC hash. Put the output at index packet_length,
713 since that size includes the whole packet. The MAC is
714 calculated on the entire unencrypted packet, including all
715 fields except the MAC field itself. */
716 session
->local
.mac
->hash(session
, p
->outbuf
+ packet_length
,
717 session
->local
.seqno
, p
->outbuf
,
718 packet_length
, NULL
, 0,
719 &session
->local
.mac_abstract
);
721 /* Encrypt the whole packet data, one block size at a time.
722 The MAC field is not encrypted. */
723 for(i
= 0; i
< packet_length
; i
+= session
->local
.crypt
->blocksize
) {
724 unsigned char *ptr
= &p
->outbuf
[i
];
725 if (session
->local
.crypt
->
726 crypt(session
, ptr
, &session
->local
.crypt_abstract
))
727 return PACKET_FAIL
; /* encryption failure */
731 session
->local
.seqno
++;
733 ret
= send(session
->socket_fd
, p
->outbuf
, total_length
,
734 LIBSSH2_SOCKET_SEND_FLAGS(session
));
737 debugdump(session
, "libssh2_packet_write send()", p
->outbuf
, ret
);
739 if (ret
!= total_length
) {
740 if ((ret
> 0) || ((ret
== -1) && (errno
== EAGAIN
))) {
741 /* the whole packet could not be sent, save the rest */
743 p
->olen
= orgdata_len
;
744 p
->osent
= (ret
== -1) ? 0 : ret
;
745 p
->ototal_num
= total_length
;
746 return PACKET_EAGAIN
;
751 /* the whole thing got sent away */
754 LIBSSH2_FREE(session
, p
->outbuf
);
757 return PACKET_NONE
; /* all is good */