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

📄 scep.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* Get a new cert from the server */
	status = createScepRequest( sessionInfoPtr, &protocolInfo );
	if( cryptStatusOK( status ) )
		{
/*///////////////////////////////////////////////////////////////*/
#if 0
		sioctl( &sessionInfoPtr->stream, STREAM_IOCTL_QUERY,
				"operation=PKIOperation", 22 );
#endif
/*///////////////////////////////////////////////////////////////*/
		status = writePkiDatagram( sessionInfoPtr, SCEP_CONTENT_TYPE,
								   SCEP_CONTENT_TYPE_LEN );
		}
	if( cryptStatusOK( status ) )
		status = readPkiDatagram( sessionInfoPtr );
	if( cryptStatusOK( status ) )
		status = checkScepResponse( sessionInfoPtr, &protocolInfo );
	krnlSendNotifier( protocolInfo.iScepCert, IMESSAGE_DECREFCOUNT );
	return( status );
	}

static int clientTransactWrapper( SESSION_INFO *sessionInfoPtr )
	{
	int status;

	/* If it's not a plug-and-play PKI session, just pass the call on down
	   to the client transaction function */
	if( !( sessionInfoPtr->sessionSCEP->flags & SCEP_PFLAG_PNPPKI ) )
		return( clientTransact( sessionInfoPtr ) );

	/* We're doing plug-and-play PKI, point the transaction function at the 
	   client-transact function to execute the PnP steps, then reset it back 
	   to the PnP wrapper after we're done */
	sessionInfoPtr->transactFunction = clientTransact;
	status = pnpPkiSession( sessionInfoPtr );
	sessionInfoPtr->transactFunction = clientTransactWrapper;
	return( status );
	}

static int serverTransact( SESSION_INFO *sessionInfoPtr )
	{
	SCEP_PROTOCOL_INFO protocolInfo;
	HTTP_DATA_INFO httpDataInfo;
	HTTP_URI_INFO httpReqInfo;
	int status;

	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );

	/* SCEP is a weird protocol that started out as a basic IPsec cert-
	   provisioning mechanism for routers but then had a pile of additional
	   functionality bolted onto it via HTTP mechanisms (rather than having
	   the protocol itself handle the extra functionality).  Because of this 
	   we have to handle not only the standard HTTP-as-a-substrate mechanism 
	   used by the other protocols but also HTTP GET requests for additional 
	   information that the original protocol didn't accomodate */
	sessionInfoPtr->receiveBufEnd = 0;
	sioctl( &sessionInfoPtr->stream, STREAM_IOCTL_HTTPREQTYPES, NULL, 
			STREAM_HTTPREQTYPE_ANY );
	initHttpDataInfoEx( &httpDataInfo, sessionInfoPtr->receiveBuffer,
						sessionInfoPtr->receiveBufSize, &httpReqInfo );
	status = sread( &sessionInfoPtr->stream, &httpDataInfo,
					sizeof( HTTP_DATA_INFO ) );
	if( cryptStatusError( status ) )
		{
		sNetGetErrorInfo( &sessionInfoPtr->stream, 
						  &sessionInfoPtr->errorInfo );
		return( status );
		}

	/* If it's one of the bolted-on additions to the basic SCEP protocol, 
	   handle it separately */
	if( httpDataInfo.reqType == STREAM_HTTPREQTYPE_GET )
		{
		status = processAdditionalScepRequest( sessionInfoPtr, 
											   &httpReqInfo );
		if( cryptStatusError( status ) )
			return( status );

		/* We've processed the bolted-on portion of the exhange, now go back 
		   to handling the main protocol */
		sioctl( &sessionInfoPtr->stream, STREAM_IOCTL_HTTPREQTYPES, NULL, 
				STREAM_HTTPREQTYPE_POST );
		status = readPkiDatagram( sessionInfoPtr );
		if( cryptStatusError( status ) )
			return( status );
		}
	else
		{
		int length = httpDataInfo.bytesAvail;

		/* Unfortunately because we can't use readPkiDatagram() because of 
		   the weird dual-purpose HTTP transport used in SCEP, we have to 
		   duplicate portions of readPkiDatagram() here.  See the 
		   readPkiDatagram() function for code comments explaining the 
		   following operations */
		sioctl( &sessionInfoPtr->stream, STREAM_IOCTL_HTTPREQTYPES, NULL, 
				STREAM_HTTPREQTYPE_POST );
		if( length < 4 || length >= MAX_INTLENGTH )
			{
			retExt( CRYPT_ERROR_UNDERFLOW,
					( CRYPT_ERROR_UNDERFLOW, SESSION_ERRINFO, 
					  "Invalid PKI message length %d", length ) );
			}
		status = length = \
			checkObjectEncoding( sessionInfoPtr->receiveBuffer, length );
		if( cryptStatusError( status ) )
			{
			retExt( status, 
					( status, SESSION_ERRINFO, 
					  "Invalid PKI message encoding" ) );
			}
		sessionInfoPtr->receiveBufEnd = length;
		}

	/* Read the initial message from the client.  We don't write an error
	   response at the initial read stage to prevent scanning/DOS attacks 
	   (vir sapit qui pauca loquitur) */
	initProtocolInfo( &protocolInfo );
	status = checkScepRequest( sessionInfoPtr, &protocolInfo );
	if( cryptStatusError( status ) )
		return( status );

	/* Check that the request is permitted and convert it into a 
	   certificate */
	status = checkPkiUserInfo( sessionInfoPtr, &protocolInfo );
	if( cryptStatusOK( status ) )
		{
		MESSAGE_KEYMGMT_INFO setkeyInfo;

		setMessageKeymgmtInfo( &setkeyInfo, CRYPT_KEYID_NONE, NULL, 0, 
							   NULL, 0, KEYMGMT_FLAG_NONE );
		setkeyInfo.cryptHandle = sessionInfoPtr->iCertRequest;
		status = krnlSendMessage( sessionInfoPtr->cryptKeyset,
								  IMESSAGE_KEY_SETKEY, &setkeyInfo, 
								  KEYMGMT_ITEM_REQUEST );
		if( cryptStatusError( status ) )
			{
			setErrorString( SESSION_ERRINFO, 
							"Request couldn't be added to cert store", 39 );
			}
		}
	if( cryptStatusOK( status ) )
		{
		MESSAGE_CERTMGMT_INFO certMgmtInfo;

		setMessageCertMgmtInfo( &certMgmtInfo, sessionInfoPtr->privateKey,
								sessionInfoPtr->iCertRequest );
		status = krnlSendMessage( sessionInfoPtr->cryptKeyset,
								  IMESSAGE_KEY_CERTMGMT, &certMgmtInfo,
								  CRYPT_CERTACTION_ISSUE_CERT );
		if( cryptStatusOK( status ) )
			sessionInfoPtr->iCertResponse = certMgmtInfo.cryptCert;
		else
			{
			setErrorString( SESSION_ERRINFO, 
							"Couldn't issue certificate for user", 35 );
			}
		}
	if( cryptStatusError( status ) )
		{
		sendErrorResponse( sessionInfoPtr, &protocolInfo, status );
		destroyProtocolInfo( &protocolInfo );
		return( status );
		}

	/* Return the certificate to the client */
	status = createScepResponse( sessionInfoPtr, &protocolInfo );
	if( cryptStatusOK( status ) )
		status = writePkiDatagram( sessionInfoPtr, SCEP_CONTENT_TYPE,
								   SCEP_CONTENT_TYPE_LEN );
	destroyProtocolInfo( &protocolInfo );
	return( status );
	}

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

static int setAttributeFunction( SESSION_INFO *sessionInfoPtr,
								 const void *data,
								 const CRYPT_ATTRIBUTE_TYPE type )
	{
	CRYPT_CERTIFICATE cryptCert = *( ( CRYPT_CERTIFICATE * ) data );
	int value, status;

	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
	assert( type == CRYPT_SESSINFO_REQUEST || \
			type == CRYPT_SESSINFO_CACERTIFICATE );

	/* Make sure that there aren't any conflicts with existing attributes */
	if( !checkAttributesConsistent( sessionInfoPtr, type ) )
		return( CRYPT_ERROR_INITED );

	if( type == CRYPT_SESSINFO_CMP_PRIVKEYSET )
		{
		CRYPT_CERTIFICATE privKeyset = *( ( CRYPT_CERTIFICATE * ) data );

		/* Remember that we're using plug-and-play PKI functionality */
		sessionInfoPtr->sessionSCEP->flags |= SCEP_PFLAG_PNPPKI;

		krnlSendNotifier( privKeyset, IMESSAGE_INCREFCOUNT );
		sessionInfoPtr->privKeyset = privKeyset;
		return( CRYPT_OK );
		}

	/* Make sure that everything is set up ready to go */
	status = krnlSendMessage( cryptCert, IMESSAGE_GETATTRIBUTE, &value, 
							  CRYPT_CERTINFO_IMMUTABLE );
	if( type == CRYPT_SESSINFO_CACERTIFICATE )
		{
		if( cryptStatusError( status ) || !value )
			return( CRYPT_ARGERROR_NUM1 );
		}
	else
		{
		/* The PKCS #10 request has to be unsigned so that we can add the 
		   challengePassword */
		if( cryptStatusError( status ) || value )
			return( CRYPT_ARGERROR_NUM1 );
		}
	if( type == CRYPT_SESSINFO_CACERTIFICATE )
		{
		/* Make sure that the CA cert meets the SCEP protocol requirements */
		if( !checkCACert( cryptCert ) )
			{
			setErrorInfo( sessionInfoPtr, CRYPT_CERTINFO_KEYUSAGE,
						  CRYPT_ERRTYPE_ATTR_VALUE );
			return( CRYPT_ARGERROR_NUM1 );
			}
		}

	/* Add the request and increment its usage count */
	krnlSendNotifier( cryptCert, IMESSAGE_INCREFCOUNT );
	if( type == CRYPT_SESSINFO_CACERTIFICATE )
		{
		sessionInfoPtr->iAuthInContext = cryptCert;
		status = processKeyFingerprint( sessionInfoPtr );
		}
	else
		sessionInfoPtr->iCertRequest = cryptCert;

	return( status );
	}

static int checkAttributeFunction( SESSION_INFO *sessionInfoPtr,
								   const CRYPT_HANDLE cryptHandle,
								   const CRYPT_ATTRIBUTE_TYPE type )
	{
	int status;

	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );

	if( type != CRYPT_SESSINFO_PRIVATEKEY )
		return( CRYPT_OK );

	/* Make sure that there aren't any conflicts with existing attributes */
	if( !checkAttributesConsistent( sessionInfoPtr, type ) )
		return( CRYPT_ERROR_INITED );

	/* If it's a client key, make sure that there's no cert attached */
	if( !isServer( sessionInfoPtr ) )
		{
		int value;

		status = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE, &value, 
								  CRYPT_CERTINFO_CERTTYPE );
		if( cryptStatusOK( status ) )
			return( CRYPT_ARGERROR_NUM1 );
		}

	return( CRYPT_OK );
	}

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

int setAccessMethodSCEP( SESSION_INFO *sessionInfoPtr )
	{
	static const PROTOCOL_INFO protocolInfo = {
		/* General session information */
		TRUE,						/* Request-response protocol */
		SESSION_ISHTTPTRANSPORT,	/* Flags */
		80,							/* HTTP port */
		SESSION_NEEDS_USERID |		/* Client attributes */
			SESSION_NEEDS_PASSWORD | \
			SESSION_NEEDS_PRIVATEKEY | \
			SESSION_NEEDS_PRIVKEYSIGN | \
			SESSION_NEEDS_PRIVKEYCRYPT | \
			SESSION_NEEDS_REQUEST,
		SESSION_NEEDS_PRIVATEKEY |	/* Server attributes */
			SESSION_NEEDS_PRIVKEYSIGN | \
			SESSION_NEEDS_PRIVKEYCRYPT | \
			SESSION_NEEDS_PRIVKEYCERT | \
			SESSION_NEEDS_PRIVKEYCACERT | \
			SESSION_NEEDS_CERTSTORE,
		1, 1, 1						/* Version 1 */
		};

	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );

	/* Set the access method pointers */
	sessionInfoPtr->protocolInfo = &protocolInfo;
	if( isServer( sessionInfoPtr ) )
		sessionInfoPtr->transactFunction = serverTransact;
	else
		sessionInfoPtr->transactFunction = clientTransactWrapper;
	sessionInfoPtr->setAttributeFunction = setAttributeFunction;
	sessionInfoPtr->checkAttributeFunction = checkAttributeFunction;

	return( CRYPT_OK );
	}
#endif /* USE_SCEP */

⌨️ 快捷键说明

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