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

📄 ssl.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 3 页
字号:
			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 );
			}
		}
	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__ ) && !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( _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 ) && 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 0	/* Optional proxy for net access */
		status = cryptSetAttributeString( CRYPT_UNUSED,
								CRYPT_OPTION_NET_HTTP_PROXY, "[Autodetect]",
								12 );
#endif /* 0 */
		}
	if( cryptStatusOK( status ) && sharedKey )
		{
		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( isServer )
			{
#if 0	/* Old PSK mechanism */
			/* 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, TEXT( "0000" ),
									paramStrlen( TEXT( "0000" ) ) );
			if( cryptStatusOK( status ) )
				status = cryptSetAttributeString( cryptSession,
									CRYPT_SESSINFO_PASSWORD, TEXT( "0000" ),
									paramStrlen( TEXT( "0000" ) ) );
			if( cryptStatusOK( status ) && \
				cryptStatusOK( \
					cryptSetAttributeString( cryptSession,
									CRYPT_SESSINFO_USERNAME, TEXT( "0000" ),
									paramStrlen( TEXT( "0000" ) ) ) ) )
				{
				printf( "SVR: Addition of duplicate entry to SSL session "
						"cache wasn't detected, line %d.\n", __LINE__ );
				return( FALSE );
				}
#endif /* 0 */

#if 0		/* Check the functioning of the session cache's LRU mechanism */
			{
			int i;

			for( i = 0; i < 1024 + 2000; i++ )
				{
				char userName[ 64 ];

				sprintf( userName, "user%04d", i );
				status = cryptSetAttributeString( cryptSession,
										CRYPT_SESSINFO_USERNAME, userName,
										paramStrlen( userName ) );
				if( cryptStatusOK( status ) )
					status = cryptSetAttributeString( cryptSession,
										CRYPT_SESSINFO_PASSWORD, userName,
										paramStrlen( userName ) );
				if( cryptStatusError( status ) )
					{
					printf( "SVR: Error %d during SSL server cache LRU "
							"test, line %d.\n", status, __LINE__ );
					return( FALSE );
					}
				}
			}
#endif /* 0 */
			}
		}
	if( cryptStatusError( status ) )
		{
		if( localSocket )
			{
#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 */
	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 )
		{
		if( !printConnectInfo( cryptSession ) )
			return( FALSE );
		}
	if( cryptStatusError( status ) )
		{
		char strBuffer[ 128 ];

		if( localSocket )
			{
#if defined( __WINDOWS__ ) && !defined( _WIN32_WCE )
			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__ && !_WIN32_WCE */
			}
		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 || 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 );
			}
		return( FALSE );
		}

	/* Report the session security info */
	if( !printSecurityInfo( cryptSession, isServer, !sharedKey ) )
		return( FALSE );
	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 )
		{
		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,
								bulkTransfer ? 0 : 5 );
#endif /* SSL_SERVER_NO == 3 */
	if( bulkTransfer )
		{
		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.\n", byteCount,
						BULKDATA_BUFFER_SIZE );
				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 %d of %d 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.\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 /* 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 */
			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 )

⌨️ 快捷键说明

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