36 const char *packetName;
38 static const PACKET_NAME_INFO packetNameInfo[] = {
81 for( i = 0; packetNameInfo[ i ].packetType != packetType && \
89 return( packetNameInfo[ i ].packetName );
111 status = sread( stream, &ch, 1 );
118 const int headerStatus,
123 const int expectedType )
126 assert(
isReadPtr( header, headerLength ) );
142 if( !
isServer( sessionInfoPtr ) && \
148 "Remote server has closed the connection, possibly "
149 "in response to an incorrect password or other "
150 "authentication value" ) );
163 "CuteFTP client has aborted the handshake due to a "
164 "CuteFTP bug, please contact the CuteFTP vendor" ) );
177 header[ 0 ] ==
'F' && \
178 ( !memcmp( header,
"FATAL: ", 7 ) || \
179 !memcmp( header,
"FATAL ERROR:", 12 ) ) )
187 memcpy( sessionInfoPtr->receiveBuffer, header,
191 status = readTextLine( readCharFunction, &sessionInfoPtr->stream,
194 sessionInfoPtr->receiveBufSize - 128 ),
195 &length, &isTextDataError );
212 "Remote SSH software has crashed, diagnostic was: '%s'",
213 sanitiseString( sessionInfoPtr->receiveBuffer,
225 static
int checkPacketValid(
IN_BYTE const int packetType,
228 static const int validHSPacketTbl[] = {
244 static const int validDataPacketTbl[] = {
261 const int *validPacketTbl = isHandshake ? validHSPacketTbl : \
263 const int validPacketTblSize = isHandshake ? \
264 FAILSAFE_ARRAYSIZE( validHSPacketTbl,
int ) : \
268 ENSURES( packetType >= 0 && packetType <= 0xFF );
271 for( i = 0; i < validPacketTblSize && \
272 validPacketTbl[ i ] != packetType && \
274 ENSURES( i < validPacketTblSize );
316 errorCode = readUint32( stream );
321 "Invalid disconnect status information in disconnect "
334 memcpy( errorString,
"<No details available>", 22 + 1 );
338 status = mapValue( errorCode, &clibStatus, errorMapTbl,
348 "Received disconnect message: %s", errorString ) );
357 const int expectedType,
366 BYTE *headerBufPtr = isHandshake ? headerBuffer : sshInfo->headerBuffer;
368 int extraLength = 0,
status;
371 assert(
isWritePtr( packetLength,
sizeof(
long ) ) );
372 assert(
isWritePtr( packetExtraLength,
sizeof(
int ) ) );
374 assert( readInfo == NULL || \
382 *packetExtraLength = 0;
385 "Packet header size" );
402 status = readFixedHeaderAtomic( sessionInfoPtr, headerBufPtr,
406 const int localStatus = \
407 checkHandshakePacketStatus( sessionInfoPtr, status,
411 status = localStatus;
416 status = readFixedHeader( sessionInfoPtr, headerBufPtr,
436 extraLength = sessionInfoPtr->authBlocksize;
463 length = readUint32( &stream );
466 "Header length calculation" );
470 length + extraLength >= sessionInfoPtr->receiveBufSize )
472 sMemDisconnect( &stream );
475 "Invalid packet length %ld, should be %d...%d",
478 sessionInfoPtr->receiveBufSize - extraLength ) );
481 (
LENGTH_SIZE + length ) % sessionInfoPtr->cryptBlocksize != 0 )
483 sMemDisconnect( &stream );
486 "Invalid packet length %ld, isn't a multiple of cipher "
488 sessionInfoPtr->cryptBlocksize ) );
495 "Header length calculation" );
497 sshInfo->packetType = headerBufPtr[
LENGTH_SIZE + 1 ];
499 sshInfo->padLength > 255 )
501 sMemDisconnect( &stream );
504 "Invalid%s packet padding length %d, should be %d...255",
505 isHandshake ?
" handshake" :
"",
510 status = checkPacketValid( sshInfo->packetType, isHandshake );
513 sMemDisconnect( &stream );
516 "Invalid%s packet %s (%d), expected %s (%d)",
517 isHandshake ?
" handshake" :
"",
525 ENSURES( ( isHandshake && sessionInfoPtr->receiveBufPos == 0 ) || \
529 sessionInfoPtr->receiveBufSize ) );
530 status = sread( &stream, sessionInfoPtr->receiveBuffer + \
531 sessionInfoPtr->receiveBufPos,
533 sMemDisconnect( &stream );
538 *packetExtraLength = extraLength;
554 IN_RANGE( 1, 1024 )
const int minPacketSize )
556 SSH_INFO *sshInfo = sessionInfoPtr->sessionSSH;
558 int minPacketLength = minPacketSize, noPackets,
status;
564 REQUIRES( minPacketSize >= 1 && minPacketSize <= 1024 );
596 REQUIRES( sessionInfoPtr->receiveBufPos == 0 && \
597 sessionInfoPtr->receiveBufEnd == 0 );
598 status = readPacketHeaderSSH2( sessionInfoPtr, expectedType, &length,
599 &extraLength, sshInfo, NULL );
603 length + extraLength < sessionInfoPtr->receiveBufSize );
611 const long remainingLength = length + extraLength - \
612 SSH2_HEADER_REMAINDER_SIZE;
618 status = readLength = \
619 sread( &sessionInfoPtr->stream,
620 sessionInfoPtr->receiveBuffer + \
624 sNetGetErrorInfo( &sessionInfoPtr->stream,
625 &sessionInfoPtr->errorInfo );
628 if( readLength != remainingLength )
632 "Timeout during handshake packet remainder read, "
633 "only got %d of %ld bytes", readLength,
648 sessionInfoPtr->receiveBuffer + \
656 status = checkMacSSH( sessionInfoPtr->iAuthInContext,
658 sessionInfoPtr->receiveBuffer,
659 length + extraLength, length,
673 "Bad message MAC for %s packet, length %ld, "
674 "probably due to an incorrect key being used "
675 "to generate the MAC",
681 "Bad message MAC for %s packet, length %ld",
687 DEBUG_PRINT((
"Read %s (%d) packet, length %ld.\n",
702 "%s sent an excessive number of consecutive no-op "
703 "packets, it may be stuck in a loop",
704 isServer( sessionInfoPtr ) ?
"Client" :
"Server" ) );
722 if( length < minPacketLength || \
727 "Invalid length %ld for %s (%d) packet, should be %d...%d",
744 sessionInfoPtr->receiveBufSize ) );
745 memmove( sessionInfoPtr->receiveBuffer,
755 sMemConnect( &stream, sessionInfoPtr->receiveBuffer, length );
756 status = getDisconnectInfo( sessionInfoPtr, &stream );
757 sMemDisconnect( &stream );
763 switch( expectedType )
809 "Invalid handshake packet %s (%d), expected "
810 "SSH_MSG_GLOBAL_REQUEST (80) or "
811 "SSH_MSG_CHANNEL_REQUEST (98)",
831 "Invalid handshake packet %s (%d), expected %s (%d)",