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

📄 ocsp.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 2 页
字号:
	status = krnlSendMessage( sessionInfoPtr->iCertRequest, 
							  RESOURCE_IMESSAGE_GETATTRIBUTE_S,
							  &msgData, CRYPT_IATTRIBUTE_ENC_OBJDATA );
	if( cryptStatusError( status ) )
		return( status );
	length = msgData.length;
	DEBUG_DUMP( "ocsp_req", length );

	/* Exchange data with the OCSP responder */
	status = sNetConnect( &sessionInfoPtr->stream, STREAM_PROTOCOL_HTTP_TRANSACTION, 
				sessionInfoPtr->serverName, 80, timeout, 
				sessionInfoPtr->errorMessage, &sessionInfoPtr->errorCode );
	if( cryptStatusError( status ) )
		return( status );
	status = exchangeClientDatagram( &sessionInfoPtr->stream, 
									 sessionInfoPtr->receiveBuffer, 
									 sessionInfoPtr->receiveBufSize, length );
	if( cryptStatusError( status ) )
		sNetGetErrorInfo( &sessionInfoPtr->stream, 
						  sessionInfoPtr->errorMessage,
						  &sessionInfoPtr->errorCode );
	sNetDisconnect( &sessionInfoPtr->stream );
	if( cryptStatusError( status ) )
		return( status );

	/* Find out how much data we got and perform a firewall check that
	   everything is OK.  We rely on this rather than the read byte count
	   since checking the ASN.1, which is the data which will actually be
	   processed, avoids any vagaries of server implementation oddities 
	   which may send extra null bytes or CRLFs or do who knows what else */
	length = checkObjectEncoding( sessionInfoPtr->receiveBuffer, 
								  sessionInfoPtr->receiveBufSize );
	if( cryptStatusError( length ) )
		return( length );
	DEBUG_DUMP( "ocsp_resp", length );

	/* Try and extract an OCSP status code from the returned object */
	sMemConnect( &stream, sessionInfoPtr->receiveBuffer, length );
	readSequence( &stream, NULL );
	status = readEnumerated( &stream, &value );
	if( cryptStatusOK( status ) )
		{
		sessionInfoPtr->errorCode = value;

		/* If it's an error status, try and translate it into something a 
		   bit more meaningful (some of the translations are a bit
		   questionable, but it's better than the generic no va response) */
		switch( value )
			{
			case OCSP_RESP_SUCCESSFUL:
				status = CRYPT_OK;
				break;

			case OCSP_RESP_TRYLATER:
				status = CRYPT_ERROR_BUSY;
				break;

			case OCSP_RESP_SIGREQUIRED:
				status = CRYPT_ERROR_SIGNATURE;
				break;

			case OCSP_RESP_UNAUTHORISED:
				status = CRYPT_ERROR_PERMISSION;
				break;

			default:
				status = CRYPT_ERROR_INVALID;
				break;
			}
		}
	if( cryptStatusError( status ) )
		{
		sMemDisconnect( &stream );
		return( status );
		}

	/* We've got a valid response, read the [0] EXPLICIT SEQUENCE { OID, 
	   OCTET STRING { encapsulation */
	readConstructed( &stream, NULL, 0 );		/* responseBytes */
	readSequence( &stream, NULL );
	readOID( &stream, OID_OCSP_RESPONSE );		/* responseType */
	status = readGenericHole( &stream, NULL );	/* response */
	dataStartPos = ( int ) stell( &stream );
	sMemDisconnect( &stream );
	if( cryptStatusError( status ) )
		return( status );

	/* Import the response into an OCSP cert object */
	setMessageCreateObjectIndirectInfo( &createInfo, 
							sessionInfoPtr->receiveBuffer + dataStartPos, 
							length - dataStartPos );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, 
							  RESOURCE_IMESSAGE_DEV_CREATEOBJECT_INDIRECT,
							  &createInfo, OBJECT_TYPE_CERTIFICATE );
	if( cryptStatusError( status ) )
		return( status );

	/* If the request went out with a nonce included (which it does by 
	   default), make sure it matches the nonce in the response.  The
	   comparison is somewhat complex because the nonce is encoded using
	   the integer analog to an OCTET STRING hole so it may have a leading
	   zero byte if the high bit is set.  Because of this we treat the
	   two as equal if they really are equal or if they differ only by a
	   leading zero byte */
	setResourceData( &msgData, nonceBuffer, CRYPT_MAX_HASHSIZE );
	status = krnlSendMessage( sessionInfoPtr->iCertRequest,
							  RESOURCE_IMESSAGE_GETATTRIBUTE_S,
							  &msgData, CRYPT_CERTINFO_OCSP_NONCE );
	if( cryptStatusOK( status ) )
		{
		RESOURCE_DATA responseMsgData;
		BYTE responseNonceBuffer[ CRYPT_MAX_HASHSIZE ];

		setResourceData( &responseMsgData, responseNonceBuffer, 
						 CRYPT_MAX_HASHSIZE );
		status = krnlSendMessage( createInfo.cryptHandle,
								  RESOURCE_IMESSAGE_GETATTRIBUTE_S,
								  &responseMsgData, CRYPT_CERTINFO_OCSP_NONCE );
		if( cryptStatusError( status ) || \
			!( ( msgData.length == responseMsgData.length && \
				 !memcmp( msgData.data, responseMsgData.data, msgData.length ) ) || \
			   ( msgData.length == responseMsgData.length - 1 && \
				 responseNonceBuffer[ 0 ] == 0 && \
				 !memcmp( msgData.data, responseNonceBuffer + 1, msgData.length ) ) ) )
			{
			/* The response doesn't contain a nonce or it doesn't match what
			   we sent, we can't trust it.  The best error we can return here
			   is a signature error to indicate that the integrity check 
			   failed */
			krnlSendNotifier( createInfo.cryptHandle, 
							  RESOURCE_IMESSAGE_DECREFCOUNT );
			return( CRYPT_ERROR_SIGNATURE );
			}
		}

	sessionInfoPtr->iCertResponse = createInfo.cryptHandle;

	return( CRYPT_OK );
	}

/* Start an OCSP server */

static int serverStartup( SESSION_INFO *sessionInfoPtr )
	{
	int timeout, status;

	krnlSendMessage( sessionInfoPtr->ownerHandle, 
					 RESOURCE_IMESSAGE_GETATTRIBUTE, &timeout, 
					 CRYPT_OPTION_NET_CONNECTTIMEOUT );

	/* Open a local socket and listen on it */
	status = sNetListenSocket( &sessionInfoPtr->stream, 
					STREAM_PROTOCOL_HTTP, sessionInfoPtr->serverName,
					sessionInfoPtr->serverPort, sessionInfoPtr->errorMessage,
					&sessionInfoPtr->errorCode );
	if( cryptStatusError( status ) )
		return( status );
	sioctl( &sessionInfoPtr->stream, STREAM_IOCTL_GETCLIENTNAME, 
			sessionInfoPtr->clientName, 0 );
	sioctl( &sessionInfoPtr->stream, STREAM_IOCTL_GETCLIENTPORT, 
			&sessionInfoPtr->clientPort, 0 );

	/* Read the client request */
	status = readOcspRequest( sessionInfoPtr );
	if( cryptStatusError( status ) )
		{
		sNetDisconnect( &sessionInfoPtr->stream );
		return( status );
		}

	/* Generate a response and send it to the client */
	status = sendOcspResponse( sessionInfoPtr );
	krnlSendNotifier( sessionInfoPtr->iCertResponse, 
					  RESOURCE_IMESSAGE_DECREFCOUNT );
	sNetDisconnect( &sessionInfoPtr->stream );
	return( status );
	}

static int connectFunction( SESSION_INFO *sessionInfoPtr )
	{
	if( sessionInfoPtr->flags & SESSION_ISSERVER )
		return( serverStartup( sessionInfoPtr ) );
	return( clientStartup( sessionInfoPtr ) );
	}

/****************************************************************************
*																			*
*					Control Information Management Functions				*
*																			*
****************************************************************************/

static int getAttributeFunction( SESSION_INFO *sessionInfoPtr, 
								 void *data, const CRYPT_ATTRIBUTE_TYPE type )
	{
	CRYPT_CERTIFICATE *ocspResponsePtr = ( CRYPT_CERTIFICATE * ) data;
	RESOURCE_DATA msgData = { NULL, 0 };

	assert( type == CRYPT_SESSINFO_RESPONSE );

	/* If we didn't get a response there's nothing to return */
	if( sessionInfoPtr->iCertResponse == CRYPT_ERROR )
		return( CRYPT_ERROR_NOTFOUND );

	/* Make the information externally visible */
	krnlSendNotifier( sessionInfoPtr->iCertResponse, 
					  RESOURCE_IMESSAGE_INCREFCOUNT );
	krnlSendMessage( sessionInfoPtr->iCertResponse, 
					 RESOURCE_IMESSAGE_SETATTRIBUTE, MESSAGE_VALUE_FALSE, 
					 CRYPT_IATTRIBUTE_INTERNAL );
	*ocspResponsePtr = sessionInfoPtr->iCertResponse;

	return( CRYPT_OK );
	}

static int setAttributeFunction( SESSION_INFO *sessionInfoPtr, 
								 const void *data, 
								 const CRYPT_ATTRIBUTE_TYPE type )
	{
	CRYPT_CERTIFICATE ocspRequest = *( ( CRYPT_CERTIFICATE * ) data );
	RESOURCE_DATA msgData = { NULL, 0 };
	int requestType, status;

	assert( type == CRYPT_SESSINFO_REQUEST );

	/* Make sure we've been passed the correct request type */
	status = krnlSendMessage( ocspRequest, RESOURCE_IMESSAGE_GETATTRIBUTE,
							  &requestType, CRYPT_CERTINFO_CERTTYPE );
	if( cryptStatusError( status ) || \
		requestType != CRYPT_CERTTYPE_OCSP_REQUEST )
		return( CRYPT_ARGERROR_NUM1 );

	/* Make sure everything is set up ready to go.  Since OCSP requests 
	   aren't signed like normal cert objects we can't just check the 
	   immutable attribute but have to perform a dummy export for which
	   the cert export code will return an error status if there's a
	   problem with the request.  Note that at this point the caller may
	   not have specified yet whether they want this encoded as a v1 or v2 
	   request so we'll end up with the default format, however this 
	   shouldn't be a problem since we're not asking for any data */
	status = krnlSendMessage( ocspRequest, RESOURCE_IMESSAGE_GETATTRIBUTE_S, 
							  &msgData, CRYPT_IATTRIBUTE_ENC_OBJDATA );
	if( cryptStatusError( status ) )
		return( CRYPT_ARGERROR_NUM1 );

	/* If we haven't already got a server name explicitly set, try and get 
	   it from the request */
	if( !*sessionInfoPtr->serverName )
		{
		setResourceData( &msgData, sessionInfoPtr->serverName, MAX_URL_SIZE );
		status = krnlSendMessage( ocspRequest, RESOURCE_IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_IATTRIBUTE_OCSPSERVER );
		if( cryptStatusOK( status ) )
			sessionInfoPtr->serverName[ msgData.length ] = '\0';
		}

	/* Add the request and increment its usage count */
	krnlSendNotifier( ocspRequest, RESOURCE_IMESSAGE_INCREFCOUNT );
	sessionInfoPtr->iCertRequest = ocspRequest;

	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*							Session Access Routines							*
*																			*
****************************************************************************/

int setAccessMethodOCSP( SESSION_INFO *sessionInfoPtr )
	{
	/* Set the access method pointers */
	sessionInfoPtr->initFunction = initFunction;
	sessionInfoPtr->connectFunction = connectFunction;
	sessionInfoPtr->getAttributeFunction = getAttributeFunction;
	sessionInfoPtr->setAttributeFunction = setAttributeFunction;

	return( CRYPT_OK );
	}

⌨️ 快捷键说明

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