📄 testsess.c
字号:
/****************************************************************************
* *
* cryptlib Secure Session Test Routines *
* Copyright Peter Gutmann 1998-2001 *
* *
****************************************************************************/
#ifdef _MSC_VER
#include "../cryptlib.h"
#include "../test/test.h"
#else
#include "cryptlib.h"
#include "test/test.h"
#endif /* Braindamaged MSC include handling */
/* Prototypes for functions in testcert.c */
int initOCSP( CRYPT_CERTIFICATE *cryptOCSPRequest, const int number,
const BOOLEAN ocspv2, const BOOLEAN revokedCert,
const BOOLEAN multipleCerts, const CRYPT_CONTEXT signingKey );
/****************************************************************************
* *
* Utility Functions *
* *
****************************************************************************/
/* Print information in the peer we're talking to */
static void printConnectInfo( const CRYPT_SESSION cryptSession )
{
time_t theTime;
char serverName[ 128 ];
int serverNameLength, serverPort, status;
time( &theTime );
status = cryptGetAttributeString( cryptSession, CRYPT_SESSINFO_CLIENT_NAME,
serverName, &serverNameLength );
if( cryptStatusError( status ) )
return;
serverName[ serverNameLength ] = '\0';
cryptGetAttribute( cryptSession, CRYPT_SESSINFO_CLIENT_PORT, &serverPort );
printf( "Connect attempt from %s, port %d, on %s", serverName, serverPort,
ctime( &theTime ) );
}
/* Set up a client/server to connect locally. For the client his simply
tells it where to connect, for the server this binds it to the local
address so we don't inadvertently open up outside ports (admittedly
they can't do much except run the hardcoded self-test, but it's better
not to do this at all) */
static BOOLEAN setLocalConnect( const CRYPT_SESSION cryptSession,
const int port, const BOOLEAN isServer )
{
int status;
status = cryptSetAttributeString( cryptSession,
CRYPT_SESSINFO_SERVER_NAME,
"localhost", 9 );
#ifdef __UNIX__
/* If we're running under Unix, set the port to a nonprivileged one so
we don't have to run as root */
if( cryptStatusOK( status ) )
status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_SERVER_PORT,
port + 2000 );
#endif /* __UNIX__ */
if( cryptStatusError( status ) )
{
printf( "cryptSetAttribute/AttributeString() failed with error code "
"%d, line %d.\n", status, __LINE__ );
return( FALSE );
}
return( TRUE );
}
/****************************************************************************
* *
* SSH Routines Test *
* *
****************************************************************************/
/* Establish an SSH session */
static int connectSSH( const CRYPT_SESSION_TYPE sessionType,
const BOOLEAN useClientCert,
const BOOLEAN localSession, const BOOLEAN forceSSHv2 )
{
CRYPT_SESSION cryptSession;
const BOOLEAN isServer = ( sessionType == CRYPT_SESSION_SSH_SERVER ) ? \
TRUE : FALSE;
char buffer[ 2048 ];
int cryptAlgo, keySize, bytesCopied, timeout, status;
printf( "Testing %sSSH%s%s session...\n", localSession ? "local " : "",
forceSSHv2 ? "v2" : "", isServer ? " server" : "" );
/* Create the session */
status = cryptCreateSession( &cryptSession, CRYPT_UNUSED, sessionType );
if( status == CRYPT_ERROR_PARAM3 ) /* SSH session access not available */
return( CRYPT_ERROR_NOTAVAIL );
if( cryptStatusError( status ) )
{
printf( "cryptCreateSession() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
/* Set up the server and user information and activate the session */
if( isServer )
{
CRYPT_CONTEXT privateKey;
if( !setLocalConnect( cryptSession, 22, TRUE ) )
return( FALSE );
status = getPrivateKey( &privateKey, SSH_PRIVKEY_FILE,
SSH_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );
if( cryptStatusOK( status ) )
{
status = cryptSetAttribute( cryptSession,
CRYPT_SESSINFO_PRIVATEKEY, privateKey );
cryptDestroyContext( privateKey );
}
}
else
{
if( localSession )
{
if( !setLocalConnect( cryptSession, 22, FALSE ) )
return( FALSE );
}
else
{
const char *serverName = forceSSHv2 ? \
SSH2_SERVER_NAME : SSH1_SERVER_NAME;
status = cryptSetAttributeString( cryptSession,
CRYPT_SESSINFO_SERVER_NAME,
serverName, strlen( serverName ) );
}
if( cryptStatusOK( status ) )
status = cryptSetAttributeString( cryptSession,
CRYPT_SESSINFO_USERNAME,
SSH_USER_NAME, strlen( SSH_USER_NAME ) );
if( cryptStatusOK( status ) )
if( useClientCert )
{
CRYPT_CONTEXT privateKey;
status = getPrivateKey( &privateKey, USER_PRIVKEY_FILE,
USER_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );
if( cryptStatusOK( status ) )
{
status = cryptSetAttribute( cryptSession,
CRYPT_SESSINFO_PRIVATEKEY, privateKey );
cryptDestroyContext( privateKey );
}
}
else
status = cryptSetAttributeString( cryptSession,
CRYPT_SESSINFO_PASSWORD,
SSH_PASSWORD, strlen( SSH_PASSWORD ) );
if( cryptStatusOK( status ) && forceSSHv2 )
status = cryptSetAttribute( cryptSession,
CRYPT_SESSINFO_PROTOCOLVERSION, 2 );
}
if( cryptStatusError( status ) )
{
printf( "cryptSetAttribute/AttributeString() failed with error code "
"%d, line %d.\n", status, __LINE__ );
return( FALSE );
}
status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );
if( isServer )
printConnectInfo( cryptSession );
if( cryptStatusError( status ) )
{
printExtError( cryptSession, isServer ? \
"Attempt to activate SSH server session" : \
"Attempt to activate SSH client session", status,
__LINE__ );
cryptDestroySession( cryptSession );
if( status == CRYPT_ERROR_OPEN )
{
/* These servers are constantly appearing and disappearing so if
we get a straight connect error we don't treat it as a serious
failure */
puts( " (Server could be down, faking it and continuing...)\n" );
return( CRYPT_ERROR_FAILED );
}
if( status == CRYPT_ERROR_WRONGKEY )
{
/* This is another possible soft error condition, the default
username and password shouldn't be able to get into many
machines */
puts( " (Incorrect username/password, continuing...)\n" );
return( TRUE );
}
if( status == CRYPT_ERROR_NOSECURE )
{
/* Another soft error condition, the server can't handle the
security level we want (usually occurs when trying to perform
an SSHv2 connect to an SSHv1 server) */
puts( " (Insufficiently secure protocol parameters, continuing...)\n" );
return( TRUE );
}
return( FALSE );
}
/* Report the session security info details */
status = cryptGetAttribute( cryptSession, CRYPT_CTXINFO_ALGO,
&cryptAlgo );
if( cryptStatusOK( status ) )
status = cryptGetAttribute( cryptSession, CRYPT_CTXINFO_KEYSIZE,
&keySize );
if( cryptStatusError( status ) )
{
printf( "Couldn't query encryption algorithm and keysize used for "
"session, status %d, line %d.\n", status, __LINE__ );
return( status );
}
printf( "%s session is protected using algorithm %d with a %d bit key.\n",
isServer ? "Server" : "Client", cryptAlgo, keySize * 8 );
/* Send data over the SSH link */
cryptGetAttribute( CRYPT_UNUSED, CRYPT_OPTION_NET_TIMEOUT, &timeout );
cryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_NET_TIMEOUT, 5 );
if( isServer )
{
/* Send a status message to the client */
status = cryptPushData( cryptSession, "Welcome to cryptlib, now go "
"away.\n", 34, &bytesCopied );
if( cryptStatusOK( status ) )
status = cryptFlushData( cryptSession );
if( cryptStatusError( status ) || bytesCopied != 34 )
{
printf( "Couldn't send data to client, status %d, line %d.\n",
status, __LINE__ );
return( status );
}
}
else
{
/* Wait a bit while data arrives */
delayThread( 2 );
/* Print the first lot of output from the server */
status = cryptPopData( cryptSession, buffer, 2048, &bytesCopied );
if( cryptStatusError( status ) )
{
printf( "Couldn't read data from server, status %d, line %d.\n",
status, __LINE__ );
return( status );
}
buffer[ bytesCopied ] = '\0';
printf( "---- Server returned %d bytes ----\n", bytesCopied );
puts( buffer );
puts( "---- End of output ----" );
/* 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( status );
}
delayThread( 3 );
status = cryptPopData( cryptSession, buffer, 2048,
&bytesCopied );
if( cryptStatusError( status ) )
{
printf( "Couldn't read data from server, status %d, line "
"%d.\n", status, __LINE__ );
return( status );
}
buffer[ bytesCopied ] = '\0';
printf( "---- Sent 'ls -l | head -25', server returned %d bytes "
"----\n", bytesCopied );
puts( buffer );
puts( "---- End of output ----" );
}
}
cryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_NET_TIMEOUT, timeout );
/* Clean up */
status = cryptDestroySession( cryptSession );
if( cryptStatusError( status ) )
{
printf( "cryptDestroySession() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
puts( isServer ? "SSH server session succeeded.\n" : \
"SSH client session succeeded.\n" );
return( TRUE );
}
int testSessionSSHv1( void )
{
return( connectSSH( CRYPT_SESSION_SSH, FALSE, FALSE, FALSE ) );
}
int testSessionSSHv2( void )
{
return( connectSSH( CRYPT_SESSION_SSH, FALSE, FALSE, TRUE ) );
}
int testSessionSSHClientCert( void )
{
return( connectSSH( CRYPT_SESSION_SSH, TRUE, FALSE, FALSE ) );
}
int testSessionSSHServer( void )
{
return( connectSSH( CRYPT_SESSION_SSH_SERVER, FALSE, FALSE, FALSE ) );
}
/* Perform a local client/server test */
#ifdef WINDOWS_THREADS
unsigned __stdcall sshServerThread( void *dummy )
{
connectSSH( CRYPT_SESSION_SSH_SERVER, FALSE, TRUE, FALSE );
_endthreadex( 0 );
return( 0 );
}
int testSessionSSHClientServer( void )
{
HANDLE hThread;
unsigned threadID;
int status;
/* Start the server and wait for it to initialise */
hThread = ( HANDLE ) _beginthreadex( NULL, 0, &sshServerThread,
NULL, 0, &threadID );
Sleep( 1000 );
/* Connect to the local server */
status = connectSSH( CRYPT_SESSION_SSH, FALSE, TRUE, FALSE );
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 );
}
#endif /* WINDOWS_THREADS */
/****************************************************************************
* *
* SSL/TLS Routines Test *
* *
****************************************************************************/
/* There are various servers running which we can use for testing, the
following remapping allows us to switch between them */
#define SSL_SERVER_NAME SSL_SERVER2_NAME
#define TLS_SERVER_NAME TLS_SERVER2_NAME
/* Establish an SSL/TLS session */
static int connectSSLTLS( const CRYPT_SESSION_TYPE sessionType,
const BOOLEAN isSSL, const BOOLEAN useClientCert,
const BOOLEAN localSession )
{
CRYPT_SESSION cryptSession;
const BOOLEAN isServer = ( sessionType == CRYPT_SESSION_SSL_SERVER ) ? \
TRUE : FALSE;
const char *serverName = isSSL ? SSL_SERVER_NAME : TLS_SERVER_NAME;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -