📄 ssh.c
字号:
puts( " (Insufficiently secure protocol parameters, "
"continuing...)\n" );
return( TRUE );
}
return( FALSE );
}
if( testType == SSH_TEST_FINGERPRINT )
{
printf( "Attempt to connect with invalid key fingerprint succeeded "
"when it should\nhave failed, line %d.\n", __LINE__ );
return( FALSE );
}
/* Report the session security info */
if( !printSecurityInfo( cryptSession, isServer, TRUE ) )
return( FALSE );
status = cryptGetAttribute( cryptSession, CRYPT_SESSINFO_SSH_CHANNEL,
&channel );
if( cryptStatusError( status ) )
{
printf( "cryptGetAttributeString() failed with error code "
"%d, line %d.\n", status, __LINE__ );
return( FALSE );
}
printf( "%sCurrent channel is #%d.\n", isServer ? "SVR: " : "",
channel );
/* Report additional channel-specific information */
if( isServer )
{
/* Display info on any channels that the client has opened */
status = printChannelInfo( cryptSession, testType, TRUE );
if( cryptStatusError( status ) )
return( FALSE );
/* Process any additional information that the client may throw
at us after the user-auth has completed */
status = cryptPopData( cryptSession, buffer, BUFFER_SIZE,
&bytesCopied );
if( cryptStatusOK( status ) && bytesCopied > 0 )
printf( "SVR: Client sent additional %d bytes post-"
"handshake data.\n", bytesCopied );
else
if( status == CRYPT_ENVELOPE_RESOURCE )
{
/* The client performed additional control actions that were
handled inline as part of the data-pop, report the
details */
status = printChannelInfo( cryptSession, testType, TRUE );
if( cryptStatusError( status ) )
return( FALSE );
}
}
/* If we're using the SFTP subsystem as a server, use the special-case
routines for this */
#ifdef WINDOWS_THREADS
if( testType == SSH_TEST_SUBSYSTEM )
{
if( isServer )
{
int sftpServer( const CRYPT_SESSION cryptSession );
status = sftpServer( cryptSession );
if( cryptStatusError( status ) )
{
printf( "SVR: Couldn't receive SFTP data from client, status %d, "
"line %d.\n", status, __LINE__ );
return( FALSE );
}
cryptDestroySession( cryptSession );
puts( "SVR: SFTP server session succeeded.\n" );
return( TRUE );
}
else
{
int sftpClient( const CRYPT_SESSION cryptSession );
status = sftpClient( cryptSession );
if( cryptStatusError( status ) )
{
printf( "Couldn't send SFTP data to server, status %d, line "
"%d.\n", status, __LINE__ );
return( FALSE );
}
cryptDestroySession( cryptSession );
puts( "SFTP client session succeeded.\n" );
return( TRUE );
}
}
#endif /* WINDOWS_THREADS */
/* If we're performing a multi-channel test, open a second channel (the
server handles this as part of its general connect-handling) */
if( testType == SSH_TEST_MULTICHANNEL && !isServer )
{
status = createChannel( cryptSession, TEXT( "direct-tcpip" ),
TEXT( "localhost:5678" ) );
if( cryptStatusOK( status ) )
status = cryptGetAttribute( cryptSession,
CRYPT_SESSINFO_SSH_CHANNEL,
&channel );
if( cryptStatusOK( status ) )
status = cryptSetAttribute( cryptSession,
CRYPT_SESSINFO_SSH_CHANNEL_ACTIVE,
TRUE );
if( cryptStatusError( status ) )
{
printf( "Couldn't open second SSH chanel, status %d, line "
"%d.\n", status, __LINE__ );
return( FALSE );
}
printf( "Opened additional channel #%d to server.\n", channel );
}
/* Send data over the SSH link */
if( isServer )
{
/* Send a status message to the client */
status = cryptPushData( cryptSession, "Welcome to cryptlib, now go "
"away.\r\n", 35, &bytesCopied );
if( cryptStatusOK( status ) )
status = cryptFlushData( cryptSession );
if( cryptStatusError( status ) || bytesCopied != 35 )
{
printf( "SVR: Couldn't send data to client, status %d, line "
"%d.\n", status, __LINE__ );
return( FALSE );
}
}
/* Wait a bit while data arrives */
delayThread( 2 );
/* Print the first lot of output from the other side */
status = printDataInfo( cryptSession, buffer, &bytesCopied, isServer );
if( cryptStatusError( status ) )
return( FALSE );
/* If we're the server, echo the command to the client */
if( isServer )
{
const int clientBytesCopied = bytesCopied;
int dummy, i;
/* If it's a multi-channel test, send the response back on a
different channel. The currently-selected channel will be the
last one that the client opened (#2), so we can hardcode in
#1 for testing purposes */
if( testType == SSH_TEST_MULTICHANNEL )
{
status = cryptSetAttribute( cryptSession,
CRYPT_SESSINFO_SSH_CHANNEL, 1 );
if( cryptStatusError( status ) )
{
printf( "SVR: Couldn't select channel #1 to return data to "
"client, status %d, line %d.\n", status, __LINE__ );
return( FALSE );
}
}
for( i = 0; i < clientBytesCopied; i++ )
if( buffer[ i ] < ' ' || buffer[ i ] >= 0x7F )
buffer[ i ] = '.';
status = cryptPushData( cryptSession, "Input was [", 11, &dummy );
if( cryptStatusOK( status ) && clientBytesCopied > 0 )
status = cryptPushData( cryptSession, buffer, clientBytesCopied,
&bytesCopied );
if( cryptStatusOK( status ) )
status = cryptPushData( cryptSession, "]\r\n", 3, &dummy );
if( cryptStatusOK( status ) )
status = cryptFlushData( cryptSession );
if( cryptStatusError( status ) || bytesCopied != clientBytesCopied )
{
printf( "SVR: Couldn't send data to client, status %d, line "
"%d.\n", status, __LINE__ );
return( FALSE );
}
}
else
{
/* We're the client, if it's a session to a Unix ssh server, send a
sample command and display the output */
if( !localSession )
{
/* Send a command to the server and get the results */
status = cryptPushData( cryptSession, "ls -l | head -25\n", 18,
&bytesCopied );
if( cryptStatusOK( status ) )
status = cryptFlushData( cryptSession );
if( cryptStatusError( status ) || bytesCopied != 18 )
{
printf( "Couldn't send data to server, status %d, line "
"%d.\n", status, __LINE__ );
return( FALSE );
}
puts( "Sent 'ls -l | head -25'" );
delayThread( 3 );
status = printDataInfo( cryptSession, buffer, &bytesCopied,
isServer );
if( cryptStatusError( status ) )
return( FALSE );
}
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 */
status = printDataInfo( cryptSession, buffer, &bytesCopied,
isServer );
if( cryptStatusError( status ) )
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 */
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" );
}
}
/* 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" );
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 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 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 and wait for it to initialise */
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 : \
ssh2ServerThread,
NULL, 0, &threadID );
Sleep( 1000 );
/* Connect to the local server */
status = connectSSH( CRYPT_SESSION_SSH, testType, TRUE );
if( WaitForSingleObject( hThread, 15000 ) == WAIT_TIMEOUT )
{
puts( "Warning: Server thread is still active due to session "
"negotiation failure,\n this will cause an error "
"condition when cryptEnd() is called due\n to "
"resources remaining allocated. Press a key to continue." );
getchar();
}
CloseHandle( hThread );
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 testSessionSSHClientServerMultichannel( void )
{
return( sshClientServer( SSH_TEST_MULTICHANNEL ) );
}
#endif /* WINDOWS_THREADS */
/****************************************************************************
* *
* SFTP Routines for SSH *
* *
****************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -