static int processAdditionalScepRequest( INOUT SESSION_INFO *sessionInfoPtr, const HTTP_URI_INFO *httpReqInfo ) { HTTP_URI_INFO rewrittenHttpReqInfo; MESSAGE_DATA msgData; int operationType, status; assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) ); assert( isReadPtr( httpReqInfo, sizeof( HTTP_URI_INFO ) ) ); /* If the client has fed us an HTTP GET request, find out what they want. SCEP's handling of HTTP requests is a bit different from the "attribute '=' value" lookup that's normally used for HTTP data retrieval. Instead, it uses the format "'operation =' value '&' extraData", with the search key buried in the 'extraData' value. In addition the content of the 'extraData' value isn't defined outside of "any string which is understood by the CA". However since 'value' defines what we want, we can determine what to return based on this and ignore the 'extraData' portion. In order to fix up the query information into a format that works with standard HTTP queries, we rewrite the query data from the "'operation =' value '&' extraData" form into "attribute '=' value" before we process the query */ memset( &rewrittenHttpReqInfo, 0, sizeof( HTTP_URI_INFO ) ); memcpy( rewrittenHttpReqInfo.attribute, httpReqInfo->value, httpReqInfo->valueLen ); rewrittenHttpReqInfo.attributeLen = httpReqInfo->valueLen; if( httpReqInfo->extraDataLen > 0 ) { memcpy( rewrittenHttpReqInfo.value, httpReqInfo->extraData, httpReqInfo->extraDataLen ); rewrittenHttpReqInfo.valueLen = httpReqInfo->extraDataLen; } status = processCertQuery( sessionInfoPtr, &rewrittenHttpReqInfo, certstoreReadInfo, FAILSAFE_ARRAYSIZE( certstoreReadInfo, \ CERTSTORE_READ_INFO ), &operationType, NULL, 0, NULL ); if( cryptStatusError( status ) ) { sendCertErrorResponse( sessionInfoPtr, status ); return( status ); } ENSURES( operationType == SCEP_OPERATION_GETCACAPS || \ operationType == SCEP_OPERATION_GETCACERT || \ operationType == SCEP_OPERATION_GETCACERTCHAIN ); /* If it's a CA capabilities query, return the information as raw text over HTTP */ if( operationType == SCEP_OPERATION_GETCACAPS ) { STREAM stream; sMemOpen( &stream, sessionInfoPtr->receiveBuffer, 1024 ); status = swrite( &stream, "POSTPKIOperation\n", 17 ); if( algoAvailable( CRYPT_ALGO_SHA1 ) ) status = swrite( &stream, "SHA-1\n", 6 ); if( algoAvailable( CRYPT_ALGO_SHA2 ) ) status = swrite( &stream, "SHA-256\n", 8 ); if( algoAvailable( CRYPT_ALGO_SHAng ) ) status = swrite( &stream, "SHAng\n", 6 ); if( algoAvailable( CRYPT_ALGO_3DES ) ) status = swrite( &stream, "DES3\n", 5 ); if( algoAvailable( CRYPT_ALGO_AES ) ) status = swrite( &stream, "AES\n", 4 ); if( cryptStatusOK( status ) ) sessionInfoPtr->receiveBufEnd = stell( &stream ); sMemDisconnect( &stream ); ENSURES( cryptStatusOK( status ) ); return( writePkiDatagram( sessionInfoPtr, SCEP_CONTENT_TYPE, SCEP_CONTENT_TYPE_LEN ) ); } /* Export the CA certificate and send it to the client */ setMessageData( &msgData, sessionInfoPtr->receiveBuffer, sessionInfoPtr->receiveBufSize ); status = krnlSendMessage( sessionInfoPtr->privateKey, IMESSAGE_CRT_EXPORT, &msgData, ( operationType == SCEP_OPERATION_GETCACERT ) ? \ CRYPT_CERTFORMAT_CERTIFICATE : \ CRYPT_CERTFORMAT_CERTCHAIN ); if( cryptStatusError( status ) ) { retExt( status, ( status, SESSION_ERRINFO, "Couldn't export CA certificate%s for '%s' request", ( operationType == SCEP_OPERATION_GETCACERT ) ? \ "" : " chain", ( operationType == SCEP_OPERATION_GETCACERT ) ? \ "GetCACert" : "GetCACertChain" ) ); } sessionInfoPtr->receiveBufEnd = msgData.length; if( operationType == SCEP_OPERATION_GETCACERT ) { return( writePkiDatagram( sessionInfoPtr, SCEP_CONTENT_TYPE_GETCACERT, SCEP_CONTENT_TYPE_GETCACERT_LEN ) ); } return( writePkiDatagram( sessionInfoPtr, SCEP_CONTENT_TYPE_GETCACERTCHAIN, SCEP_CONTENT_TYPE_GETCACERTCHAIN_LEN ) ); }
static int processAdditionalScepRequest( INOUT SESSION_INFO *sessionInfoPtr, const HTTP_URI_INFO *httpReqInfo ) { HTTP_URI_INFO rewrittenHttpReqInfo; MESSAGE_DATA msgData; int operationType, status; assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) ); assert( isReadPtr( httpReqInfo, sizeof( HTTP_URI_INFO ) ) ); /* If the client has fed us an HTTP GET request, find out what they want. SCEP's handling of HTTP requests is a bit different from the "attribute '=' value" lookup that's normally used for HTTP data retrieval. Instead, it uses the format "'operation =' value '&' extraData", with the search key buried in the 'extraData' value. In addition the content of the 'extraData' value isn't defined outside of "any string which is understood by the CA". However since 'value' defines what we want, we can determine what to return based on this and ignore the 'extraData' portion. In order to fix up the query information into a format that works with standard HTTP queries, we rewrite the query data from the "'operation =' value '&' extraData" form into "attribute '=' value" before we process the query */ memset( &rewrittenHttpReqInfo, 0, sizeof( HTTP_URI_INFO ) ); memcpy( rewrittenHttpReqInfo.attribute, httpReqInfo->value, httpReqInfo->valueLen ); rewrittenHttpReqInfo.attributeLen = httpReqInfo->valueLen; if( httpReqInfo->extraDataLen > 0 ) { memcpy( rewrittenHttpReqInfo.value, httpReqInfo->extraData, httpReqInfo->extraDataLen ); rewrittenHttpReqInfo.valueLen = httpReqInfo->extraDataLen; } status = processCertQuery( sessionInfoPtr, &rewrittenHttpReqInfo, certstoreReadInfo, FAILSAFE_ARRAYSIZE( certstoreReadInfo, \ CERTSTORE_READ_INFO ), &operationType, NULL, 0, NULL ); if( cryptStatusError( status ) ) { sendCertErrorResponse( sessionInfoPtr, status ); return( status ); } ENSURES( operationType == SCEP_OPERATION_GETCACAPS || \ operationType == SCEP_OPERATION_GETCACERT || \ operationType == SCEP_OPERATION_GETCACERTCHAIN ); /* If it's a CA capabilities query, return the information as raw text over HTTP */ if( operationType == SCEP_OPERATION_GETCACAPS ) { STREAM stream; sMemOpen( &stream, sessionInfoPtr->receiveBuffer, 1024 ); swrite( &stream, "POSTPKIOperation\n", 17 ); #if 0 /* 14/6/14 Too risky to implement given its current state in the spec, see the discussion on the JSCEP mailing list for details */ status = swrite( &stream, "Renewal\n", 8 ); #endif /* 0 */ if( algoAvailable( CRYPT_ALGO_SHA1 ) ) status = swrite( &stream, "SHA-1\n", 6 ); if( algoAvailable( CRYPT_ALGO_SHA2 ) ) status = swrite( &stream, "SHA-256\n", 8 ); if( algoAvailable( CRYPT_ALGO_SHAng ) ) status = swrite( &stream, "SHAng\n", 6 ); if( algoAvailable( CRYPT_ALGO_3DES ) ) status = swrite( &stream, "DES3\n", 5 ); if( algoAvailable( CRYPT_ALGO_AES ) ) status = swrite( &stream, "AES\n", 4 ); if( cryptStatusOK( status ) ) sessionInfoPtr->receiveBufEnd = stell( &stream ); sMemDisconnect( &stream ); ENSURES( cryptStatusOK( status ) ); return( writePkiDatagram( sessionInfoPtr, SCEP_CONTENT_TYPE, SCEP_CONTENT_TYPE_LEN ) ); }