📄 testsess.c
字号:
}
else
{
if( localSocket )
{
/* Testing this fully requires a lot of OS-specific juggling so
unless we're running under Windows we just supply the handle
to stdin, which will return a read/write error during the
connect. This checks that the handle has been assigned
corectly without requiring a lot of OS-specific socket
handling code. Under Windows, we use a (very cut-down) set
of socket calls to set up a minimal socket. Since there's
very little error-checking done, we don't treat a failure
as fatal */
#if defined( __WINDOWS__ )
WSADATA wsaData;
if( WSAStartup( 2, &wsaData ) )
{
printf( "Couldn't initialise sockets interface, line %d.\n",
__LINE__ );
return( FALSE );
}
/* Try and negotiate a STARTTLS session. We don't treat most
types of failure as fatal since there are a great many minor
things that can go wrong that we don't want to have to handle
without writing half an MUA */
netSocket = negotiateSTARTTLS( &protocol );
if( netSocket <= 0 )
{
cryptDestroySession( cryptSession );
WSACleanup();
if( netSocket == CRYPT_OK )
{
puts( "This is a nonfatal error (a great many other "
"things can go wrong while\nnegotiating through "
"to the TLS upgrade).\n" );
return( TRUE );
}
return( FALSE );
}
/* Hand the socket to cryptlib */
status = cryptSetAttribute( cryptSession,
CRYPT_SESSINFO_NETWORKSOCKET, netSocket );
#elif defined( DDNAME_IO )
/* The fileno() function doesn't work for DDNAMEs */
status = cryptSetAttribute( cryptSession,
CRYPT_SESSINFO_NETWORKSOCKET, 0 );
#else
status = cryptSetAttribute( cryptSession,
CRYPT_SESSINFO_NETWORKSOCKET, fileno( stdin ) );
#endif /* __WINDOWS__ */
}
else
{
if( localSession )
{
if( !setLocalConnect( cryptSession, 443 ) )
return( FALSE );
}
else
status = cryptSetAttributeString( cryptSession,
CRYPT_SESSINFO_SERVER_NAME, serverName,
strlen( serverName ) );
}
if( cryptStatusOK( status ) && 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 );
}
}
}
if( cryptStatusOK( status ) && sharedKey )
{
status = cryptSetAttributeString( cryptSession,
CRYPT_SESSINFO_USERNAME, SSL_USER_NAME,
strlen( SSL_USER_NAME ) );
if( cryptStatusOK( status ) )
status = cryptSetAttributeString( cryptSession,
CRYPT_SESSINFO_PASSWORD, SSL_PASSWORD,
strlen( SSL_PASSWORD ) );
if( isServer )
{
/* If it's a server session, set an additional username/password
to test the ability of the session cache to store multiple
shared secrets */
status = cryptSetAttributeString( cryptSession,
CRYPT_SESSINFO_USERNAME, "0000", 4 );
if( cryptStatusOK( status ) )
status = cryptSetAttributeString( cryptSession,
CRYPT_SESSINFO_PASSWORD, "0000", 4 );
if( cryptStatusOK( status ) && \
cryptStatusOK( \
cryptSetAttributeString( cryptSession,
CRYPT_SESSINFO_USERNAME, "0000", 4 ) ) )
{
printf( "SVR: Addition of duplicate entry to SSL session "
"cache wasn't detected, line %d.\n", __LINE__ );
return( FALSE );
}
}
}
if( cryptStatusError( status ) )
{
if( localSocket )
{
#ifdef __WINDOWS__
closesocket( netSocket );
WSACleanup();
#else
/* Creating a socket in a portable manner is too difficult so
we've passed in a stdio handle, this should return an error
since it's not a blocking socket */
return( TRUE );
#endif /* __WINDOWS__ */
}
printf( "cryptSetAttribute/AttributeString() failed with error code "
"%d, line %d.\n", status, __LINE__ );
return( FALSE );
}
#if SSL_SERVER_NO == 5
cryptGetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,
&version );
cryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,
CRYPT_COMPLIANCELEVEL_OBLIVIOUS );
#endif /* SSL server with b0rken certs */
status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );
#if SSL_SERVER_NO == 5
cryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,
version );
#endif /* SSL server with b0rken certs */
if( isServer )
printConnectInfo( cryptSession );
if( cryptStatusError( status ) )
{
char strBuffer[ 128 ];
if( localSocket )
{
#ifdef __WINDOWS__
closesocket( netSocket );
WSACleanup();
#else
/* If we're using a dummy local socket, we'll get a R/W error at
this point since it's not connected to anything, so we
intercept it before it gets any further */
if( status == CRYPT_ERROR_READ || status == CRYPT_ERROR_WRITE )
{
cryptDestroySession( cryptSession );
return( TRUE );
}
#endif /* __WINDOWS__ */
}
sprintf( strBuffer, "%sAttempt to activate %s%s session",
isServer ? "SVR: " : "", localSession ? "local " : "",
versionStr[ version ] );
printExtError( cryptSession, strBuffer, status, __LINE__ );
cryptDestroySession( cryptSession );
if( bulkTransfer )
free( bulkBuffer );
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 );
}
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( cryptStatusOK( status ) )
status = cryptGetAttribute( cryptSession, CRYPT_SESSINFO_VERSION,
&protocolVersion );
if( cryptStatusError( status ) )
{
printf( "Couldn't query session details, status %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
printf( "%sSession is protected using algorithm %d with a %d bit key,\n"
" protocol version %d.\n", isServer ? "SVR: " : "",
cryptAlgo, keySize * 8, protocolVersion );
if( !isServer && !sharedKey )
{
BYTE fingerPrint[ CRYPT_MAX_HASHSIZE ];
int length, i;
status = cryptGetAttributeString( cryptSession,
CRYPT_SESSINFO_SERVER_FINGERPRINT,
fingerPrint, &length );
if( cryptStatusError( status ) )
{
printf( "cryptGetAttributeString() failed with error code "
"%d, line %d.\n", status, __LINE__ );
return( FALSE );
}
printf( "Server key fingerprint =" );
for( i = 0; i < length; i++ )
printf( " %02X", fingerPrint[ i ] );
puts( "." );
}
if( ( !localSession && !isServer ) ||
( localSession && isServer && useClientCert ) )
{
CRYPT_CERTIFICATE cryptCertificate;
status = cryptGetAttribute( cryptSession, CRYPT_SESSINFO_RESPONSE,
&cryptCertificate );
if( cryptStatusError( status ) )
{
printf( "%sCouldn't get %s certificate, status %d, line %d.\n",
isServer ? "SVR: " : "", isServer ? "client" : "server",
status, __LINE__ );
return( FALSE );
}
puts( localSession ? "SVR: Client cert details are:" : \
"Server cert details are:" );
printCertChainInfo( cryptCertificate );
cryptDestroyCert( cryptCertificate );
}
if( isServer && sharedKey )
{
int length;
status = cryptGetAttributeString( cryptSession,
CRYPT_SESSINFO_USERNAME, buffer,
&length );
if( cryptStatusError( status ) )
{
printf( "SVR: Couldn't read client user name, status %d, line "
"%d.\n", status, __LINE__ );
return( FALSE );
}
buffer[ length ] = '\0';
printf( "SVR: Client user name = '%s'.\n", buffer );
}
/* Send data over the SSL/TLS link */
#if SSL_SERVER_NO == 3
/* This server has a large amount of data on it, used to test high-
latency bulk transfers, so we set a larger timeout for the read */
status = cryptSetAttribute( cryptSession, CRYPT_OPTION_NET_TIMEOUT, 15 );
#else
status = cryptSetAttribute( cryptSession, CRYPT_OPTION_NET_TIMEOUT, 5 );
#endif /* SSL_SERVER_NO == 3 */
if( bulkTransfer )
{
if( isServer )
{
status = cryptPushData( cryptSession, bulkBuffer,
BULKDATA_BUFFER_SIZE, &bytesCopied );
if( cryptStatusOK( status ) )
status = cryptFlushData( cryptSession );
if( cryptStatusError( status ) || \
bytesCopied != BULKDATA_BUFFER_SIZE )
{
printf( "SVR: Couldn't send bulk data to client, status %d, "
"line %d.\n", status, __LINE__ );
return( FALSE );
}
}
else
{
long byteCount = 0;
do
{
status = cryptPopData( cryptSession, bulkBuffer + byteCount,
BULKDATA_BUFFER_SIZE - byteCount,
&bytesCopied );
byteCount += bytesCopied;
}
while( cryptStatusOK( status ) && \
byteCount < BULKDATA_BUFFER_SIZE );
if( cryptStatusError( status ) )
{
printf( "Couldn't read bulk data from server, status %d, "
"line %d.\n", status, __LINE__ );
return( FALSE );
}
if( byteCount != BULKDATA_BUFFER_SIZE )
{
printf( "Only received %ld of %ld bytes.\n", byteCount,
BULKDATA_BUFFER_SIZE );
return( FALSE );
}
if( !handleBulkBuffer( bulkBuffer, FALSE ) )
{
puts( "Received buffer contents don't match sent buffer "
"contents." );
return( FALSE );
}
}
free( bulkBuffer );
}
else
/* It's a standard transfer, send/receive and HTTP request/response.
We clean up if we exit due to an error, if we're running a local
loopback test the client and server threads can occasionally lose
sync, which isn't a fatal error but can turn into a
CRYPT_ERROR_INCOMPLETE once all the tests are finished */
if( isServer )
{
#if defined( __MVS__ ) || defined( __VMCMS__ )
#pragma convlit( resume )
#endif /* EBCDIC systems */
const char serverReply[] = \
"HTTP/1.0 200 OK\n"
"Date: Fri, 7 June 1999 20:02:07 GMT\n"
"Server: cryptlib SSL/TLS test\n"
"Content-Type: text/html\n"
"\n"
"<!DOCTYPE HTML SYSTEM \"html.dtd\">\n"
"<html>\n"
"<head>\n"
"<title>cryptlib SSL/TLS test page</title>\n"
"<body>\n"
"Test message from the cryptlib SSL/TLS server<p>\n"
"</body>\n"
"</html>\n";
#if defined( __MVS__ ) || defined( __VMCMS__ )
#pragma convlit( suspend )
#endif /* EBCDIC systems */
/* Print the text of the request from the client */
status = cryptPopData( cryptSession, buffer, FILEBUFFER_SIZE,
&bytesCopied );
if( cryptStatusError( status ) )
{
printExtError( cryptSession, "SVR: Attempt to read data "
"from client", status, __LINE__ );
cryptDestroySession( cryptSession );
return( FALSE );
}
buffer[ bytesCopied ] = '\0';
#if defined( __MVS__ ) || defined( __VMCMS__ )
asciiToEbcdic( buffer, bytesCopied );
#endif /* EBCDIC systems */
printf( "---- Client sent %d bytes ----\n", bytesCopied );
puts( buffer );
puts( "---- End of output ----" );
/* Send a reply */
status = cryptPushData( cryptSession, serverReply,
sizeof( serverReply ) - 1, &bytesCopied );
if( cryptStatusOK( status ) )
status = cryptFlushData( cryptSession );
if( cryptStatusError( status ) || \
bytesCopied != sizeof( serverReply ) - 1 )
{
printExtError( cryptSession, "Attempt to send data to "
"client", status, __LINE__ );
cryptDestroySession( cryptSession );
return( FALSE );
}
}
else
{
char fetchString[ 128 ];
int fetchStringLen;
/* Send a fetch request to the server */
if( localSocket )
{
if( protocol == PROTOCOL_SMTP )
strcpy( fetchString, "EHLO foo.bar.com\r\n" );
else
if( protocol == PROTOCOL_POP )
strcpy( fetchString, "CAPA\r\n" );
else
if( protocol == PROTOCOL_IMAP )
strcpy( fetchString, "a003 CAPABILITY\r\n" );
else
strcpy( fetchString, "USER test\r\n" );
}
else
sprintf( fetchString, "GET %s HTTP/1.0\r\n\r\n",
sslInfo[ SSL_SERVER_NO ].path );
fetchStringLen = strlen( fetchString );
#if defined( __MVS__ ) || defined( __VMCMS__ )
ebcdicToAscii( fetchString, fetchStringLen );
#endif /* EBCDIC systems */
status = cryptPushData( cryptSession, fetchString,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -