📄 ssh.c
字号:
}
else
{
/* It's a local session, just send a simple text string for
testing */
status = cryptPushData( cryptSession, "Some test data", 14,
&bytesCopied );
if( cryptStatusOK( status ) )
status = cryptFlushData( cryptSession );
if( cryptStatusError( status ) || bytesCopied != 14 )
{
printf( "Couldn't send data to server, status %d, line "
"%d.\n", status, __LINE__ );
return( FALSE );
}
/* Make sure that we stay around long enough to get the
server's response */
delayThread( 1 );
/* Print the server's response */
if( !printDataInfo( cryptSession, buffer, &bytesCopied,
isServer ) )
return( FALSE );
}
}
/* If we're performing a multi-channel test, close the second channel */
if( testType == SSH_TEST_MULTICHANNEL )
{
if( isServer )
{
/* Perform a dummy pop to process the channel close */
( void ) cryptPopData( cryptSession, buffer, BUFFER_SIZE,
&bytesCopied );
}
else
{
/* Close the current channel */
status = cryptSetAttribute( cryptSession,
CRYPT_SESSINFO_SSH_CHANNEL_ACTIVE,
FALSE );
if( cryptStatusError( status ) )
{
printf( "Couldn't close second SSH chanel, status %d, line "
"%d.\n", status, __LINE__ );
return( FALSE );
}
printf( "Closed second channel to server.\n" );
fflush( stdout );
}
}
/* Clean up */
status = cryptDestroySession( cryptSession );
if( cryptStatusError( status ) )
{
printf( "cryptDestroySession() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
puts( isServer ? "SVR: SSH server session succeeded.\n" : \
"SSH client session succeeded.\n" );
fflush( stdout );
return( TRUE );
}
int testSessionSSHv1( void )
{
return( connectSSH( CRYPT_SESSION_SSH, SSH_TEST_SSH1, FALSE ) );
}
int testSessionSSH( void )
{
return( connectSSH( CRYPT_SESSION_SSH, SSH_TEST_NORMAL, FALSE ) );
}
int testSessionSSHClientCert( void )
{
return( connectSSH( CRYPT_SESSION_SSH, SSH_TEST_CLIENTCERT, FALSE ) );
}
int testSessionSSHPortforward( void )
{
return( connectSSH( CRYPT_SESSION_SSH, SSH_TEST_PORTFORWARDING, FALSE ) );
}
int testSessionSSHExec( void )
{
return( connectSSH( CRYPT_SESSION_SSH, SSH_TEST_EXEC, FALSE ) );
}
int testSessionSSH_SFTP( void )
{
return( connectSSH( CRYPT_SESSION_SSH, SSH_TEST_SUBSYSTEM, FALSE ) );
}
int testSessionSSHv1Server( void )
{
return( connectSSH( CRYPT_SESSION_SSH_SERVER, SSH_TEST_SSH1, FALSE ) );
}
int testSessionSSHServer( void )
{
return( connectSSH( CRYPT_SESSION_SSH_SERVER, SSH_TEST_CONFIRMAUTH, FALSE ) );
}
int testSessionSSH_SFTPServer( void )
{
return( connectSSH( CRYPT_SESSION_SSH_SERVER, SSH_TEST_SUBSYSTEM, FALSE ) );
}
/* Perform a client/server loopback test */
#ifdef WINDOWS_THREADS
unsigned __stdcall ssh1ServerThread( void *dummy )
{
connectSSH( CRYPT_SESSION_SSH_SERVER, SSH_TEST_SSH1, TRUE );
_endthreadex( 0 );
return( 0 );
}
unsigned __stdcall ssh2ServerThread( void *dummy )
{
connectSSH( CRYPT_SESSION_SSH_SERVER, SSH_TEST_NORMAL, TRUE );
_endthreadex( 0 );
return( 0 );
}
unsigned __stdcall ssh2ServerFingerprintThread( void *dummy )
{
connectSSH( CRYPT_SESSION_SSH_SERVER, SSH_TEST_FINGERPRINT, TRUE );
_endthreadex( 0 );
return( 0 );
}
unsigned __stdcall ssh2ServerMultichannelThread( void *dummy )
{
connectSSH( CRYPT_SESSION_SSH_SERVER, SSH_TEST_MULTICHANNEL, TRUE );
_endthreadex( 0 );
return( 0 );
}
unsigned __stdcall ssh2ServerDualThread1( void *dummy )
{
connectSSH( CRYPT_SESSION_SSH_SERVER, SSH_TEST_DUALTHREAD, TRUE );
_endthreadex( 0 );
return( 0 );
}
unsigned __stdcall ssh2ServerDualThread2( void *dummy )
{
connectSSH( CRYPT_SESSION_SSH_SERVER, SSH_TEST_DUALTHREAD2, TRUE );
_endthreadex( 0 );
return( 0 );
}
unsigned __stdcall sftpServerThread( void *dummy )
{
connectSSH( CRYPT_SESSION_SSH_SERVER, SSH_TEST_SUBSYSTEM, TRUE );
_endthreadex( 0 );
return( 0 );
}
static int sshClientServer( const SSH_TEST_TYPE testType )
{
HANDLE hThread;
unsigned threadID;
int status;
/* Start the server */
createMutex();
hThread = ( HANDLE ) _beginthreadex( NULL, 0,
( testType == SSH_TEST_SUBSYSTEM ) ? \
sftpServerThread : \
( testType == SSH_TEST_SSH1 ) ? \
ssh1ServerThread : \
( testType == SSH_TEST_FINGERPRINT ) ? \
ssh2ServerFingerprintThread : \
( testType == SSH_TEST_MULTICHANNEL ) ? \
ssh2ServerMultichannelThread : \
( testType == SSH_TEST_DUALTHREAD ) ? \
ssh2ServerDualThread1 : \
ssh2ServerThread,
NULL, 0, &threadID );
Sleep( 1000 );
/* Connect to the local server */
status = connectSSH( CRYPT_SESSION_SSH, testType, TRUE );
waitForThread( hThread );
destroyMutex();
return( status );
}
int testSessionSSHv1ClientServer( void )
{
return( sshClientServer( SSH_TEST_SSH1 ) );
}
int testSessionSSHClientServer( void )
{
return( sshClientServer( SSH_TEST_NORMAL ) );
}
int testSessionSSHClientServerFingerprint( void )
{
/* Note that this test tests the correct functioning of a refused
connection when an incorrect key fingerprint is used, so it's
supposed to fail */
return( sshClientServer( SSH_TEST_FINGERPRINT ) );
}
int testSessionSSHClientServerSFTP( void )
{
return( sshClientServer( SSH_TEST_SUBSYSTEM ) );
}
int testSessionSSHClientServerPortForward( void )
{
return( sshClientServer( SSH_TEST_PORTFORWARDING ) );
}
int testSessionSSHClientServerExec( void )
{
return( sshClientServer( SSH_TEST_EXEC ) );
}
int testSessionSSHClientServerMultichannel( void )
{
return( sshClientServer( SSH_TEST_MULTICHANNEL ) );
}
int testSessionSSHClientServerDualThread( void )
{
return( sshClientServer( SSH_TEST_DUALTHREAD ) );
}
#endif /* WINDOWS_THREADS */
/****************************************************************************
* *
* SFTP Routines for SSH *
* *
****************************************************************************/
/* 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
#include "misc/misc_rw.c"
#endif /* Non-static lib cryptlib */
#undef BYTE
#define BYTE unsigned char
/* Replacements for cryptlib stream routines */
#define sMemDisconnect( stream )
#define sMemConnect sMemOpen
#define stell( stream ) ( ( stream )->bufPos )
int sSetError( STREAM *stream, const int status )
{
stream->status = status;
return( status );
}
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 );
}
int sMemDataLeft( const STREAM *stream )
{
return( stream->bufSize - stream->bufPos );
}
/* 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; }
int extractBignum( BIGNUM *bn, const void *buffer, const int length,
const int minLength, const int maxLength,
const BIGNUM *maxRange, const BOOLEAN checkKeysize ) { return -1; }
int getBignumData( const void *bignumPtr, void *data, const int dataMaxLength,
int *dataLength ) { return -1; }
/* 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -