📄 ssl.c
字号:
#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__ && !_WIN32_WCE */
}
if( sessionID != CRYPT_UNUSED )
printf( "%02d: ", sessionID );
sprintf( strBuffer, "%sAttempt to activate %s%s session",
isServer ? "SVR: " : "", localSession ? "local " : "",
versionStr[ version ] );
printExtError( cryptSession, strBuffer, status, __LINE__ );
cryptDestroySession( cryptSession );
if( testType == SSL_TEST_BULKTRANSER )
free( bulkBuffer );
if( !isServer && \
( status == CRYPT_ERROR_OPEN || status == CRYPT_ERROR_NOTFOUND ) )
{
/* 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( testType == SSL_TEST_PSK_CLIONLY || \
testType == SSL_TEST_PSK_SVRONLY )
{
/* The CLIONLY/SVRONLY test is supposed to fail, so if this
happens then the overall test has succeeded */
puts( " (This test checks error handling, so the failure "
"response is correct).\n" );
return( TRUE );
}
return( FALSE );
}
else
/* The CLIONLY/SVRONLY test is supposed to fail, if this doesn't
happen then there's a problem */
if( testType == SSL_TEST_PSK_CLIONLY || \
testType == SSL_TEST_PSK_SVRONLY )
{
printf( "%sTLS-PSK handshake without password should have "
"failed but succeeded,\nline %d.\n",
isServer ? "SVR: " : "", __LINE__ );
return( FALSE );
}
/* Report the session security info */
if( testType != SSL_TEST_MULTITHREAD && \
!printSecurityInfo( cryptSession, isServer,
( testType != SSL_TEST_PSK ) ) )
return( FALSE );
if( ( !localSession && !isServer ) ||
( localSession && isServer && testType == SSL_TEST_CLIENTCERT ) )
{
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 && testType == SSL_TEST_PSK )
{
C_CHR userNameBuffer[ CRYPT_MAX_TEXTSIZE + 1 ];
int length;
status = cryptGetAttributeString( cryptSession,
CRYPT_SESSINFO_USERNAME,
userNameBuffer, &length );
if( cryptStatusError( status ) )
{
printf( "SVR: Couldn't read client user name, status %d, line "
"%d.\n", status, __LINE__ );
return( FALSE );
}
#ifdef UNICODE_STRINGS
userNameBuffer[ length / sizeof( wchar_t ) ] = TEXT( '\0' );
printf( "SVR: Client user name = '%S'.\n", userNameBuffer );
#else
userNameBuffer[ length ] = '\0';
printf( "SVR: Client user name = '%s'.\n", userNameBuffer );
#endif /* UNICODE_STRINGS */
}
/* Send data over the SSL/TLS link. If we're doing a bulk transfer
we use fully asynchronous I/O to verify the timeout handling in
the session code */
#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_READTIMEOUT,
15 );
#else
status = cryptSetAttribute( cryptSession, CRYPT_OPTION_NET_READTIMEOUT,
( testType == SSL_TEST_BULKTRANSER ) ? 0 : 5 );
#endif /* SSL_SERVER_NO == 3 */
if( testType == SSL_TEST_BULKTRANSER )
{
if( isServer )
{
long byteCount = 0;
do
{
status = cryptPushData( cryptSession, bulkBuffer + byteCount,
BULKDATA_BUFFER_SIZE - byteCount,
&bytesCopied );
byteCount += bytesCopied;
}
while( ( cryptStatusOK( status ) || \
status == CRYPT_ERROR_TIMEOUT ) && \
byteCount < BULKDATA_BUFFER_SIZE );
if( cryptStatusError( status ) )
{
printExtError( cryptSession,
"SVR: Send of bulk data to client", status,
__LINE__ );
return( FALSE );
}
status = cryptFlushData( cryptSession );
if( cryptStatusError( status ) )
{
printExtError( cryptSession,
"SVR: Flush of bulk data to client", status,
__LINE__ );
return( FALSE );
}
if( byteCount != BULKDATA_BUFFER_SIZE )
{
printf( "Only sent %ld of %ld bytes, line %d.\n", byteCount,
BULKDATA_BUFFER_SIZE, __LINE__ );
return( FALSE );
}
}
else
{
long byteCount = 0;
do
{
status = cryptPopData( cryptSession, bulkBuffer + byteCount,
BULKDATA_BUFFER_SIZE - byteCount,
&bytesCopied );
byteCount += bytesCopied;
}
while( ( cryptStatusOK( status ) || \
status == CRYPT_ERROR_TIMEOUT ) && \
byteCount < BULKDATA_BUFFER_SIZE );
if( cryptStatusError( status ) )
{
char strBuffer[ 256 ];
sprintf( strBuffer, "Read of bulk data from server aborted "
"after %ld of %ld bytes were read\n(last "
"read = %d bytes), transfer",
byteCount, BULKDATA_BUFFER_SIZE,
bytesCopied );
printExtError( cryptSession, strBuffer, status, __LINE__ );
return( FALSE );
}
if( byteCount != BULKDATA_BUFFER_SIZE )
{
printf( "Only received %ld of %ld bytes, line %d.\n",
byteCount, BULKDATA_BUFFER_SIZE, __LINE__ );
return( FALSE );
}
if( !handleBulkBuffer( bulkBuffer, FALSE ) )
{
printf( "Received buffer contents don't match sent buffer "
"contents, line %d.", __LINE__ );
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 /* IBM big iron */
#if defined( __ILEC400__ )
#pragma convert( 819 )
#endif /* IBM medium iron */
const char serverReply[] = \
"HTTP/1.0 200 OK\n"
"Date: Fri, 7 June 2005 20:02:07 GMT\n"
"Server: cryptlib SSL/TLS test\n"
"Content-Type: text/html\n"
"Connection: Close\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 /* IBM big iron */
#if defined( __ILEC400__ )
#pragma convert( 0 )
#endif /* IBM medium iron */
/* 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 */
if( testType != SSL_TEST_MULTITHREAD )
{
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 );
}
/* Wait for the data to be flushed through to the client before
we close the session */
delayThread( 1 );
}
else
{
char fetchString[ 128 ];
int fetchStringLen;
/* Send a fetch request to the server */
if( testType == SSL_TEST_STARTTLS )
{
switch( protocol )
{
case PROTOCOL_SMTP:
strcpy( fetchString, "EHLO foo.bar.com\r\n" );
break;
case PROTOCOL_POP:
strcpy( fetchString, "CAPA\r\n" );
break;
case PROTOCOL_IMAP:
strcpy( fetchString, "a003 CAPABILITY\r\n" );
break;
default:
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,
fetchStringLen, &bytesCopied );
if( cryptStatusOK( status ) )
status = cryptFlushData( cryptSession );
if( cryptStatusError( status ) || bytesCopied != fetchStringLen )
{
printExtError( cryptSession, "Attempt to send data to "
"server", status, __LINE__ );
cryptDestroySession( cryptSession );
return( FALSE );
}
/* Print the text of the reply from the server */
status = cryptPopData( cryptSession, buffer, FILEBUFFER_SIZE,
&bytesCopied );
if( cryptStatusError( status ) )
{
printExtError( cryptSession, "Attempt to read data from "
"server", status, __LINE__ );
cryptDestroySession( cryptSession );
return( FALSE );
}
if( bytesCopied == 0 )
{
/* We've set a 5s timeout, we should get at least some
data */
puts( "Server returned no data in response to our request." );
cryptDestroySession( cryptSession );
return( FALSE );
}
buffer[ min( bytesCopied, 4096 ) ] = '\0';
#if defined( __MVS__ ) || defined( __VMCMS__ )
asciiToEbcdic( buffer, bytesCopied );
#endif /* EBCDIC systems */
if( testType != SSL_TEST_MULTITHREAD )
{
printf( "---- Server sent %d bytes ----\n", bytesCopied );
puts( buffer );
if( bytesCopied > 4096 )
printf( " (Further %d bytes data omitted)\n",
bytesCopied - 4096 );
puts( "---- End of output ----" );
}
#if SSL_SERVER_NO == 3
/* If we're reading a lot of data, more may have arrived in the
meantime */
status = cryptPopData( cryptSession, buffer, FILEBUFFER_SIZE,
&bytesCopied );
if( cryptStatusError( status ) )
{
if( status == CRYPT_ERROR_READ )
/* Since this is HTTP, the other side can close the
connection with no further warning, even though SSL
says you shouldn't really do this */
puts( "Remote system closed connection." );
else
{
printExtError( cryptSession, "Attempt to read data from "
"server", status, __LINE__ );
cryptDestroySession( cryptSession );
return( FALSE );
}
}
else
{
buffer[ bytesCopied ] = '\0';
#if defined( __MVS__ ) || defined( __VMCMS__ )
asciiToEbcdic( buffer, bytesCopied );
#endif /* EBCDIC systems */
if( testType != SSL_TEST_MULTITHREAD )
{
printf( "---- Server sent further %d bytes ----\n",
bytesCopied );
puts( buffer );
puts( "---- End of output ----" );
}
}
#endif /* SSL_SERVER_NO == 3 */
/* If it's a chatty protocol, exchange some more pleasantries */
if( testType == SSL_TEST_STARTTLS )
{
if( protocol == PROTOCOL_SMTP )
strcpy( fetchString, "QUIT\r\n" );
else
if( protocol == PROTOCOL_POP )
strcpy( fetchString, "USER test\r\n" );
else
if( protocol == PROTOCOL_IMAP )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -