⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 testsess.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 5 页
字号:
/* If we're using local sockets, we have to pull in the winsock defines */

#ifdef __WINDOWS__
  #include <winsock.h>
#endif /* __WINDOWS__ */

/* There are various servers running that we can use for testing, the
   following remapping allows us to switch between them.  Notes:

	Server 1: Local loopback.
	Server 2: Generic test server.
	Server 3: ~40K data returned.
	Server 4: Sends zero-length blocks (actually a POP server).
	Server 5: Requires CRYPT_OPTION_CERT_COMPLIANCELEVEL = 
			  CRYPT_COMPLIANCELEVEL_OBLIVIOUS due to b0rken certs.
	Server 6: (Causes MAC failure during handshake when called from PMail, 
			   works OK when called here).
	Server 7: Can only do crippled crypto (not even conventional crippled 
			  crypto but RC4-56) and instead of sending an alert for this 
			  just drops the connection (this may be caused by the NetApp
			  NetCache it's using).  This site is also running an Apache 
			  server that claims it's optimised for MSIE, and that the page 
			  won't work properly for non-MSIE browsers.  The mind boggles...
	Server 8: Server ("Hitachi Web Server 02-00") can only do SSL, when 
			  cryptlib is set to perform a TLS handshake (i.e. cryptlib is 
			  told to expect TLS but falls back to SSL), goes through the 
			  full handshake, then returns a handshake failure alert.  The
			  same occurs for other apps (e.g. MSIE) when TLS is enabled.
	Server 9: Buggy older IIS that can only do crippled crypto and drops
			  the connection as soon as it sees the client hello advertising 
			  strong crypto only.
	Server 10:Newer IIS (certificate is actually for akamai.net, so the SSL
			  may not be Microsoft's at all).
	Server 11:IBM (Websphere?).
	Server 12:Server is running TLS with SSL disabled, drops connection when
			  it sees an SSL handshake.  MSIE in its default config (TLS
			  disabled) can't connect to this server */

#define SSL_SERVER_NO	2
#define TLS_SERVER_NO	2
#define TLS11_SERVER_NO	2

static const struct {
	const char *name, *path;
	} sslInfo[] = {
	{ NULL, NULL },
	/*  1 */ { "localhost", "/" },
	/*  2 */ { "https://www.amazon.com", "/" },
	/*  3 */ { "https://www.cs.berkeley.edu", "/~daw/people/crypto.html" },
	/*  4 */ { "pop.web.de:995", "/" },
	/*  5 */ { "imap4-gw.uni-regensburg.de:993", "/" },
	/*  6 */ { "securepop.t-online.de:995", "/" },
	/*  7 */ { "https://homedir.wlv.ac.uk", "/" },
	/*  8 */ { "https://www.horaso.com:20443", "/" },
	/*  9 */ { "https://homedir.wlv.ac.uk", "/" },
	/* 10 */ { "https://www.microsoft.com", "/" },
	/* 11 */ { "https://alphaworks.ibm.com/", "/" },
	/* 12 */ { "https://webmount.turbulent.ca/", "/" },
	{ NULL, NULL }
	};

/* Various servers used for STARTTLS/STLS/AUTH TLS testing.  Notes:

	Server 1: SMTP: mailbox.ucsd.edu:25 (132.239.1.57) requires a client cert.
	Server 2: POP: pop.cae.wisc.edu:1110 (144.92.240.11) OK
	Server 3: SMTP: smtpauth.cae.wisc.edu:25 (144.92.12.93) requires a client 
			  cert 
	Server 4: SMTP: send.columbia.edu:25 (128.59.59.23) returns invalid cert 
			  (lower compliance level to fix) 
	Server 5: POP: pop3.myrealbox.com:110 (192.108.102.201) returns invalid 
			  cert (lower compliance level to fix) 
	Server 6: Encrypted POP: securepop.t-online.de:995 (194.25.134.46) direct 
			  SSL connect 
	Server 7: FTP: ftp.windsorchapel.net:21 (68.38.166.195) sends redundant 
			  client cert request with invalid length

			  To test FTP with SSL/TLS manually: Disable auto-login with FTP, 
			  then send RFC 2389 FEAT command to check security facilities.  
			  If this is supported, one of the responses will be either 
			  AUTH SSL or AUTH TLS, use this to turn on SSL/TLS.  If FEAT 
			  isn't supported, AUTH TLS should usually work:

				ftp -n ftp.windsorchapel.net
				quote feat
				quote auth ssl

			  or just:

				telnet ftp.windsorchapel.net 21
				auth ssl */

#define STARTTLS_SERVER_NO	2

typedef enum { PROTOCOL_NONE, PROTOCOL_SMTP, PROTOCOL_POP, 
			   PROTOCOL_IMAP, PROTOCOL_POP_DIRECT, PROTOCOL_FTP 
			 } PROTOCOL_TYPE;

static const struct {
	const char *name;
	const int port;
	PROTOCOL_TYPE protocol;
	} starttlsInfo[] = {
	{ NULL, 0 },
	{ "132.239.1.57", 25, PROTOCOL_SMTP },
	{ "144.92.240.11", 1110, PROTOCOL_POP },
	{ "144.92.12.93", 25, PROTOCOL_SMTP },
	{ "128.59.59.23", 25, PROTOCOL_SMTP },
	{ "192.108.102.201", 110, PROTOCOL_POP },
	{ "194.25.134.46", 995, PROTOCOL_POP_DIRECT },
	{ "68.38.166.195", 21, PROTOCOL_FTP },
	{ NULL, 0 }
	};

/* Large buffer size to test bulk data transfer capability for secure
   sessions */

#define BULKDATA_BUFFER_SIZE	300000L

static int checksumData( const void *data, const int dataLength )
	{
	const BYTE *dataPtr = data;
	int sum1 = 0, sum2 = 0, i;

	/* Calculate a 16-bit Fletcher-like checksum of the data (it doesn't
	   really matter if it's not exactly right, as long as the behaviour is 
	   the same for all data) */
	for( i = 0; i < dataLength; i++ )
		{
		sum1 += dataPtr[ i ];
		sum2 += sum1;
		}

	return( sum2 & 0xFFFF );
	}

static BOOLEAN handleBulkBuffer( BYTE *buffer, const BOOLEAN isInit )
	{
	int checkSum, i;

	/* If we're initialising the buffer, fill it with [0...256]* followed by
	   a checksum of the buffer contents */
	if( isInit )
		{
		for( i = 0; i < BULKDATA_BUFFER_SIZE - 2; i++ )
			buffer[ i ] = i & 0xFF;
		checkSum = checksumData( buffer, BULKDATA_BUFFER_SIZE - 2 );
		buffer[ BULKDATA_BUFFER_SIZE - 2 ] = ( checkSum >> 8 ) & 0xFF;
		buffer[ BULKDATA_BUFFER_SIZE - 1 ] = checkSum & 0xFF;

		return( TRUE );
		}

	/* We're being sent an initialised buffer, make sure that it's OK */
	for( i = 0; i < BULKDATA_BUFFER_SIZE - 2; i++ )
		if( buffer[ i ] != ( i & 0xFF )	)
			return( FALSE );
	checkSum = checksumData( buffer, BULKDATA_BUFFER_SIZE - 2 );
	if( buffer[ BULKDATA_BUFFER_SIZE - 2 ] != ( ( checkSum >> 8 ) & 0xFF ) || \
		buffer[ BULKDATA_BUFFER_SIZE - 1 ] != ( checkSum & 0xFF ) )
		return( FALSE );

	return( TRUE );
	}

/* Negotiate through a STARTTLS */

#ifdef __WINDOWS__

static int readLine( SOCKET netSocket, char *buffer )
	{
	int bufPos = 0, status = CRYPT_OK;

	for( bufPos = 0; \
		 status >= 0 && bufPos < 1024 && \
			( bufPos < 1 || buffer[ bufPos -1 ] != '\n' ); 
		 bufPos++ )
		status = recv( netSocket, buffer + bufPos, 1, 0 );
	while( bufPos > 1 && isspace( buffer[ bufPos - 1 ] ) )
		bufPos--;
	if( bufPos >= 3 )
		{
		while( bufPos > 1 && isspace( buffer[ bufPos - 1 ] ) )
			bufPos--;
		buffer[ min( bufPos, 56 ) ] = '\0';
		}
	return( bufPos );
	}

static int negotiateSTARTTLS( int *protocol )
	{
	SOCKET netSocket;
	struct sockaddr_in serverAddr;
	char buffer[ 1024 ];
	int bufPos, status;

	puts( "Negotiating SMTP/POP/IMAP/FTP session through to TLS start..." );
	*protocol = starttlsInfo[ STARTTLS_SERVER_NO ].protocol;

	/* Connect to a generally-available server to test STARTTLS/STLS 
	   functionality */
	memset( &serverAddr, 0, sizeof( struct sockaddr_in ) );
	serverAddr.sin_family = AF_INET;
	serverAddr.sin_port = htons( ( u_short ) starttlsInfo[ STARTTLS_SERVER_NO ].port );
	serverAddr.sin_addr.s_addr = inet_addr( starttlsInfo[ STARTTLS_SERVER_NO ].name );
	netSocket = socket( PF_INET, SOCK_STREAM, 0 );
	if( netSocket == INVALID_SOCKET )
		{
		printf( "Couldn't create socket, line %d.\n", __LINE__ );
		return( CRYPT_ERROR_FAILED );
		}
	status = connect( netSocket, ( struct sockaddr * ) &serverAddr,
					  sizeof( struct sockaddr_in ) );
	if( status == SOCKET_ERROR )
		{
		closesocket( netSocket );
		printf( "Couldn't connect socket, line %d.\n", __LINE__ );
		return( CRYPT_OK );
		}

	/* If it's a direct connect, there's nothing left to do */
	if( *protocol == PROTOCOL_POP_DIRECT )
		{
		*protocol = PROTOCOL_POP;
		return( netSocket );
		}

	/* Perform (very crude) SMTP/POP/IMAP negotiation to switch to TLS */
	bufPos = readLine( netSocket, buffer );
	if( bufPos < 3 || ( strncmp( buffer, "220", 3 ) && \
						strncmp( buffer, "+OK", 3 ) && \
						strncmp( buffer, "OK", 2 ) ) )
		{
		closesocket( netSocket );
		printf( "Got response '%s', line %d.\n", buffer, __LINE__ );
		return( CRYPT_OK );
		}
	printf( "  Server said: '%s'\n", buffer );
	assert( ( *protocol == PROTOCOL_SMTP && !strncmp( buffer, "220", 3 ) ) || \
			( *protocol == PROTOCOL_POP && !strncmp( buffer, "+OK", 3 ) ) || \
			( *protocol == PROTOCOL_IMAP && !strncmp( buffer, "OK", 2 ) ) || \
			( *protocol == PROTOCOL_FTP && !strncmp( buffer, "220", 3 ) ) || \
			*protocol == PROTOCOL_NONE );
	switch( *protocol )
		{
		case PROTOCOL_POP:
			send( netSocket, "STLS\r\n", 6, 0 );
			puts( "  We said: 'STLS'" );
			break;

		case PROTOCOL_IMAP:
			/* It's possible for some servers that we may need to explicitly 
			   send a CAPABILITY command first to enable STARTTLS:
				a001 CAPABILITY
				> CAPABILITY IMAP4rev1 STARTTLS LOGINDISABLED
				> OK CAPABILITY completed */
			send( netSocket, "a001 STARTTLS\r\n", 15, 0 );
			puts( "  We said: 'STARTTLS'" );
			break;

		case PROTOCOL_SMTP:
			send( netSocket, "EHLO foo.bar.com\r\n", 18, 0 );
			puts( "  We said: 'EHLO foo.bar.com'" );
			do
				{
				bufPos = readLine( netSocket, buffer );
				if( bufPos < 3 || strncmp( buffer, "250", 3 ) )
					{
					closesocket( netSocket );
					printf( "Got response '%s', line %d.\n", buffer, __LINE__ );
					return( CRYPT_OK );
					}
				printf( "  Server said: '%s'\n", buffer );
				}
			while( !strncmp( buffer, "250-", 4 ) );
			send( netSocket, "STARTTLS\r\n", 10, 0 );
			puts( "  We said: 'STARTTLS'" );
			break;

		case PROTOCOL_FTP:
			send( netSocket, "AUTH TLS\r\n", 10, 0 );
			puts( "  We said: 'AUTH TLS'" );
			break;

		default:
			assert( FALSE );
		}
	bufPos = readLine( netSocket, buffer );
	if( bufPos < 3 || ( strncmp( buffer, "220", 3 ) && \
						strncmp( buffer, "+OK", 3 ) && \
						strncmp( buffer, "OK", 2 ) && \
						strncmp( buffer, "234", 3 ) ) )
		{
		printf( "Got response '%s', line %d.\n", buffer, __LINE__ );
		return( CRYPT_OK );
		}
	printf( "  Server said: '%s'\n", buffer );
	return( netSocket );
	}
#endif /* __WINDOWS__ */

/* Establish an SSL/TLS session */

static int connectSSLTLS( const CRYPT_SESSION_TYPE sessionType,
						  const int version, const BOOLEAN useClientCert,
						  const BOOLEAN localSession,
						  const BOOLEAN bulkTransfer, 
						  const BOOLEAN localSocket,
						  const BOOLEAN sharedKey )
	{
	CRYPT_SESSION cryptSession;
	const BOOLEAN isServer = ( sessionType == CRYPT_SESSION_SSL_SERVER ) ? \
							   TRUE : FALSE;
	const char *versionStr[] = { "SSL", "TLS", "TLS 1.1" };
	const char *serverName = ( version == 0 ) ? \
								sslInfo[ SSL_SERVER_NO ].name : \
							 ( version == 1 ) ? \
								sslInfo[ TLS_SERVER_NO ].name : \
								sslInfo[ TLS11_SERVER_NO ].name;
	BYTE *bulkBuffer;
	char buffer[ FILEBUFFER_SIZE ];
#ifdef __WINDOWS__
	int netSocket;
#endif /* __WINDOWS__ */
	int cryptAlgo, keySize, bytesCopied, protocolVersion;
	int protocol = PROTOCOL_SMTP, status;

	printf( "%sTesting %s%s session%s...\n", isServer ? "SVR: " : "",
			localSession ? "local " : "", versionStr[ version ],
			useClientCert ? " with client certs" : \
			localSocket ? " with local socket" : \
			bulkTransfer ? " for bulk data transfer" : \
			sharedKey ? " with shared key" : "" );
	if( !isServer && !localSession )
		printf( "  Remote host: %s.\n", serverName );

	/* Create the SSL/TLS session */
	status = cryptCreateSession( &cryptSession, CRYPT_UNUSED, sessionType );
	if( status == CRYPT_ERROR_PARAM3 )	/* SSL/TLS 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 );
		}
	status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_VERSION, version );
	if( cryptStatusError( status ) )
		{
		printf( "cryptSetAttribute() failed with error code %d, line %d.\n",
				status, __LINE__ );
		return( FALSE );
		}

	/* If we're doing a bulk data transfer, set up the necessary buffer */
	if( bulkTransfer )
		{
		if( ( bulkBuffer = malloc( BULKDATA_BUFFER_SIZE ) ) == NULL )
			{
			printf( "Failed to allocated %ld bytes, line %d.\n",
					BULKDATA_BUFFER_SIZE, __LINE__ );
			return( FALSE );
			}
		if( isServer )
			handleBulkBuffer( bulkBuffer, TRUE );
		}

	/* Set up the server information and activate the session */
	if( isServer )
		{
		CRYPT_CONTEXT privateKey;

		if( !setLocalConnect( cryptSession, 443 ) )
			return( FALSE );
		status = getPrivateKey( &privateKey, SERVER_PRIVKEY_FILE,
								USER_PRIVKEY_LABEL, 
								TEST_PRIVKEY_PASSWORD );
		if( cryptStatusOK( status ) )
			{
			status = cryptSetAttribute( cryptSession,
										CRYPT_SESSINFO_PRIVATEKEY, 
										privateKey );
			cryptDestroyContext( privateKey );
			}
		if( cryptStatusOK( status ) && useClientCert )
			{
			CRYPT_KEYSET cryptKeyset;

			status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED,
								DATABASE_KEYSET_TYPE, DATABASE_KEYSET_NAME,
								CRYPT_KEYOPT_READONLY );
			if( cryptStatusError( status ) )
				{
				printf( "SVR: Client cert keyset open failed with error code "
						"%d, line %d.\n", status, __LINE__ );
				return( FALSE );
				}
			status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_KEYSET,
										cryptKeyset );
			cryptKeysetClose( cryptKeyset );
			}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -