libssh2
1/* Copyright (C) The Written Word, Inc.
2* Copyright (C) Daniel Stenberg
3* All rights reserved.
4*
5* Redistribution and use in source and binary forms,
6* with or without modification, are permitted provided
7* that the following conditions are met:
8*
9* Redistributions of source code must retain the above
10* copyright notice, this list of conditions and the
11* following disclaimer.
12*
13* Redistributions in binary form must reproduce the above
14* copyright notice, this list of conditions and the following
15* disclaimer in the documentation and/or other materials
16* provided with the distribution.
17*
18* Neither the name of the copyright holder nor the names
19* of any other contributors may be used to endorse or
20* promote products derived from this software without
21* specific prior written permission.
22*
23* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
24* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
25* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
28* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
33* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
35* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
36* OF SUCH DAMAGE.
37*
38* SPDX-License-Identifier: BSD-3-Clause
39*/
40
41/*
42* This file handles reading and writing to the SECSH transport layer. RFC4253.
43*/
44
45#include "libssh2_priv.h"46
47#include <errno.h>48#include <ctype.h>49#include <assert.h>50
51#include "transport.h"52#include "mac.h"53
54#ifdef LIBSSH2DEBUG55#define UNPRINTABLE_CHAR '.'56static void57debugdump(LIBSSH2_SESSION * session,58const char *desc, const unsigned char *ptr, size_t size)59{
60size_t i;61size_t c;62unsigned int width = 0x10;63char buffer[256]; /* Must be enough for width*4 + about 30 or so */64size_t used;65static const char *hex_chars = "0123456789ABCDEF";66
67if(!(session->showmask & LIBSSH2_TRACE_TRANS)) {68/* not asked for, bail out */69return;70}71
72used = snprintf(buffer, sizeof(buffer), "=> %s (%lu bytes)\n",73desc, (unsigned long) size);74if(session->tracehandler)75(session->tracehandler)(session, session->tracehandler_context,76buffer, used);77else78fprintf(stderr, "%s", buffer);79
80for(i = 0; i < size; i += width) {81
82used = snprintf(buffer, sizeof(buffer), "%04lx: ", (long)i);83
84/* hex not disabled, show it */85for(c = 0; c < width; c++) {86if(i + c < size) {87buffer[used++] = hex_chars[(ptr[i + c] >> 4) & 0xF];88buffer[used++] = hex_chars[ptr[i + c] & 0xF];89}90else {91buffer[used++] = ' ';92buffer[used++] = ' ';93}94
95buffer[used++] = ' ';96if((width/2) - 1 == c)97buffer[used++] = ' ';98}99
100buffer[used++] = ':';101buffer[used++] = ' ';102
103for(c = 0; (c < width) && (i + c < size); c++) {104buffer[used++] = isprint(ptr[i + c]) ?105ptr[i + c] : UNPRINTABLE_CHAR;106}107buffer[used++] = '\n';108buffer[used] = 0;109
110if(session->tracehandler)111(session->tracehandler)(session, session->tracehandler_context,112buffer, used);113else114fprintf(stderr, "%s", buffer);115}116}
117#else118#define debugdump(a,x,y,z) do {} while(0)119#endif120
121
122/* decrypt() decrypts 'len' bytes from 'source' to 'dest' in units of
123* blocksize.
124*
125* returns 0 on success and negative on failure
126*/
127
128static int129decrypt(LIBSSH2_SESSION * session, unsigned char *source,130unsigned char *dest, ssize_t len, int firstlast)131{
132struct transportpacket *p = &session->packet;133int blocksize = session->remote.crypt->blocksize;134
135/* if we get called with a len that isn't an even number of blocksizes136we risk losing those extra bytes. AAD is an exception, since those first
137few bytes aren't encrypted so it throws off the rest of the count. */
138if(!CRYPT_FLAG_L(session, PKTLEN_AAD))139assert((len % blocksize) == 0);140
141while(len > 0) {142/* normally decrypt up to blocksize bytes at a time */143ssize_t decryptlen = LIBSSH2_MIN(blocksize, len);144/* The first block is special (since it needs to be decoded to get the145length of the remainder of the block) and takes priority. When the
146length finally gets to the last blocksize bytes, and there's no
147more data to come, it's the end. */
148int lowerfirstlast = IS_FIRST(firstlast) ? FIRST_BLOCK :149((len <= blocksize) ? firstlast : MIDDLE_BLOCK);150/* If the last block would be less than a whole blocksize, combine it151with the previous block to make it larger. This ensures that the
152whole MAC is included in a single decrypt call. */
153if(CRYPT_FLAG_L(session, PKTLEN_AAD) && IS_LAST(firstlast)154&& (len < blocksize*2)) {155decryptlen = len;156lowerfirstlast = LAST_BLOCK;157}158
159if(session->remote.crypt->crypt(session, source, decryptlen,160&session->remote.crypt_abstract,161lowerfirstlast)) {162LIBSSH2_FREE(session, p->payload);163return LIBSSH2_ERROR_DECRYPT;164}165
166/* if the crypt() function would write to a given address it167wouldn't have to memcpy() and we could avoid this memcpy()
168too */
169memcpy(dest, source, decryptlen);170
171len -= decryptlen; /* less bytes left */172dest += decryptlen; /* advance write pointer */173source += decryptlen; /* advance read pointer */174}175return LIBSSH2_ERROR_NONE; /* all is fine */176}
177
178/*
179* fullpacket() gets called when a full packet has been received and properly
180* collected.
181*/
182static int183fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )184{
185unsigned char macbuf[MAX_MACSIZE];186struct transportpacket *p = &session->packet;187int rc;188int compressed;189uint32_t seq = session->remote.seqno;190
191if(session->fullpacket_state == libssh2_NB_state_idle) {192session->fullpacket_macstate = LIBSSH2_MAC_CONFIRMED;193session->fullpacket_payload_len = p->packet_length - 1;194
195if(encrypted && !CRYPT_FLAG_L(session, INTEGRATED_MAC)) {196
197/* Calculate MAC hash */198int etm = session->remote.mac->etm;199size_t mac_len = session->remote.mac->mac_len;200if(etm) {201/* store hash here */202session->remote.mac->hash(session, macbuf,203session->remote.seqno,204p->payload, p->total_num - mac_len,205NULL, 0,206&session->remote.mac_abstract);207}208else {209/* store hash here */210session->remote.mac->hash(session, macbuf,211session->remote.seqno,212p->init, 5,213p->payload,214session->fullpacket_payload_len,215&session->remote.mac_abstract);216}217
218/* Compare the calculated hash with the MAC we just read from219* the network. The read one is at the very end of the payload
220* buffer. Note that 'payload_len' here is the packet_length
221* field which includes the padding but not the MAC.
222*/
223if(memcmp(macbuf, p->payload + p->total_num - mac_len, mac_len)) {224_libssh2_debug((session, LIBSSH2_TRACE_SOCKET,225"Failed MAC check"));226session->fullpacket_macstate = LIBSSH2_MAC_INVALID;227
228}229else if(etm) {230/* MAC was ok and we start by decrypting the first block that231contains padding length since this allows us to decrypt
232all other blocks to the right location in memory
233avoiding moving a larger block of memory one byte. */
234unsigned char first_block[MAX_BLOCKSIZE];235ssize_t decrypt_size;236unsigned char *decrypt_buffer;237int blocksize = session->remote.crypt->blocksize;238
239rc = decrypt(session, p->payload + 4,240first_block, blocksize, FIRST_BLOCK);241if(rc) {242return rc;243}244
245/* we need buffer for decrypt */246decrypt_size = p->total_num - mac_len - 4;247decrypt_buffer = LIBSSH2_ALLOC(session, decrypt_size);248if(!decrypt_buffer) {249return LIBSSH2_ERROR_ALLOC;250}251
252/* grab padding length and copy anything else253into target buffer */
254p->padding_length = first_block[0];255if(blocksize > 1) {256memcpy(decrypt_buffer, first_block + 1, blocksize - 1);257}258
259/* decrypt all other blocks packet */260if(blocksize < decrypt_size) {261rc = decrypt(session, p->payload + blocksize + 4,262decrypt_buffer + blocksize - 1,263decrypt_size - blocksize, LAST_BLOCK);264if(rc) {265LIBSSH2_FREE(session, decrypt_buffer);266return rc;267}268}269
270/* replace encrypted payload with plain text payload */271LIBSSH2_FREE(session, p->payload);272p->payload = decrypt_buffer;273}274}275
276session->remote.seqno++;277
278/* ignore the padding */279session->fullpacket_payload_len -= p->padding_length;280
281/* Check for and deal with decompression */282compressed = session->local.comp &&283session->local.comp->compress &&284((session->state & LIBSSH2_STATE_AUTHENTICATED) ||285session->local.comp->use_in_auth);286
287if(compressed && session->remote.comp_abstract) {288/*289* The buffer for the decompression (remote.comp_abstract) is
290* initialised in time when it is needed so as long it is NULL we
291* cannot decompress.
292*/
293
294unsigned char *data;295size_t data_len;296rc = session->remote.comp->decomp(session,297&data, &data_len,298LIBSSH2_PACKET_MAXDECOMP,299p->payload,300session->fullpacket_payload_len,301&session->remote.comp_abstract);302LIBSSH2_FREE(session, p->payload);303if(rc)304return rc;305
306p->payload = data;307session->fullpacket_payload_len = data_len;308}309
310session->fullpacket_packet_type = p->payload[0];311
312debugdump(session, "libssh2_transport_read() plain",313p->payload, session->fullpacket_payload_len);314
315session->fullpacket_state = libssh2_NB_state_created;316}317
318if(session->fullpacket_state == libssh2_NB_state_created) {319rc = _libssh2_packet_add(session, p->payload,320session->fullpacket_payload_len,321session->fullpacket_macstate, seq);322if(rc == LIBSSH2_ERROR_EAGAIN)323return rc;324if(rc) {325session->fullpacket_state = libssh2_NB_state_idle;326return rc;327}328}329
330session->fullpacket_state = libssh2_NB_state_idle;331
332if(session->kex_strict &&333session->fullpacket_packet_type == SSH_MSG_NEWKEYS) {334session->remote.seqno = 0;335}336
337return session->fullpacket_packet_type;338}
339
340
341/*
342* _libssh2_transport_read
343*
344* Collect a packet into the input queue.
345*
346* Returns packet type added to input queue (0 if nothing added), or a
347* negative error number.
348*/
349
350/*
351* This function reads the binary stream as specified in chapter 6 of RFC4253
352* "The Secure Shell (SSH) Transport Layer Protocol"
353*
354* DOES NOT call _libssh2_error() for ANY error case.
355*/
356int _libssh2_transport_read(LIBSSH2_SESSION * session)357{
358int rc;359struct transportpacket *p = &session->packet;360ssize_t remainpack; /* how much there is left to add to the current payload361package */
362ssize_t remainbuf; /* how much data there is remaining in the buffer to363deal with before we should read more from the
364network */
365ssize_t numbytes; /* how much data to deal with from the buffer on this366iteration through the loop */
367ssize_t numdecrypt; /* number of bytes to decrypt this iteration */368unsigned char block[MAX_BLOCKSIZE]; /* working block buffer */369int blocksize; /* minimum number of bytes we need before we can370use them */
371int encrypted = 1; /* whether the packet is encrypted or not */372int firstlast = FIRST_BLOCK; /* if the first or last block to decrypt */373
374/* default clear the bit */375session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_INBOUND;376
377/*378* All channels, systems, subsystems, etc eventually make it down here
379* when looking for more incoming data. If a key exchange is going on
380* (LIBSSH2_STATE_EXCHANGING_KEYS bit is set) then the remote end will
381* ONLY send key exchange related traffic. In non-blocking mode, there is
382* a chance to break out of the kex_exchange function with an EAGAIN
383* status, and never come back to it. If LIBSSH2_STATE_EXCHANGING_KEYS is
384* active, then we must redirect to the key exchange. However, if
385* kex_exchange is active (as in it is the one that calls this execution
386* of packet_read, then don't redirect, as that would be an infinite loop!
387*/
388
389if(session->state & LIBSSH2_STATE_EXCHANGING_KEYS &&390!(session->state & LIBSSH2_STATE_KEX_ACTIVE)) {391
392/* Whoever wants a packet won't get anything until the key re-exchange393* is done!
394*/
395_libssh2_debug((session, LIBSSH2_TRACE_TRANS, "Redirecting into the"396" key re-exchange from _libssh2_transport_read"));397rc = _libssh2_kex_exchange(session, 1, &session->startup_key_state);398if(rc)399return rc;400}401
402/*403* =============================== NOTE ===============================
404* I know this is very ugly and not a really good use of "goto", but
405* this case statement would be even uglier to do it any other way
406*/
407if(session->readPack_state == libssh2_NB_state_jump1) {408session->readPack_state = libssh2_NB_state_idle;409encrypted = session->readPack_encrypted;410goto libssh2_transport_read_point1;411}412
413do {414int etm;415if(session->socket_state == LIBSSH2_SOCKET_DISCONNECTED) {416return LIBSSH2_ERROR_SOCKET_DISCONNECT;417}418
419if(session->state & LIBSSH2_STATE_NEWKEYS) {420blocksize = session->remote.crypt->blocksize;421}422else {423encrypted = 0; /* not encrypted */424blocksize = 5; /* not strictly true, but we can use 5 here to425make the checks below work fine still */
426}427
428etm = encrypted && session->remote.mac ? session->remote.mac->etm : 0;429
430/* read/use a whole big chunk into a temporary area stored in431the LIBSSH2_SESSION struct. We will decrypt data from that
432buffer into the packet buffer so this temp one doesn't have
433to be able to keep a whole SSH packet, just be large enough
434so that we can read big chunks from the network layer. */
435
436/* how much data there is remaining in the buffer to deal with437before we should read more from the network */
438remainbuf = p->writeidx - p->readidx;439
440/* if remainbuf turns negative we have a bad internal error */441assert(remainbuf >= 0);442
443if(remainbuf < blocksize) {444/* If we have less than a blocksize left, it is too445little data to deal with, read more */
446ssize_t nread;447
448/* move any remainder to the start of the buffer so449that we can do a full refill */
450if(remainbuf) {451memmove(p->buf, &p->buf[p->readidx], remainbuf);452p->readidx = 0;453p->writeidx = remainbuf;454}455else {456/* nothing to move, just zero the indexes */457p->readidx = p->writeidx = 0;458}459
460/* now read a big chunk from the network into the temp buffer */461nread = LIBSSH2_RECV(session, &p->buf[remainbuf],462PACKETBUFSIZE - remainbuf,463LIBSSH2_SOCKET_RECV_FLAGS(session));464if(nread <= 0) {465/* check if this is due to EAGAIN and return the special466return code if so, error out normally otherwise */
467if((nread < 0) && (nread == -EAGAIN)) {468session->socket_block_directions |=469LIBSSH2_SESSION_BLOCK_INBOUND;470return LIBSSH2_ERROR_EAGAIN;471}472_libssh2_debug((session, LIBSSH2_TRACE_SOCKET,473"Error recving %ld bytes (got %ld)",474(long)(PACKETBUFSIZE - remainbuf),475(long)-nread));476return LIBSSH2_ERROR_SOCKET_RECV;477}478_libssh2_debug((session, LIBSSH2_TRACE_SOCKET,479"Recved %ld/%ld bytes to %p+%ld", (long)nread,480(long)(PACKETBUFSIZE - remainbuf), (void *)p->buf,481(long)remainbuf));482
483debugdump(session, "libssh2_transport_read() raw",484&p->buf[remainbuf], nread);485/* advance write pointer */486p->writeidx += nread;487
488/* update remainbuf counter */489remainbuf = p->writeidx - p->readidx;490}491
492/* how much data to deal with from the buffer */493numbytes = remainbuf;494
495if(!p->total_num) {496size_t total_num; /* the number of bytes following the initial497(5 bytes) packet length and padding length
498fields */
499
500/* packet length is not encrypted in encode-then-mac mode501and we donøt need to decrypt first block */
502ssize_t required_size = etm ? 4 : blocksize;503
504/* No payload package area allocated yet. To know the505size of this payload, we need enough to decrypt the first
506blocksize data. */
507
508if(numbytes < required_size) {509/* we can't act on anything less than blocksize, but this510check is only done for the initial block since once we have
511got the start of a block we can in fact deal with fractions
512*/
513session->socket_block_directions |=514LIBSSH2_SESSION_BLOCK_INBOUND;515return LIBSSH2_ERROR_EAGAIN;516}517
518if(etm) {519p->packet_length = _libssh2_ntohu32(&p->buf[p->readidx]);520}521else {522if(encrypted) {523/* first decrypted block */524rc = decrypt(session, &p->buf[p->readidx],525block, blocksize, FIRST_BLOCK);526if(rc != LIBSSH2_ERROR_NONE) {527return rc;528}529/* Save the first 5 bytes of the decrypted package, to be530used in the hash calculation later down.
531This is ignored in the INTEGRATED_MAC case. */
532memcpy(p->init, block, 5);533}534else {535/* the data is plain, just copy it verbatim to536the working block buffer */
537memcpy(block, &p->buf[p->readidx], blocksize);538}539
540/* advance the read pointer */541p->readidx += blocksize;542
543/* we now have the initial blocksize bytes decrypted,544* and we can extract packet and padding length from it
545*/
546p->packet_length = _libssh2_ntohu32(block);547}548
549if(p->packet_length < 1) {550return LIBSSH2_ERROR_DECRYPT;551}552else if(p->packet_length > LIBSSH2_PACKET_MAXPAYLOAD) {553return LIBSSH2_ERROR_OUT_OF_BOUNDARY;554}555
556if(etm) {557/* we collect entire undecrypted packet including the558packet length field that we run MAC over */
559total_num = 4 + p->packet_length +560session->remote.mac->mac_len;561}562else {563/* padding_length has not been authenticated yet, but it won't564actually be used (except for the sanity check immediately
565following) until after the entire packet is authenticated,
566so this is safe. */
567p->padding_length = block[4];568if(p->padding_length > p->packet_length - 1) {569return LIBSSH2_ERROR_DECRYPT;570}571
572/* total_num is the number of bytes following the initial573(5 bytes) packet length and padding length fields */
574total_num = p->packet_length - 1 +575(encrypted ? session->remote.mac->mac_len : 0);576}577
578/* RFC4253 section 6.1 Maximum Packet Length says:579*
580* "All implementations MUST be able to process
581* packets with uncompressed payload length of 32768
582* bytes or less and total packet size of 35000 bytes
583* or less (including length, padding length, payload,
584* padding, and MAC.)."
585*/
586if(total_num > LIBSSH2_PACKET_MAXPAYLOAD || total_num == 0) {587return LIBSSH2_ERROR_OUT_OF_BOUNDARY;588}589
590/* Get a packet handle put data into. We get one to591hold all data, including padding and MAC. */
592p->payload = LIBSSH2_ALLOC(session, total_num);593if(!p->payload) {594return LIBSSH2_ERROR_ALLOC;595}596p->total_num = total_num;597/* init write pointer to start of payload buffer */598p->wptr = p->payload;599
600if(!etm && blocksize > 5) {601/* copy the data from index 5 to the end of602the blocksize from the temporary buffer to
603the start of the decrypted buffer */
604if(blocksize - 5 <= (int) total_num) {605memcpy(p->wptr, &block[5], blocksize - 5);606p->wptr += blocksize - 5; /* advance write pointer */607if(etm) {608/* advance past unencrypted packet length */609p->wptr += 4;610}611}612else {613if(p->payload)614LIBSSH2_FREE(session, p->payload);615return LIBSSH2_ERROR_OUT_OF_BOUNDARY;616}617}618
619/* init the data_num field to the number of bytes of620the package read so far */
621p->data_num = p->wptr - p->payload;622
623/* we already dealt with a blocksize worth of data */624if(!etm)625numbytes -= blocksize;626}627
628/* how much there is left to add to the current payload629package */
630remainpack = p->total_num - p->data_num;631
632if(numbytes > remainpack) {633/* if we have more data in the buffer than what is going into this634particular packet, we limit this round to this packet only */
635numbytes = remainpack;636}637
638if(encrypted && !etm) {639/* At the end of the incoming stream, there is a MAC,640and we don't want to decrypt that since we need it
641"raw". We MUST however decrypt the padding data
642since it is used for the hash later on. */
643int skip = session->remote.mac->mac_len;644
645if(CRYPT_FLAG_R(session, INTEGRATED_MAC))646/* This crypto method DOES need the MAC to go through647decryption so it can be authenticated. */
648skip = 0;649
650/* if what we have plus numbytes is bigger than the651total minus the skip margin, we should lower the
652amount to decrypt even more */
653if((p->data_num + numbytes) >= (p->total_num - skip)) {654/* decrypt the entire rest of the package */655numdecrypt = LIBSSH2_MAX(0,656(int)(p->total_num - skip) - (int)p->data_num);657firstlast = LAST_BLOCK;658}659else {660ssize_t frac;661numdecrypt = numbytes;662frac = numdecrypt % blocksize;663if(frac) {664/* not an aligned amount of blocks, align it by reducing665the number of bytes processed this loop */
666numdecrypt -= frac;667/* and make it no unencrypted data668after it */
669numbytes = 0;670}671if(CRYPT_FLAG_R(session, INTEGRATED_MAC)) {672/* Make sure that we save enough bytes to make the last673* block large enough to hold the entire integrated MAC */
674numdecrypt = LIBSSH2_MIN(numdecrypt,675(int)(p->total_num - skip - blocksize - p->data_num));676numbytes = 0;677}678firstlast = MIDDLE_BLOCK;679}680}681else {682/* unencrypted data should not be decrypted at all */683numdecrypt = 0;684}685assert(numdecrypt >= 0);686
687/* if there are bytes to decrypt, do that */688if(numdecrypt > 0) {689/* now decrypt the lot */690rc = decrypt(session, &p->buf[p->readidx], p->wptr, numdecrypt,691firstlast);692if(rc != LIBSSH2_ERROR_NONE) {693p->total_num = 0; /* no packet buffer available */694return rc;695}696
697/* advance the read pointer */698p->readidx += numdecrypt;699/* advance write pointer */700p->wptr += numdecrypt;701/* increase data_num */702p->data_num += numdecrypt;703
704/* bytes left to take care of without decryption */705numbytes -= numdecrypt;706}707
708/* if there are bytes to copy that aren't decrypted,709copy them as-is to the target buffer */
710if(numbytes > 0) {711
712if((size_t)numbytes <= (p->total_num - (p->wptr - p->payload))) {713memcpy(p->wptr, &p->buf[p->readidx], numbytes);714}715else {716if(p->payload)717LIBSSH2_FREE(session, p->payload);718return LIBSSH2_ERROR_OUT_OF_BOUNDARY;719}720
721/* advance the read pointer */722p->readidx += numbytes;723/* advance write pointer */724p->wptr += numbytes;725/* increase data_num */726p->data_num += numbytes;727}728
729/* now check how much data there's left to read to finish the730current packet */
731remainpack = p->total_num - p->data_num;732
733if(!remainpack) {734/* we have a full packet */735libssh2_transport_read_point1:736rc = fullpacket(session, encrypted);737if(rc == LIBSSH2_ERROR_EAGAIN) {738
739if(session->packAdd_state != libssh2_NB_state_idle) {740/* fullpacket only returns LIBSSH2_ERROR_EAGAIN if741* libssh2_packet_add() returns LIBSSH2_ERROR_EAGAIN. If
742* that returns LIBSSH2_ERROR_EAGAIN but the packAdd_state
743* is idle, then the packet has been added to the brigade,
744* but some immediate action that was taken based on the
745* packet type (such as key re-exchange) is not yet
746* complete. Clear the way for a new packet to be read
747* in.
748*/
749session->readPack_encrypted = encrypted;750session->readPack_state = libssh2_NB_state_jump1;751}752
753return rc;754}755
756p->total_num = 0; /* no packet buffer available */757
758return rc;759}760} while(1); /* loop */761
762return LIBSSH2_ERROR_SOCKET_RECV; /* we never reach this point */763}
764
765static int766send_existing(LIBSSH2_SESSION *session, const unsigned char *data,767size_t data_len, ssize_t *ret)768{
769ssize_t rc;770ssize_t length;771struct transportpacket *p = &session->packet;772
773if(!p->olen) {774*ret = 0;775return LIBSSH2_ERROR_NONE;776}777
778/* send as much as possible of the existing packet */779if((data != p->odata) || (data_len != p->olen)) {780/* When we are about to complete the sending of a packet, it is vital781that the caller doesn't try to send a new/different packet since
782we don't add this one up until the previous one has been sent. To
783make the caller really notice his/hers flaw, we return error for
784this case */
785_libssh2_debug((session, LIBSSH2_TRACE_SOCKET,786"Address is different, but will resume nonetheless"));787}788
789*ret = 1; /* set to make our parent return */790
791/* number of bytes left to send */792length = p->ototal_num - p->osent;793
794rc = LIBSSH2_SEND(session, &p->outbuf[p->osent], length,795LIBSSH2_SOCKET_SEND_FLAGS(session));796if(rc < 0)797_libssh2_debug((session, LIBSSH2_TRACE_SOCKET,798"Error sending %ld bytes: %ld",799(long)length, (long)-rc));800else {801_libssh2_debug((session, LIBSSH2_TRACE_SOCKET,802"Sent %ld/%ld bytes at %p+%lu", (long)rc, (long)length,803(void *)p->outbuf, (unsigned long)p->osent));804debugdump(session, "libssh2_transport_write send()",805&p->outbuf[p->osent], rc);806}807
808if(rc == length) {809/* the remainder of the package was sent */810p->ototal_num = 0;811p->olen = 0;812/* we leave *ret set so that the parent returns as we MUST return back813a send success now, so that we don't risk sending EAGAIN later
814which then would confuse the parent function */
815return LIBSSH2_ERROR_NONE;816
817}818else if(rc < 0) {819/* nothing was sent */820if(rc != -EAGAIN)821/* send failure! */822return LIBSSH2_ERROR_SOCKET_SEND;823
824session->socket_block_directions |= LIBSSH2_SESSION_BLOCK_OUTBOUND;825return LIBSSH2_ERROR_EAGAIN;826}827
828p->osent += rc; /* we sent away this much data */829
830return rc < length ? LIBSSH2_ERROR_EAGAIN : LIBSSH2_ERROR_NONE;831}
832
833/*
834* libssh2_transport_send
835*
836* Send a packet, encrypting it and adding a MAC code if necessary
837* Returns 0 on success, non-zero on failure.
838*
839* The data is provided as _two_ data areas that are combined by this
840* function. The 'data' part is sent immediately before 'data2'. 'data2' may
841* be set to NULL to only use a single part.
842*
843* Returns LIBSSH2_ERROR_EAGAIN if it would block or if the whole packet was
844* not sent yet. If it does so, the caller should call this function again as
845* soon as it is likely that more data can be sent, and this function MUST
846* then be called with the same argument set (same data pointer and same
847* data_len) until ERROR_NONE or failure is returned.
848*
849* This function DOES NOT call _libssh2_error() on any errors.
850*/
851int _libssh2_transport_send(LIBSSH2_SESSION *session,852const unsigned char *data, size_t data_len,853const unsigned char *data2, size_t data2_len)854{
855int blocksize =856(session->state & LIBSSH2_STATE_NEWKEYS) ?857session->local.crypt->blocksize : 8;858ssize_t padding_length;859size_t packet_length;860ssize_t total_length;861#ifdef LIBSSH2_RANDOM_PADDING862int rand_max;863int seed = data[0]; /* FIXME: make this random */864#endif865struct transportpacket *p = &session->packet;866int encrypted;867int compressed;868int etm;869ssize_t ret;870int rc;871const unsigned char *orgdata = data;872size_t orgdata_len = data_len;873size_t crypt_offset, etm_crypt_offset;874
875/*876* If the last read operation was interrupted in the middle of a key
877* exchange, we must complete that key exchange before continuing to write
878* further data.
879*
880* See the similar block in _libssh2_transport_read for more details.
881*/
882if(session->state & LIBSSH2_STATE_EXCHANGING_KEYS &&883!(session->state & LIBSSH2_STATE_KEX_ACTIVE)) {884/* Don't write any new packets if we're still in the middle of a key885* exchange. */
886_libssh2_debug((session, LIBSSH2_TRACE_TRANS, "Redirecting into the"887" key re-exchange from _libssh2_transport_send"));888rc = _libssh2_kex_exchange(session, 1, &session->startup_key_state);889if(rc)890return rc;891}892
893debugdump(session, "libssh2_transport_write plain", data, data_len);894if(data2)895debugdump(session, "libssh2_transport_write plain2", data2, data2_len);896
897/* FIRST, check if we have a pending write to complete. send_existing898only sanity-check data and data_len and not data2 and data2_len! */
899rc = send_existing(session, data, data_len, &ret);900if(rc)901return rc;902
903session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_OUTBOUND;904
905if(ret)906/* set by send_existing if data was sent */907return rc;908
909encrypted = (session->state & LIBSSH2_STATE_NEWKEYS) ? 1 : 0;910
911etm = encrypted && session->local.mac ? session->local.mac->etm : 0;912
913compressed = session->local.comp &&914session->local.comp->compress &&915((session->state & LIBSSH2_STATE_AUTHENTICATED) ||916session->local.comp->use_in_auth);917
918if(encrypted && compressed && session->local.comp_abstract) {919/* the idea here is that these function must fail if the output gets920larger than what fits in the assigned buffer so thus they don't
921check the input size as we don't know how much it compresses */
922size_t dest_len = MAX_SSH_PACKET_LEN-5-256;923size_t dest2_len = dest_len;924
925/* compress directly to the target buffer */926rc = session->local.comp->comp(session,927&p->outbuf[5], &dest_len,928data, data_len,929&session->local.comp_abstract);930if(rc)931return rc; /* compression failure */932
933if(data2 && data2_len) {934/* compress directly to the target buffer right after where the935previous call put data */
936dest2_len -= dest_len;937
938rc = session->local.comp->comp(session,939&p->outbuf[5 + dest_len],940&dest2_len,941data2, data2_len,942&session->local.comp_abstract);943}944else945dest2_len = 0;946if(rc)947return rc; /* compression failure */948
949data_len = dest_len + dest2_len; /* use the combined length */950}951else {952if((data_len + data2_len) >= (MAX_SSH_PACKET_LEN-0x100))953/* too large packet, return error for this until we make this954function split it up and send multiple SSH packets */
955return LIBSSH2_ERROR_INVAL;956
957/* copy the payload data */958memcpy(&p->outbuf[5], data, data_len);959if(data2 && data2_len)960memcpy(&p->outbuf[5 + data_len], data2, data2_len);961data_len += data2_len; /* use the combined length */962}963
964
965/* RFC4253 says: Note that the length of the concatenation of966'packet_length', 'padding_length', 'payload', and 'random padding'
967MUST be a multiple of the cipher block size or 8, whichever is
968larger. */
969
970/* Plain math: (4 + 1 + packet_length + padding_length) % blocksize == 0 */971
972packet_length = data_len + 1 + 4; /* 1 is for padding_length field9734 for the packet_length field */
974/* subtract 4 bytes of the packet_length field when padding AES-GCM975or with ETM */
976crypt_offset = (etm || (encrypted && CRYPT_FLAG_R(session, PKTLEN_AAD)))977? 4 : 0;978etm_crypt_offset = etm ? 4 : 0;979
980/* at this point we have it all except the padding */981
982/* first figure out our minimum padding amount to make it an even983block size */
984padding_length = blocksize - ((packet_length - crypt_offset) % blocksize);985
986/* if the padding becomes too small we add another blocksize worth987of it (taken from the original libssh2 where it didn't have any
988real explanation) */
989if(padding_length < 4) {990padding_length += blocksize;991}992#ifdef LIBSSH2_RANDOM_PADDING993/* FIXME: we can add padding here, but that also makes the packets994bigger etc */
995
996/* now we can add 'blocksize' to the padding_length N number of times997(to "help thwart traffic analysis") but it must be less than 255 in
998total */
999rand_max = (255 - padding_length) / blocksize + 1;1000padding_length += blocksize * (seed % rand_max);1001#endif1002
1003packet_length += padding_length;1004
1005/* append the MAC length to the total_length size */1006total_length =1007packet_length + (encrypted ? session->local.mac->mac_len : 0);1008
1009/* store packet_length, which is the size of the whole packet except1010the MAC and the packet_length field itself */
1011_libssh2_htonu32(p->outbuf, (uint32_t)(packet_length - 4));1012/* store padding_length */1013p->outbuf[4] = (unsigned char)padding_length;1014
1015/* fill the padding area with random junk */1016if(_libssh2_random(p->outbuf + 5 + data_len, padding_length)) {1017return _libssh2_error(session, LIBSSH2_ERROR_RANDGEN,1018"Unable to get random bytes for packet padding");1019}1020
1021if(encrypted) {1022size_t i;1023
1024/* Calculate MAC hash. Put the output at index packet_length,1025since that size includes the whole packet. The MAC is
1026calculated on the entire unencrypted packet, including all
1027fields except the MAC field itself. This is skipped in the
1028INTEGRATED_MAC case, where the crypto algorithm also does its
1029own hash. */
1030if(!etm && !CRYPT_FLAG_R(session, INTEGRATED_MAC)) {1031if(session->local.mac->hash(session, p->outbuf + packet_length,1032session->local.seqno, p->outbuf,1033packet_length, NULL, 0,1034&session->local.mac_abstract))1035return _libssh2_error(session, LIBSSH2_ERROR_MAC_FAILURE,1036"Failed to calculate MAC");1037}1038
1039/* Encrypt the whole packet data, one block size at a time.1040The MAC field is not encrypted unless INTEGRATED_MAC. */
1041/* Some crypto back-ends could handle a single crypt() call for1042encryption, but (presumably) others cannot, so break it up
1043into blocksize-sized chunks to satisfy them all. */
1044for(i = etm_crypt_offset; i < packet_length;1045i += session->local.crypt->blocksize) {1046unsigned char *ptr = &p->outbuf[i];1047size_t bsize = LIBSSH2_MIN(session->local.crypt->blocksize,1048(int)(packet_length-i));1049/* The INTEGRATED_MAC case always has an extra call below, so it1050will never be LAST_BLOCK up here. */
1051int firstlast = i == 0 ? FIRST_BLOCK :1052(!CRYPT_FLAG_L(session, INTEGRATED_MAC)1053&& (i == packet_length - session->local.crypt->blocksize)1054? LAST_BLOCK: MIDDLE_BLOCK);1055/* In the AAD case, the last block would be only 4 bytes because1056everything is offset by 4 since the initial packet_length isn't
1057encrypted. In this case, combine that last short packet with the
1058previous one since AES-GCM crypt() assumes that the entire MAC
1059is available in that packet so it can set that to the
1060authentication tag. */
1061if(!CRYPT_FLAG_L(session, INTEGRATED_MAC))1062if(i > packet_length - 2*bsize) {1063/* increase the final block size */1064bsize = packet_length - i;1065/* advance the loop counter by the extra amount */1066i += bsize - session->local.crypt->blocksize;1067}1068_libssh2_debug((session, LIBSSH2_TRACE_SOCKET,1069"crypting bytes %lu-%lu", (unsigned long)i,1070(unsigned long)(i + bsize - 1)));1071if(session->local.crypt->crypt(session, ptr,1072bsize,1073&session->local.crypt_abstract,1074firstlast))1075return LIBSSH2_ERROR_ENCRYPT; /* encryption failure */1076}1077/* Call crypt() one last time so it can be filled in with the MAC */1078if(CRYPT_FLAG_L(session, INTEGRATED_MAC)) {1079int authlen = session->local.mac->mac_len;1080assert((size_t)total_length <=1081packet_length + session->local.crypt->blocksize);1082if(session->local.crypt->crypt(session, &p->outbuf[packet_length],1083authlen,1084&session->local.crypt_abstract,1085LAST_BLOCK))1086return LIBSSH2_ERROR_ENCRYPT; /* encryption failure */1087}1088
1089if(etm) {1090/* Calculate MAC hash. Put the output at index packet_length,1091since that size includes the whole packet. The MAC is
1092calculated on the entire packet (length plain the rest
1093encrypted), including all fields except the MAC field
1094itself. */
1095if(session->local.mac->hash(session, p->outbuf + packet_length,1096session->local.seqno, p->outbuf,1097packet_length, NULL, 0,1098&session->local.mac_abstract))1099return _libssh2_error(session, LIBSSH2_ERROR_MAC_FAILURE,1100"Failed to calculate MAC");1101}1102}1103
1104session->local.seqno++;1105
1106if(session->kex_strict && data[0] == SSH_MSG_NEWKEYS) {1107session->local.seqno = 0;1108}1109
1110ret = LIBSSH2_SEND(session, p->outbuf, total_length,1111LIBSSH2_SOCKET_SEND_FLAGS(session));1112if(ret < 0)1113_libssh2_debug((session, LIBSSH2_TRACE_SOCKET,1114"Error sending %ld bytes: %ld",1115(long)total_length, (long)-ret));1116else {1117_libssh2_debug((session, LIBSSH2_TRACE_SOCKET,1118"Sent %ld/%ld bytes at %p",1119(long)ret, (long)total_length, (void *)p->outbuf));1120debugdump(session, "libssh2_transport_write send()", p->outbuf, ret);1121}1122
1123if(ret != total_length) {1124if(ret >= 0 || ret == -EAGAIN) {1125/* the whole packet could not be sent, save the rest */1126session->socket_block_directions |= LIBSSH2_SESSION_BLOCK_OUTBOUND;1127p->odata = orgdata;1128p->olen = orgdata_len;1129p->osent = ret <= 0 ? 0 : ret;1130p->ototal_num = total_length;1131return LIBSSH2_ERROR_EAGAIN;1132}1133return LIBSSH2_ERROR_SOCKET_SEND;1134}1135
1136/* the whole thing got sent away */1137p->odata = NULL;1138p->olen = 0;1139
1140return LIBSSH2_ERROR_NONE; /* all is good */1141}
1142