📄 ocsp.c
字号:
/****************************************************************************
* *
* cryptlib OCSP Session Management *
* Copyright Peter Gutmann 1999-2002 *
* *
****************************************************************************/
#include <stdlib.h>
#include <string.h>
#if defined( INC_ALL )
#include "crypt.h"
#include "asn1.h"
#include "asn1oid.h"
#include "stream.h"
#include "session.h"
#elif defined( INC_CHILD )
#include "../crypt.h"
#include "../keymgmt/asn1.h"
#include "../keymgmt/asn1oid.h"
#include "../keymgmt/stream.h"
#include "../session/session.h"
#else
#include "crypt.h"
#include "keymgmt/asn1.h"
#include "keymgmt/asn1oid.h"
#include "keymgmt/stream.h"
#include "session/session.h"
#endif /* Compiler-specific includes */
/* The following macro can be used to enable dumping of PDUs to disk (as a
safeguard, this only works in the Win32 debug version to prevent it from
being accidentally enabled in any release version) */
#if defined( __WIN32__ ) && !defined( NDEBUG )
#define DEBUG_DUMP( name, length ) \
{ \
FILE *filePtr; \
char fileName[ 1024 ]; \
\
strcpy( fileName, "r:/tmp/" ); \
strcat( fileName, name ); \
strcat( fileName, ".der" ); \
\
filePtr = fopen( fileName, "wb" ); \
if( filePtr != NULL ) \
{ \
fwrite( sessionInfoPtr->receiveBuffer, 1, length, filePtr ); \
fclose( filePtr ); \
} \
}
#else
#define DEBUG_DUMP( name, length )
#endif /* Win32 debug */
/* OCSP response status values */
enum { OCSP_RESP_SUCCESSFUL, OCSP_RESP_MALFORMEDREQUEST,
OCSP_RESP_INTERNALERROR, OCSP_RESP_TRYLATER, OCSP_RESP_DUMMY,
OCSP_RESP_SIGREQUIRED, OCSP_RESP_UNAUTHORISED };
/****************************************************************************
* *
* Client-side Functions *
* *
****************************************************************************/
/* Exchange a datagram with an OCSP responder */
static int exchangeClientDatagram( STREAM *stream, void *buffer,
const int bufSize, const int dataOutSize )
{
int status;
/* Send the request to the responder */
sioctl( stream, STREAM_IOCTL_CONTENTTYPE, "application/ocsp-request", 24 );
status = swrite( stream, buffer, dataOutSize );
if( cryptStatusError( status ) )
return( status );
/* Read the response from the responder, converting the sread() byte
count into a CRYPT_OK */
status = sread( stream, buffer, bufSize );
return( cryptStatusError( status ) ? status : CRYPT_OK );
}
/****************************************************************************
* *
* Server-side Functions *
* *
****************************************************************************/
/* Send an error response back to the client. Since there are only a small
number of these, we write back a fixed blob rather than encoding each
one */
#define RESPONSE_SIZE 5
static const BYTE respBadRequest[] = {
0x30, 0x03, 0x0A, 0x01, 0x01 /* Rejection, malformed request */
};
static const BYTE respIntError[] = {
0x30, 0x03, 0x0A, 0x01, 0x02 /* Rejection, internal error */
};
/* Read a request from an OCSP client */
static int readOcspRequest( SESSION_INFO *sessionInfoPtr )
{
CRYPT_CERTIFICATE iOcspRequest;
MESSAGE_CREATEOBJECT_INFO createInfo;
BYTE *bufPtr = sessionInfoPtr->receiveBuffer;
int status;
/* Read the request data from the client */
status = sread( &sessionInfoPtr->stream, sessionInfoPtr->receiveBuffer,
sessionInfoPtr->receiveBufSize );
if( cryptStatusError( status ) )
return( status );
DEBUG_DUMP( "ocsp_sreq", status );
/* Import the request as a cryptlib object */
setMessageCreateObjectIndirectInfo( &createInfo,
sessionInfoPtr->receiveBuffer, status );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
RESOURCE_IMESSAGE_DEV_CREATEOBJECT_INDIRECT,
&createInfo, OBJECT_TYPE_CERTIFICATE );
if( cryptStatusError( status ) )
{
swrite( &sessionInfoPtr->stream, respBadRequest, RESPONSE_SIZE );
return( status );
}
iOcspRequest = createInfo.cryptHandle;
/* Create an OSCP response and add the request information to it */
setMessageCreateObjectInfo( &createInfo, CRYPT_CERTTYPE_OCSP_RESPONSE );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_CERTIFICATE );
if( cryptStatusOK( status ) )
{
status = krnlSendMessage( createInfo.cryptHandle,
RESOURCE_IMESSAGE_SETATTRIBUTE, &iOcspRequest,
CRYPT_IATTRIBUTE_OCSPREQUEST );
sessionInfoPtr->iCertResponse = createInfo.cryptHandle;
}
krnlSendNotifier( iOcspRequest, RESOURCE_IMESSAGE_DECREFCOUNT );
if( cryptStatusOK( status ) )
sessionInfoPtr->iCertResponse = createInfo.cryptHandle;
else
{
krnlSendNotifier( createInfo.cryptHandle,
RESOURCE_IMESSAGE_DECREFCOUNT );
swrite( &sessionInfoPtr->stream, respIntError, RESPONSE_SIZE );
}
return( status );
}
/* Return a response to an OCSP client */
static int sendOcspResponse( SESSION_INFO *sessionInfoPtr )
{
RESOURCE_DATA msgData;
STREAM stream;
int responseLength, status;
/* Check the entries from the request against the cert store and sign
the resulting status information ("Love, ken") */
status = krnlSendMessage( sessionInfoPtr->iCertResponse,
RESOURCE_IMESSAGE_CRT_SIGCHECK, NULL,
sessionInfoPtr->cryptKeyset );
if( cryptStatusOK( status ) )
status = krnlSendMessage( sessionInfoPtr->iCertResponse,
RESOURCE_IMESSAGE_CRT_SIGN, NULL,
sessionInfoPtr->privateKey );
if( cryptStatusError( status ) )
{
swrite( &sessionInfoPtr->stream, respIntError, RESPONSE_SIZE );
return( status );
}
/* Determine how long the response is and write the wrapper for it */
setResourceData( &msgData, NULL, 0 );
status = krnlSendMessage( sessionInfoPtr->iCertResponse,
RESOURCE_IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_ENC_CERT );
if( cryptStatusError( status ) )
{
swrite( &sessionInfoPtr->stream, respIntError, RESPONSE_SIZE );
return( status );
}
sMemOpen( &stream, sessionInfoPtr->receiveBuffer,
sessionInfoPtr->receiveBufSize );
responseLength = sizeofOID( OID_OCSP_RESPONSE ) + \
sizeofObject( msgData.length );
writeSequence( &stream, sizeofEnumerated( 0 ) + \
sizeofObject( sizeofObject( responseLength ) ) );
writeEnumerated( &stream, 0, DEFAULT_TAG ); /* respStatus */
writeConstructed( &stream, sizeofObject( responseLength ), 0 );
writeSequence( &stream, responseLength ); /* respBytes */
writeOID( &stream, OID_OCSP_RESPONSE ); /* respType */
writeTag( &stream, BER_OCTETSTRING ); /* response */
writeLength( &stream, msgData.length );
/* Get the encoded response data */
setResourceData( &msgData, sMemBufPtr( &stream ),
sessionInfoPtr->receiveBufSize - stell( &stream ) );
status = krnlSendMessage( sessionInfoPtr->iCertResponse,
RESOURCE_IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_ENC_CERT );
sessionInfoPtr->receiveBufEnd = stell( &stream ) + msgData.length;
sMemDisconnect( &stream );
if( cryptStatusError( status ) )
{
swrite( &sessionInfoPtr->stream, respIntError, RESPONSE_SIZE );
return( status );
}
DEBUG_DUMP( "ocsp_sresp", sessionInfoPtr->receiveBufEnd );
/* Send the response to the client */
sioctl( &sessionInfoPtr->stream, STREAM_IOCTL_CONTENTTYPE,
"application/ocsp-response", 25 );
status = swrite( &sessionInfoPtr->stream, sessionInfoPtr->receiveBuffer,
sessionInfoPtr->receiveBufEnd );
if( cryptStatusError( status ) )
return( status );
return( status );
}
/****************************************************************************
* *
* Init/Shutdown Functions *
* *
****************************************************************************/
/* Init/shutdown functions. Since OCSP is stateless there isn't much to
do */
static int initFunction( SESSION_INFO *sessionInfoPtr )
{
/* Set various OCSP session parameters */
sessionInfoPtr->requiredAttributeFlags |= \
SESSION_SERVER_NEEDSPRIVATEKEY | SESSION_SERVER_NEEDSPRIVKEYCERT | \
SESSION_SERVER_NEEDSCERTSTORE;
sessionInfoPtr->sendBufSize = CRYPT_UNUSED;
sessionInfoPtr->receiveBufSize = MIN_BUFFER_SIZE;
sessionInfoPtr->serverPort = 80;
sessionInfoPtr->version = 1;
return( CRYPT_OK );
}
/* Exchange data with an OCSP server */
static int clientStartup( SESSION_INFO *sessionInfoPtr )
{
MESSAGE_CREATEOBJECT_INFO createInfo;
RESOURCE_DATA msgData;
STREAM stream;
BYTE nonceBuffer[ CRYPT_MAX_HASHSIZE ];
int timeout, value, length, dataStartPos, status;
krnlSendMessage( sessionInfoPtr->ownerHandle,
RESOURCE_IMESSAGE_GETATTRIBUTE, &timeout,
CRYPT_OPTION_NET_CONNECTTIMEOUT );
/* Make sure we have all the needed information */
if( sessionInfoPtr->iCertRequest == CRYPT_ERROR )
{
setErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_REQUEST,
CRYPT_ERRTYPE_ATTR_ABSENT );
return( CRYPT_ERROR_NOTINITED );
}
/* Get the encoded request data. We read this into the send buffer which
at its minimum size is roughly two orders of magnitude larger than the
request */
setResourceData( &msgData, sessionInfoPtr->receiveBuffer,
sessionInfoPtr->receiveBufSize );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -