📄 scep.c
字号:
/* 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 + -