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

📄 net.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 3 页
字号:
	{
	int timeout;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );
	assert( isReadPtr( connectInfo, sizeof( NET_CONNECT_INFO ) ) );

	REQUIRES( protocol > STREAM_PROTOCOL_NONE && \
			  protocol < STREAM_PROTOCOL_LAST );

	/* Set up the basic network stream info */
	memset( stream, 0, sizeof( STREAM ) );
	stream->type = STREAM_TYPE_NETWORK;
	memset( netStream, 0, sizeof( NET_STREAM_INFO ) );
	netStream->protocol = protocol;
	netStream->port = connectInfo->port;
	netStream->netSocket = netStream->listenSocket = CRYPT_ERROR;
	netStream->iTransportSession = CRYPT_ERROR;
	if( isServer )
		netStream->nFlags = STREAM_NFLAG_ISSERVER;

	/* Set up the stream timeout information.  While we're connecting the 
	   stream timeout is the connect timeout.  Once we've connected it's set
	   to the data transfer timeout, so initially we set the stream timeout
	   to the connect timeout and the saved timeout to the data transfer
	   timeout */
	if( connectInfo->connectTimeout != CRYPT_ERROR )
		{
		/* There's an explicit timeout specified, use that */
		timeout = connectInfo->connectTimeout;
		}
	else
		{
		/* Get the default timeout from the user object */
		if( cryptStatusError( \
				krnlSendMessage( connectInfo->iUserObject, IMESSAGE_GETATTRIBUTE,
								 &timeout, CRYPT_OPTION_NET_CONNECTTIMEOUT ) ) )
			timeout = 30;
		}
	if( timeout < 5 )
		{
		/* Enforce the same minimum connect timeout as the kernel ACLs */
		assert( DEBUG_WARN );
		timeout = 5;
		}
	netStream->timeout = timeout;
	if( connectInfo->timeout != CRYPT_ERROR )
		{
		/* There's an explicit timeout specified, use that */
		timeout = connectInfo->timeout;
		}
	else
		{
		/* Get the default timeout from the user object */
		if( cryptStatusError( \
				krnlSendMessage( connectInfo->iUserObject, IMESSAGE_GETATTRIBUTE,
								 &timeout, CRYPT_OPTION_NET_READTIMEOUT ) ) )
			timeout = 30;
		}
	netStream->savedTimeout = timeout;

	return( CRYPT_OK );
	}

/* Clean up a stream to shut it down */

STDC_NONNULL_ARG( ( 1 ) ) \
static void cleanupStream( INOUT STREAM *stream, 
						   const BOOLEAN cleanupTransport )
	{
	NET_STREAM_INFO *netStream = ( NET_STREAM_INFO * ) stream->netStreamInfo;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );

	REQUIRES_V( netStream->sanityCheckFunction( stream ) );

	/* Clean up the transport system if necessary */
	if( cleanupTransport && !( netStream->nFlags & STREAM_NFLAG_USERSOCKET ) )
		netStream->transportDisconnectFunction( netStream, TRUE );

	/* Clean up stream-related buffers if necessary */
	zeroise( netStream, sizeof( NET_STREAM_INFO ) + netStream->storageSize );
	clFree( "cleanupStream", netStream );

	zeroise( stream, sizeof( STREAM ) );
	}

/****************************************************************************
*																			*
*						Network Stream Connect Functions					*
*																			*
****************************************************************************/

/* Process network connect options */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
static int processConnectOptions( INOUT STREAM *stream, 
								  INOUT NET_STREAM_INFO *netStream,
								  OUT_OPT URL_INFO *urlInfo,
								  const NET_CONNECT_INFO *connectInfo )
	{
	int status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );
	assert( ( urlInfo == NULL ) || \
			isWritePtr( urlInfo, sizeof( URL_INFO ) ) );
	assert( isReadPtr( connectInfo, sizeof( NET_CONNECT_INFO ) ) );

	REQUIRES_S( stream->type == STREAM_TYPE_NETWORK );
				/* We can't use the sanity-check function because the stream
				   hasn't been fully set up yet */
	REQUIRES_S( ( ( connectInfo->options == NET_OPTION_TRANSPORTSESSION || \
					connectInfo->options == NET_OPTION_NETWORKSOCKET || \
					connectInfo->options == NET_OPTION_NETWORKSOCKET_DUMMY ) && \
					urlInfo == NULL ) || \
				( ( connectInfo->options == NET_OPTION_HOSTNAME || \
					connectInfo->options == NET_OPTION_HOSTNAME_TUNNEL ) && \
				  connectInfo->name != NULL && urlInfo != NULL ) || \
				( connectInfo->options == NET_OPTION_HOSTNAME && \
				  ( netStream->nFlags & STREAM_NFLAG_ISSERVER ) && \
				  connectInfo->name == NULL && urlInfo == NULL ) );

	/* Clear return value */
	if( urlInfo != NULL )
		memset( urlInfo, 0, sizeof( URL_INFO ) );

	/* If we're running over a cryptlib transport layer set up the 
	   transport session handle */
	if( connectInfo->options == NET_OPTION_TRANSPORTSESSION )
		{
		netStream->iTransportSession = connectInfo->iCryptSession;

		return( CRYPT_ERROR_NOTAVAIL );	/* See comment in net_trans.c */
		}

	/* If it's a user-supplied network socket remember this */
	if( connectInfo->options == NET_OPTION_NETWORKSOCKET || \
		connectInfo->options == NET_OPTION_NETWORKSOCKET_DUMMY )
		{
		netStream->netSocket = connectInfo->networkSocket;
		netStream->nFlags |= STREAM_NFLAG_USERSOCKET;

		return( CRYPT_OK );
		}

	ENSURES_S( connectInfo->options == NET_OPTION_HOSTNAME || \
			   connectInfo->options == NET_OPTION_HOSTNAME_TUNNEL );

	REQUIRES_S( ( ( netStream->nFlags & STREAM_NFLAG_ISSERVER ) && \
				  connectInfo->name == NULL && \
				  connectInfo->nameLength == 0 ) || \
				( connectInfo->name != NULL && \
				  connectInfo->nameLength > 0 && \
				  connectInfo->nameLength < MAX_INTLENGTH_SHORT ) );

	/* If it's a server (i.e. we're opening a listen socket) then the name
	   is optional */
	if( ( netStream->nFlags & STREAM_NFLAG_ISSERVER ) && \
		connectInfo->name == NULL )
		return( CRYPT_OK );
	ENSURES( urlInfo != NULL );

	/* Parse the URI into its various components */
	status = parseURL( urlInfo, connectInfo->name, connectInfo->nameLength, 
					   connectInfo->port,
					   ( netStream->protocol == STREAM_PROTOCOL_HTTP ) ? \
							URL_TYPE_HTTP : 
					   ( netStream->protocol == STREAM_PROTOCOL_CMP ) ? \
							URL_TYPE_HTTP : URL_TYPE_NONE );
	if( cryptStatusError( status ) )
		{
		/* There's an error in the URL format, provide more information to 
		   the caller */
		setErrorString( NETSTREAM_ERRINFO, "Invalid host name/URL", 21 );
		return( CRYPT_ERROR_OPEN );
		}
	return( CRYPT_OK );
	}

/* Complete a network connection after the client- or server-specific
   portions have been handled */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 9 ) ) \
static int completeConnect( INOUT STREAM *stream,
							INOUT NET_STREAM_INFO *netStreamTemplate, 
							IN_OPT const URL_INFO *urlInfo,
							IN_ENUM( STREAM_PROTOCOL ) \
								const STREAM_PROTOCOL_TYPE protocol,
							IN_ENUM( NET_OPTION ) const NET_OPTION_TYPE options,
							IN_BUFFER_OPT( proxyUrlLen ) const char *proxyUrl, 
							IN_LENGTH_DNS_Z const int proxyUrlLen,
							IN_HANDLE const CRYPT_USER iUserObject, 
							INOUT ERROR_INFO *errorInfo )
	{
	const BOOLEAN useTransportBuffering = \
						( options == NET_OPTION_TRANSPORTSESSION || \
						  protocol == STREAM_PROTOCOL_TCPIP ) ? \
						FALSE : TRUE;
	void *netStreamData;
	int netStreamDataSize = 0, status = CRYPT_OK;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isReadPtr( netStreamTemplate, sizeof( NET_STREAM_INFO ) ) );
	assert( ( urlInfo == NULL ) || \
			isReadPtr( urlInfo, sizeof( URL_INFO ) ) );
	assert( ( proxyUrl == NULL && proxyUrlLen == 0 ) || \
			isReadPtr( proxyUrl, proxyUrlLen ) );
	assert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );

	REQUIRES_S( stream->type == STREAM_TYPE_NETWORK );
				/* We can't use the sanity-check function because the stream
				   hasn't been fully set up yet */
	REQUIRES_S( protocol > STREAM_PROTOCOL_NONE && \
				protocol < STREAM_PROTOCOL_LAST );
	REQUIRES_S( options > NET_OPTION_NONE && options < NET_OPTION_LAST );
	REQUIRES_S( ( proxyUrl == NULL && proxyUrlLen == 0 ) || \
				( proxyUrl != NULL && \
				  proxyUrlLen > 0 && proxyUrlLen <= MAX_DNS_SIZE ) );
	REQUIRES_S( ( iUserObject == DEFAULTUSER_OBJECT_HANDLE ) || \
				  isHandleRangeValid( iUserObject ) );

	/* Set up the access method pointers.  We can use either direct TCP/IP
	   access or a cryptlib stream for transport, and layered over that
	   either HTTP, the CMP socket protocol, or direct access to the
	   transport layer */
	if( options == NET_OPTION_TRANSPORTSESSION )
		setAccessMethodTransportSession( netStreamTemplate );
	else
		setAccessMethodTCP( netStreamTemplate );
	switch( protocol )
		{
		case STREAM_PROTOCOL_HTTP:
#ifdef USE_HTTP
			setStreamLayerHTTP( netStreamTemplate );
#else
			return( CRYPT_ERROR_NOTAVAIL );
#endif /* USE_HTTP */
			break;

		case STREAM_PROTOCOL_CMP:
#ifdef USE_CMP_TRANSPORT
			setStreamLayerCMP( netStreamTemplate );
#else
			return( CRYPT_ERROR_NOTAVAIL );
#endif /* USE_CMP_TRANSPORT */
			break;

		case STREAM_PROTOCOL_TCPIP:
			setStreamLayerDirect( netStreamTemplate );
			break;

		default:
			retIntError_Stream( stream );
		}
	setStreamLayerBuffering( netStreamTemplate, useTransportBuffering );

	ENSURES( netStreamTemplate->sanityCheckFunction != NULL );
	ENSURES( netStreamTemplate->writeFunction != NULL && \
			 netStreamTemplate->readFunction != NULL );
	ENSURES( netStreamTemplate->transportConnectFunction != NULL && \
			 netStreamTemplate->transportDisconnectFunction != NULL );
	ENSURES( netStreamTemplate->transportReadFunction != NULL && \
			 netStreamTemplate->transportWriteFunction != NULL );
	ENSURES( netStreamTemplate->transportOKFunction != NULL && \
			 netStreamTemplate->transportCheckFunction != NULL );
	ENSURES( netStreamTemplate->bufferedTransportReadFunction != NULL && \
			 netStreamTemplate->bufferedTransportWriteFunction != NULL );
	ENSURES( ( netStreamTemplate->nFlags & STREAM_NFLAG_ISSERVER ) || \
			 ( urlInfo != NULL && \
			   urlInfo->host != NULL && urlInfo->hostLen != 0 ) || \
			 netStreamTemplate->netSocket != CRYPT_ERROR );

#if 0	/* 5/5/08 See comment in net_trans.c */
	/* If we're running over a cryptlib session, make sure that we wait around
	   for a minimum amount of time during network comms in case the user has
	   specified nonblocking behaviour or quick timeouts */
	if( options == NET_OPTION_TRANSPORTSESSION )
		{
		static const int fixedTimeout = 30;
		int timeout;

		status = krnlSendMessage( iUserObject, IMESSAGE_GETATTRIBUTE,
								  &timeout, CRYPT_OPTION_NET_CONNECTTIMEOUT );
		if( cryptStatusOK( status ) && timeout < fixedTimeout )
			{
			( void ) krnlSendMessage( netStreamTemplate->iTransportSession,
							IMESSAGE_SETATTRIBUTE, ( void * ) &fixedTimeout,
							CRYPT_OPTION_NET_CONNECTTIMEOUT );
			}
		status = krnlSendMessage( iUserObject, IMESSAGE_GETATTRIBUTE,
								  &timeout, CRYPT_OPTION_NET_READTIMEOUT );
		if( cryptStatusOK( status ) && timeout < fixedTimeout )
			{
			( void ) krnlSendMessage( netStreamTemplate->iTransportSession, 
							IMESSAGE_SETATTRIBUTE, ( void * ) &fixedTimeout,
							CRYPT_OPTION_NET_READTIMEOUT );
			}
		status = krnlSendMessage( iUserObject, IMESSAGE_GETATTRIBUTE,
								  &timeout, CRYPT_OPTION_NET_WRITETIMEOUT );
		if( cryptStatusOK( status ) && timeout < fixedTimeout )
			{
			( void ) krnlSendMessage( netStreamTemplate->iTransportSession, 
							IMESSAGE_SETATTRIBUTE, ( void * ) &fixedTimeout,
							CRYPT_OPTION_NET_WRITETIMEOUT );
			}
		status = CRYPT_OK;	/* Reset status from above checks */
		}
#endif /* 0 */

	/* Wait for any async network driver binding to complete and make sure
	   that the network interface has been initialised */
	if( !krnlWaitSemaphore( SEMAPHORE_DRIVERBIND ) || \
		!netStreamTemplate->transportOKFunction() )
		{
		/* Provide more information on the nature of the problem */
		setErrorString( errorInfo, "Networking subsystem not available", 34 );

		/* Clean up */
		zeroise( stream, sizeof( STREAM ) );
		return( CRYPT_ERROR_NOTINITED );
		}

	/* Allocate room for the network stream information */
	if( useTransportBuffering )
		netStreamDataSize += NETWORK_BUFFER_SIZE + NETWORK_BUFFER_SIZE;
	if( urlInfo != NULL )
		netStreamDataSize += urlInfo->hostLen + urlInfo->locationLen;
	netStreamData = clAlloc( "completeConnect", sizeof( NET_STREAM_INFO ) + \
												netStreamDataSize );
	if( netStreamData == NULL )
		{
		zeroise( stream, sizeof( STREAM ) );
		return( CRYPT_ERROR_MEMORY );
		}

	/* Initialise the network stream with the net stream template and set up 
	   pointers to buffers if required */
	memcpy( netStreamData, netStreamTemplate, sizeof( NET_STREAM_INFO ) );
	if( useTransportBuffering || urlInfo != NULL )
		{
		NET_STREAM_INFO *netStreamInfo = netStreamData;
		BYTE *netStreamDataPtr = ( BYTE * ) netStreamData + \
											sizeof( NET_STREAM_INFO );

⌨️ 快捷键说明

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