📄 ssh.c
字号:
/* The following code re-uses internal parts of cryptlib, so it provides its
own dummy functions as stubs for cryptlib-internal ones. Since this would
produce link errors when cryptlib is statically linked with the test
app, we only enable it for the threaded Windows (i.e. DLL) self-test */
#ifdef WINDOWS_THREADS
/* The following code is a bare-bones SFTP implementation created purely for
interop/performance testing of cryptlib's SSH implementation. It does
the bare minimum needed to set up an SFTP transfer, and shouldn't be used
for anything other than testing.
Rather than creating our own versions of code already present in cryptlib,
we pull in the cryptlib code wholesale here unless we've built cryptlib as
a static lib, in which case it'll already be present. This is a pretty
ugly hack, but saves having to copy over a pile of cryptlib code.
Because cryptlib has an internal BYTE type, we need to no-op it out before
we pull in any cryptlib code */
#undef BYTE
#define BYTE _BYTE_DUMMY
#ifdef BOOLEAN
#undef BOOLEAN /* May be a typedef or a #define */
#endif /* BOOLEAN */
#ifndef STATIC_LIB
#if defined( SYMANTEC_C ) || defined( __BEOS__ )
#define INC_ALL
#include "misc_rw.c"
#elif defined( _MSC_VER )
#define INC_CHILD
#include "../misc/misc_rw.c"
#else
#include "misc/misc_rw.c"
#endif /* Compiler-specific includes */
#endif /* Non-static lib cryptlib */
#undef BYTE
#define BYTE unsigned char
/* Replacements for cryptlib stream routines */
#define sMemDisconnect( stream )
#define sMemConnect sMemOpen
int sMemOpen( STREAM *stream, void *buffer, const int bufSize )
{
memset( stream, 0, sizeof( STREAM ) );
stream->buffer = ( void * ) buffer;
stream->bufEnd = bufSize;
return( CRYPT_OK );
}
int sread( STREAM *stream, void *buffer, const int count )
{
if( stream->bufPos + count > stream->bufEnd )
{
sSetError( stream, CRYPT_ERROR_UNDERFLOW );
return( CRYPT_ERROR_UNDERFLOW );
}
memcpy( buffer, stream->buffer + stream->bufPos, count );
stream->bufPos += count;
return( CRYPT_OK );
}
int swrite( STREAM *stream, const void *buffer, const int count )
{
if( stream->buffer != NULL )
{
if( stream->bufPos + count > stream->bufEnd )
{
sSetError( stream, CRYPT_ERROR_OVERFLOW );
return( CRYPT_ERROR_OVERFLOW );
}
memcpy( stream->buffer + stream->bufPos, buffer, count );
}
stream->bufPos += count;
return( CRYPT_OK );
}
int sgetc( STREAM *stream )
{
int ch;
if( stream->bufPos + 1 > stream->bufEnd )
{
sSetError( stream, CRYPT_ERROR_UNDERFLOW );
return( CRYPT_ERROR_UNDERFLOW );
}
ch = stream->buffer[ stream->bufPos ];
stream->bufPos++;
return( ch );
}
int sputc( STREAM *stream, const int data )
{
if( stream->buffer != NULL )
{
if( stream->bufPos + 1 > stream->bufEnd )
{
sSetError( stream, CRYPT_ERROR_OVERFLOW );
return( CRYPT_ERROR_OVERFLOW );
}
stream->buffer[ stream->bufPos++ ] = data;
}
else
stream->bufPos++;
return( CRYPT_OK );
}
int sseek( STREAM *stream, const long position )
{
return( 0 );
}
int sPeek( STREAM *stream )
{
return( 0 );
}
int sSkip( STREAM *stream, const long offset )
{
return( 0 );
}
/* Dummy routines needed in misc_rw.c */
int BN_num_bits( const BIGNUM *a ) { return 0; }
int BN_high_bit( BIGNUM *a ) { return 0; }
BIGNUM *BN_bin2bn( const unsigned char *s, int len, BIGNUM *ret ) { return NULL; }
int BN_bn2bin( const BIGNUM *a, unsigned char *to ) { return 0; }
/* SFTP command types */
#define SSH_FXP_INIT 1
#define SSH_FXP_VERSION 2
#define SSH_FXP_OPEN 3
#define SSH_FXP_CLOSE 4
#define SSH_FXP_READ 5
#define SSH_FXP_WRITE 6
#define SSH_FXP_LSTAT 7
#define SSH_FXP_FSTAT 8
#define SSH_FXP_SETSTAT 9
#define SSH_FXP_FSETSTAT 10
#define SSH_FXP_OPENDIR 11
#define SSH_FXP_READDIR 12
#define SSH_FXP_REMOVE 13
#define SSH_FXP_MKDIR 14
#define SSH_FXP_RMDIR 15
#define SSH_FXP_REALPATH 16
#define SSH_FXP_STAT 17
#define SSH_FXP_RENAME 18
#define SSH_FXP_READLINK 19
#define SSH_FXP_SYMLINK 20
#define SSH_FXP_STATUS 101
#define SSH_FXP_HANDLE 102
#define SSH_FXP_DATA 103
#define SSH_FXP_NAME 104
#define SSH_FXP_ATTRS 105
/* SFTP attribute presence flags. When these flags are set, the
corresponding file attribute value is present */
#define SSH_FILEXFER_ATTR_SIZE 0x01
#define SSH_FILEXFER_ATTR_UIDGID 0x02
#define SSH_FILEXFER_ATTR_PERMISSIONSv3 0x04
#define SSH_FILEXFER_ATTR_ACMODTIME 0x08
#define SSH_FILEXFER_ATTR_ACCESSTIME 0x08
#define SSH_FILEXFER_ATTR_CREATETIME 0x10
#define SSH_FILEXFER_ATTR_MODIFYTIME 0x20
#define SSH_FILEXFER_ATTR_PERMISSIONSv4 0x40
#define SSH_FILEXFER_ATTR_ACL 0x40
#define SSH_FILEXFER_ATTR_OWNERGROUP 0x80
#define SSH_FILEXFER_ATTR_SUBSECOND_TIMES 0x100
#define SSH_FILEXFER_ATTR_EXTENDED 0x80000000
/* SFTP file open/create flags */
#define SSH_FXF_READ 0x01
#define SSH_FXF_WRITE 0x02
#define SSH_FXF_APPEND 0x04
#define SSH_FXF_CREAT 0x08
#define SSH_FXF_TRUNC 0x10
#define SSH_FXF_EXCL 0x20
#define SSH_FXF_TEXT 0x40
/* SFTP file types */
#define SSH_FILETYPE_REGULAR 1
#define SSH_FILETYPE_DIRECTORY 2
#define SSH_FILETYPE_SYMLINK 3
#define SSH_FILETYPE_SPECIAL 4
#define SSH_FILETYPE_UNKNOWN 5
/* SFTP status codes */
#define SSH_FX_OK 0
#define SSH_FX_EOF 1
#define SSH_FX_NO_SUCH_FILE 2
#define SSH_FX_PERMISSION_DENIED 3
#define SSH_FX_FAILURE 4
#define SSH_FX_BAD_MESSAGE 5
#define SSH_FX_NO_CONNECTION 6
#define SSH_FX_CONNECTION_LOST 7
#define SSH_FX_OP_UNSUPPORTED 8
#define SSH_FX_INVALID_HANDLE 9
#define SSH_FX_NO_SUCH_PATH 10
#define SSH_FX_FILE_ALREADY_EXISTS 11
#define SSH_FX_WRITE_PROTECT 12
#define SSH_FX_NO_MEDIA 13
/* A structure to contain SFTP file attributes */
typedef struct {
BOOLEAN isDirectory; /* Whether directory or normal file */
long size; /* File size */
int permissions; /* File permissions */
time_t ctime, atime, mtime; /* File create, access, mod times */
} SFTP_ATTRS;
/* A structure to contain SFTP session information */
#define MAX_HANDLE_SIZE 16
typedef struct {
int version; /* SFTP protocol version */
long id; /* Session ID */
BYTE handle[ MAX_HANDLE_SIZE ]; /* File handle */
int handleSize;
} SFTP_INFO;
/* Read/write SFTP attributes. This changed completely from v3 to v4, so we
have to treat them as special-cases:
uint32 flags
byte file_type
uint64 size (present if ATTR_SIZE)
string owner (present if ATTR_OWNERGROUP)
string group (present if ATTR_OWNERGROUP)
uint32 permissions (present if ATTR_PERMISSIONS)
uint64 atime (present if ATTR_ACCESSTIME)
uint32 atime_nseconds (present if ATTR_SUBSECOND_TIMES)
uint64 createtime (present if ATTR_CREATETIME)
uint32 createtime_nseconds (present if ATTR_SUBSECOND_TIMES)
uint64 mtime (present if ATTR_MODIFYTIME)
uint32 mtime_nseconds (present if ATTR_SUBSECOND_TIMES)
string acl (present if ATTR_ACL)
uint32 extended_count (present if ATTR_EXTENDED)
string extended_type
string extended_value
[ extended_count type/value pairs ] */
static int sizeofAttributes( SFTP_ATTRS *attributes, const int version )
{
int size = UINT32_SIZE; /* Flags */
if( version < 4 )
{
if( attributes->size != CRYPT_UNUSED )
size += UINT64_SIZE;
if( attributes->permissions != CRYPT_UNUSED )
size += UINT32_SIZE;
if( attributes->atime )
size += UINT32_SIZE;
if( attributes->mtime )
size += UINT32_SIZE;
}
else
{
size++;
if( attributes->size != CRYPT_UNUSED )
size += UINT64_SIZE;
if( attributes->permissions != CRYPT_UNUSED )
size += UINT32_SIZE;
if( attributes->ctime )
size += UINT64_SIZE;
if( attributes->atime )
size += UINT64_SIZE;
if( attributes->mtime )
size += UINT64_SIZE;
}
return( size );
}
static int readAttributes( STREAM *stream, SFTP_ATTRS *attributes, const int version )
{
long flags;
memset( attributes, 0, sizeof( SFTP_ATTRS ) );
attributes->permissions = CRYPT_UNUSED;
attributes->size = CRYPT_UNUSED;
/* Read basic attribute information: File size, and owner, and
permissions */
flags = readUint32( stream );
if( cryptStatusError( flags ) )
return( flags );
if( version < 4 )
{
if( flags & SSH_FILEXFER_ATTR_SIZE )
attributes->size = readUint64( stream );
if( flags & SSH_FILEXFER_ATTR_UIDGID )
{
readUint32( stream );
readUint32( stream );
}
if( flags & SSH_FILEXFER_ATTR_PERMISSIONSv3 )
attributes->permissions = readUint32( stream );
/* Read file access and modify times */
if( flags & SSH_FILEXFER_ATTR_ACMODTIME )
{
readUint32Time( stream, &attributes->atime );
readUint32Time( stream, &attributes->mtime );
}
}
else
{
if( flags & SSH_FILEXFER_ATTR_SIZE )
attributes->size = readUint64( stream );
if( flags & SSH_FILEXFER_ATTR_OWNERGROUP )
{
readString32( stream, NULL, NULL, 0 );
readString32( stream, NULL, NULL, 0 );
}
if( flags & SSH_FILEXFER_ATTR_PERMISSIONSv4 )
attributes->permissions = readUint32( stream );
/* Read file create, access, and modify times */
if( flags & SSH_FILEXFER_ATTR_ACCESSTIME )
{
readUint64Time( stream, &attributes->atime );
if( flags & SSH_FILEXFER_ATTR_SUBSECOND_TIMES )
readUint32( stream );
}
if( flags & SSH_FILEXFER_ATTR_CREATETIME )
{
readUint64Time( stream, &attributes->ctime );
if( flags & SSH_FILEXFER_ATTR_SUBSECOND_TIMES )
readUint32( stream );
}
if( flags & SSH_FILEXFER_ATTR_MODIFYTIME )
{
readUint64Time( stream, &attributes->mtime );
if( flags & SSH_FILEXFER_ATTR_SUBSECOND_TIMES )
readUint32( stream );
}
}
/* Read ACLs and extended attribute type/value pairs, the one thing that
stayed the same from v3 to v4 */
if( flags & SSH_FILEXFER_ATTR_ACL )
readString32( stream, NULL, NULL, 0 );
if( flags & SSH_FILEXFER_ATTR_EXTENDED )
{
int extAttrCount = readUint32( stream );
if( cryptStatusError( extAttrCount ) )
return( extAttrCount );
while( extAttrCount > 0 )
{
readString32( stream, NULL, NULL, 0 );
readString32( stream, NULL, NULL, 0 );
extAttrCount--;
}
}
return( sGetStatus( stream ) );
}
static int writeAttributes( STREAM *stream, SFTP_ATTRS *attributes, const int version )
{
int flags = 0;
if( version < 4 )
{
/* Indicate which attribute values we're going to write */
if( attributes->size != CRYPT_UNUSED )
flags |= SSH_FILEXFER_ATTR_SIZE;
if( attributes->permissions != CRYPT_UNUSED )
flags |= SSH_FILEXFER_ATTR_PERMISSIONSv3;
if( attributes->atime )
flags |= SSH_FILEXFER_ATTR_ACMODTIME;
writeUint32( stream, flags );
/* Write the optional attributes */
if( attributes->size != CRYPT_UNUSED )
writeUint64( stream, attributes->size );
if( attributes->permissions != CRYPT_UNUSED )
writeUint32( stream, attributes->permissions );
if( attributes->atime )
{
writeUint32Time( stream, attributes->atime );
writeUint32Time( stream, attributes->mtime );
}
}
else
{
/* Indicate which attribute values we're going to write */
if( attributes->size != CRYPT_UNUSED )
flags |= SSH_FILEXFER_ATTR_SIZE;
if( attributes->permissions != CRYPT_UNUSED )
flags |= SSH_FILEXFER_ATTR_PERMISSIONSv4;
if( attributes->ctime )
flags |= SSH_FILEXFER_ATTR_CREATETIME;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -