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

📄 ssl.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 4 页
字号:

		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__ && !_WIN32_WCE */

/* Establish an SSL/TLS session */

static int connectSSLTLS( const CRYPT_SESSION_TYPE sessionType,
						  const SSL_TEST_TYPE testType, const int version,
						  const int sessionID, const BOOLEAN localSession )
	{
	CRYPT_SESSION cryptSession;
	const BOOLEAN isServer = ( sessionType == CRYPT_SESSION_SSL_SERVER ) ? \
							   TRUE : FALSE;
	const char *versionStr[] = { "SSL", "TLS", "TLS 1.1", "TLS 1.2" };
	const C_STR serverName = ( testType == SSL_TEST_STARTTLS ) ? \
								starttlsInfo[ STARTTLS_SERVER_NO ].name : \
							 ( version == 0 ) ? \
								sslInfo[ SSL_SERVER_NO ].name : \
							 ( version == 1 ) ? \
								sslInfo[ TLS_SERVER_NO ].name : \
							 ( version == 2 ) ? \
								sslInfo[ TLS11_SERVER_NO ].name : \
								sslInfo[ TLS12_SERVER_NO ].name;
	BYTE *bulkBuffer = NULL;	/* Needed for bogus uninit-value warnings */
	char buffer[ FILEBUFFER_SIZE ];
#if defined( __WINDOWS__ ) && !defined( _WIN32_WCE )
	int netSocket;
#endif /* __WINDOWS__ && !_WIN32_WCE */
	int bytesCopied, protocol = PROTOCOL_SMTP, status;

	/* If this is a local session, synchronise the client and server */
	if( localSession )
		{
		if( isServer )
			{
			/* Acquire the init mutex */
			acquireMutex();
			}
		else
			{
			/* We're the client Wait for the server to finish initialising */
			if( waitMutex() == CRYPT_ERROR_TIMEOUT )
				{
				printf( "Timed out waiting for server to initialise, "
						"line %d.\n", __LINE__ );
				return( FALSE );
				}
			}
		}

	/* If this is the dual-thread server test and we're the second server 
	   thread, skip the portions that have already been handled by the first 
	   thread */
#ifdef WINDOWS_THREADS
	if( isServer && testType == SSL_TEST_DUALTHREAD && sessionID == 0 )
		goto dualThreadContinue;
#endif /* WINDOWS_THREADS */

	if( sessionID != CRYPT_UNUSED )
		printf( "%02d: ", sessionID );
	printf( "%sTesting %s%s session%s...\n", isServer ? "SVR: " : "",
			localSession ? "local " : "", versionStr[ version ],
			( testType == SSL_TEST_CLIENTCERT ) ? " with client certs" : \
			( testType == SSL_TEST_STARTTLS ) ? " with local socket" : \
			( testType == SSL_TEST_BULKTRANSER ) ? " for bulk data transfer" : \
			( testType == SSL_TEST_PSK || \
			  testType == SSL_TEST_PSK_CLIONLY || \
			  testType == SSL_TEST_PSK_SVRONLY ) ? " 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( testType == SSL_TEST_BULKTRANSER )
		{
		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 );
		if( testType != SSL_TEST_PSK && \
			testType != SSL_TEST_PSK_SVRONLY && \
			testType != SSL_TEST_DUALTHREAD )
			{
			/* We don't add a private key if we're doing TLS-PSK, to test
			   TLS-PSK's abiltiy to work without a PKC */
			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 ) && testType == SSL_TEST_CLIENTCERT )
			{
			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 );
			}
		}
	else
		{
		if( testType == SSL_TEST_STARTTLS )
			{
			/* 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__ ) && \
	!( defined( __WIN16__ ) || defined( _WIN32_WCE ) )
			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 );
#elif defined( __WIN16__ ) || defined( _WIN32_WCE )
			status = cryptSetAttribute( cryptSession,
							CRYPT_SESSINFO_NETWORKSOCKET, 1 );
#else
			status = cryptSetAttribute( cryptSession,
							CRYPT_SESSINFO_NETWORKSOCKET, fileno( stdin ) );
#endif /* OS-specific local socket handling */
			}
		else
			{
			if( localSession )
				{
				if( !setLocalConnect( cryptSession, 443 ) )
					return( FALSE );
				}
			else
				status = cryptSetAttributeString( cryptSession,
								CRYPT_SESSINFO_SERVER_NAME, serverName,
								paramStrlen( serverName ) );
			}
		if( cryptStatusOK( status ) && testType == SSL_TEST_CLIENTCERT )
			{
			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 0	/* Optional proxy for net access */
		status = cryptSetAttributeString( CRYPT_UNUSED,
								CRYPT_OPTION_NET_HTTP_PROXY, "[Autodetect]",
								12 );
#endif /* 0 */
		}
	if( cryptStatusOK( status ) && \
		( testType == SSL_TEST_PSK || \
		  ( isServer && testType == SSL_TEST_PSK_SVRONLY ) || \
		  ( !isServer && testType == SSL_TEST_PSK_CLIONLY ) ) )
		{
		/* If we're testing the no-PSK handling, only the server is
		   expecting TLS-PSK, so the client isn't supplied with a
		   password */
		if( cryptStatusOK( status ) && isServer && testType == SSL_TEST_PSK )
			{
			/* If we're testing PSK, add several preceding usernames and
			   passwords */
			cryptSetAttributeString( cryptSession,
								CRYPT_SESSINFO_USERNAME, TEXT( "before1" ),
								paramStrlen( TEXT( "before1" ) ) );
			cryptSetAttributeString( cryptSession,
								CRYPT_SESSINFO_PASSWORD, TEXT( "before1" ),
								paramStrlen( TEXT( "before1" ) ) );
			cryptSetAttributeString( cryptSession,
								CRYPT_SESSINFO_USERNAME, TEXT( "before2" ),
								paramStrlen( TEXT( "before2" ) ) );
			cryptSetAttributeString( cryptSession,
								CRYPT_SESSINFO_PASSWORD, TEXT( "before2" ),
								paramStrlen( TEXT( "before2" ) ) );
			}
		status = cryptSetAttributeString( cryptSession,
								CRYPT_SESSINFO_USERNAME, SSL_USER_NAME,
								paramStrlen( SSL_USER_NAME ) );
		if( cryptStatusOK( status ) )
			status = cryptSetAttributeString( cryptSession,
								CRYPT_SESSINFO_PASSWORD, SSL_PASSWORD,
								paramStrlen( SSL_PASSWORD ) );
		if( cryptStatusOK( status ) && isServer && testType == SSL_TEST_PSK )
			{
			/* If we're testing PSK, add several succeeding usernames and
			   passwords */
			cryptSetAttributeString( cryptSession,
								CRYPT_SESSINFO_USERNAME, TEXT( "after1" ),
								paramStrlen( TEXT( "after1" ) ) );
			cryptSetAttributeString( cryptSession,
								CRYPT_SESSINFO_PASSWORD, TEXT( "after1" ),
								paramStrlen( TEXT( "after1" ) ) );
			cryptSetAttributeString( cryptSession,
								CRYPT_SESSINFO_USERNAME, TEXT( "after2" ),
								paramStrlen( TEXT( "after2" ) ) );
			cryptSetAttributeString( cryptSession,
								CRYPT_SESSINFO_PASSWORD, TEXT( "after2" ),
								paramStrlen( TEXT( "after2" ) ) );
			}
		}
	if( cryptStatusError( status ) )
		{
		if( testType == SSL_TEST_STARTTLS )
			{
#if defined( __WINDOWS__ ) && !defined( _WIN32_WCE )
			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__ && !_WIN32_WCE */
			}
		printf( "cryptSetAttribute/AttributeString() failed with error code "
				"%d, line %d.\n", status, __LINE__ );
		return( FALSE );
		}
#if ( SSL_SERVER_NO == 5 ) || ( STARTTLS_SERVER_NO == 8 )
	cryptGetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,
					   &version );
	cryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,
					   CRYPT_COMPLIANCELEVEL_OBLIVIOUS );
#endif /* SSL servers with b0rken certs */
	if( localSession )
		{
		/* If we're running a local loopback test, display additional 
		   information indicating when the session is activated, since 
		   the multithreaded tests may not get to this point until long 
		   after the threads are started */
		if( sessionID != CRYPT_UNUSED )
			printf( "%02d: ", sessionID );
		printf( "%sActivating %s session...\n", isServer ? "SVR: " : "",
				versionStr[ version ] );
		}
	if( localSession && isServer )
		/* Tell the client that we're ready to go */
		releaseMutex();
	status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );
#if ( SSL_SERVER_NO == 5 ) || ( STARTTLS_SERVER_NO == 8 )
	cryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,
					   version );
#endif /* SSL server with b0rken certs */
	if( isServer && testType != SSL_TEST_PSK_CLIONLY && \
					testType != SSL_TEST_PSK_SVRONLY )
		{
		/* We don't check the return status for this since the session may
		   be disconnected before we get the client info, which would cause
		   us to bail out before we display the error info */
		if( sessionID != CRYPT_UNUSED )
			printf( "%02d: ", sessionID );
		printConnectInfo( cryptSession );
		}
#ifdef WINDOWS_THREADS
	if( isServer && testType == SSL_TEST_DUALTHREAD && \
		status == CRYPT_ENVELOPE_RESOURCE )
		{
		static CRYPT_SESSION localCryptSession = 0;
		unsigned threadID;

		/* Start a second thread to complete the handshake and exit */
		localCryptSession = cryptSession;
		_beginthreadex( NULL, 0, tlsServerDualThread2, NULL, 0, &threadID );
		return( TRUE );

		/* The second thread continues from here */
dualThreadContinue:
		assert( localSession > 0 );
		cryptSession = localCryptSession;

		/* Allow the auth.and complete the handshake */
		puts( "SVR: Confirming authentication to client..." );
		status = cryptSetAttribute( cryptSession,
									CRYPT_SESSINFO_AUTHRESPONSE, TRUE );
		if( cryptStatusOK( status ) )
			status = cryptSetAttribute( cryptSession,
										CRYPT_SESSINFO_ACTIVE, TRUE );
		}
#endif /* WINDOWS_THREADS */
	if( cryptStatusError( status ) )
		{
		char strBuffer[ 128 ];

		if( testType == SSL_TEST_STARTTLS )
			{
#if defined( __WINDOWS__ ) && !defined( _WIN32_WCE )
			closesocket( netSocket );
			WSACleanup();

⌨️ 快捷键说明

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