📄 ca_issue.c
字号:
/****************************************************************************
* *
* cryptlib DBMS CA Cert Issue Interface *
* Copyright Peter Gutmann 1996-2004 *
* *
****************************************************************************/
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#if defined( INC_ALL )
#include "crypt.h"
#include "keyset.h"
#include "dbms.h"
#include "asn1.h"
#include "rpc.h"
#elif defined( INC_CHILD )
#include "../crypt.h"
#include "../keyset/keyset.h"
#include "../keyset/dbms.h"
#include "../misc/asn1.h"
#include "../misc/rpc.h"
#else
#include "crypt.h"
#include "keyset/keyset.h"
#include "keyset/dbms.h"
#include "misc/asn1.h"
#include "misc/rpc.h"
#endif /* Compiler-specific includes */
#ifdef USE_DBMS
/****************************************************************************
* *
* Cert Issue Functions *
* *
****************************************************************************/
/* Get the issue type (new request, renewal, etc) for a particular cert
request or certificate */
static int getCertIssueType( DBMS_INFO *dbmsInfo,
const CRYPT_CERTIFICATE iCertificate,
const BOOLEAN isCert )
{
BYTE certData[ MAX_QUERY_RESULT_SIZE ];
char certID[ DBXKEYID_BUFFER_SIZE ];
int certIDlength, length, status;
/* Get the certID of the request that resulted in the cert creation */
status = certIDlength = getKeyID( certID, iCertificate,
CRYPT_CERTINFO_FINGERPRINT_SHA );
if( !cryptStatusError( status ) && isCert )
{
/* If it's a cert we have to apply an extra level of indirection to
get the request that resulted in its creation */
status = dbmsQuery(
"SELECT reqCertID FROM certLog WHERE certID = ?",
certData, &length, certID, certIDlength, 0,
DBMS_CACHEDQUERY_NONE, DBMS_QUERY_NORMAL );
if( cryptStatusOK( status ) )
{
if( length > MAX_ENCODED_DBXKEYID_SIZE )
length = MAX_ENCODED_DBXKEYID_SIZE;
memcpy( certID, certData, length );
certIDlength = length;
}
}
if( cryptStatusError( status ) )
return( status );
/* Find out whether this was a cert update by checking whether it was
added as a standard or renewal request, then set the update type
appropriately. The comparison for the action type is a bit odd since
some back-ends will return the action as text and some as a binary
numeric value, rather than relying on the back-end glue code to
perform the appropriate conversion we just check for either value
type */
status = dbmsQuery(
"SELECT action FROM certLog WHERE certID = ?",
certData, &length, certID, certIDlength, 0,
DBMS_CACHEDQUERY_NONE, DBMS_QUERY_NORMAL );
if( cryptStatusError( status ) )
return( status );
switch( certData[ 0 ] )
{
case CRYPT_CERTACTION_REQUEST_CERT:
case TEXTCH_CERTACTION_REQUEST_CERT:
return( CERTADD_PARTIAL );
case CRYPT_CERTACTION_REQUEST_RENEWAL:
case TEXTCH_CERTACTION_REQUEST_RENEWAL:
return( CERTADD_PARTIAL_RENEWAL );
default:
assert( NOTREACHED );
}
return( CRYPT_ERROR_NOTFOUND );
}
/* Replace one cert (usually a partially-issued one) with another (usually
its completed form). The types of operations and their corresponding
add-type values are:
ESC1 -> std CERTADD_PARTIAL Completion of partial
ESC1 -> ESC2 CERTADD_PARTIAL_RENEWAL First half of renewal
ESC2 -> std CERTADD_RENEWAL_COMPLETE Second half of renewal */
static int completeCert( DBMS_INFO *dbmsInfo,
const CRYPT_CERTIFICATE iCertificate,
const CERTADD_TYPE addType )
{
char sqlBuffer[ MAX_SQL_QUERY_SIZE ];
char certID[ DBXKEYID_BUFFER_SIZE ];
int length, status;
assert( addType == CERTADD_PARTIAL || \
addType == CERTADD_PARTIAL_RENEWAL || \
addType == CERTADD_RENEWAL_COMPLETE );
status = length = getKeyID( certID, iCertificate,
CRYPT_CERTINFO_FINGERPRINT_SHA );
if( cryptStatusError( status ) )
return( status );
status = addCert( dbmsInfo, iCertificate, CRYPT_CERTTYPE_CERTIFICATE,
( addType == CERTADD_PARTIAL_RENEWAL ) ? \
CERTADD_PARTIAL_RENEWAL : CERTADD_NORMAL,
DBMS_UPDATE_BEGIN );
if( cryptStatusOK( status ) )
{
char specialCertID[ DBXKEYID_BUFFER_SIZE ];
/* Turn the general certID into the form required for special-case
cert data */
memcpy( specialCertID, certID, length + 1 );
memcpy( specialCertID,
( addType == CERTADD_RENEWAL_COMPLETE ) ? \
KEYID_ESC2 : KEYID_ESC1, KEYID_ESC_SIZE );
specialCertID[ MAX_ENCODED_DBXKEYID_SIZE ] = '\0';
dbmsFormatSQL( sqlBuffer,
"DELETE FROM certificates WHERE certID = '$'",
specialCertID );
status = dbmsUpdate( sqlBuffer, NULL, 0, 0,
( addType == CERTADD_PARTIAL_RENEWAL ) ? \
DBMS_UPDATE_COMMIT : DBMS_UPDATE_CONTINUE );
}
if( cryptStatusOK( status ) )
{
if( addType != CERTADD_PARTIAL_RENEWAL )
status = updateCertLog( dbmsInfo,
CRYPT_CERTACTION_CERT_CREATION_COMPLETE,
NULL, NULL, certID, NULL, 0,
DBMS_UPDATE_COMMIT );
}
else
/* Something went wrong, abort the transaction */
dbmsUpdate( NULL, NULL, 0, 0, DBMS_UPDATE_ABORT );
/* If the operation failed, record the details */
if( cryptStatusError( status ) )
updateCertErrorLog( dbmsInfo, status,
"Certificate creation - completion operation "
"failed", NULL, NULL, certID, NULL, 0 );
return( status );
}
/* Complete a certificate renewal operation by revoking the cert to be
replaced and replacing it with the newly-issued cert */
int completeCertRenewal( DBMS_INFO *dbmsInfo,
const CRYPT_CERTIFICATE iReplaceCertificate )
{
CRYPT_CERTIFICATE iOrigCertificate;
char keyID[ DBXKEYID_BUFFER_SIZE ];
int dummy, length, status;
/* Extract the key ID from the new cert and use it to fetch the existing
cert issued for the same key */
status = length = getCertKeyID( keyID, iReplaceCertificate );
if( !cryptStatusError( status ) )
status = getItemData( dbmsInfo, &iOrigCertificate, &dummy,
CRYPT_IKEYID_KEYID, keyID, length,
KEYMGMT_ITEM_PUBLICKEY, KEYMGMT_FLAG_NONE );
if( status == CRYPT_ERROR_NOTFOUND )
/* If the original cert fetch fails with a notfound error this is OK
since we may be resuming from a point where the revocation has
already occurred, or the cert may have already expired or been
otherwise replaced, so we just slide in the new cert */
return( completeCert( dbmsInfo, iReplaceCertificate,
CERTADD_RENEWAL_COMPLETE ) );
if( cryptStatusError( status ) )
return( status );
/* Replace the original cert with the new one */
status = revokeCertDirect( dbmsInfo, iOrigCertificate,
CRYPT_CERTACTION_REVOKE_CERT );
if( cryptStatusOK( status ) )
status = completeCert( dbmsInfo, iReplaceCertificate,
CERTADD_RENEWAL_COMPLETE );
krnlSendNotifier( iOrigCertificate, IMESSAGE_DECREFCOUNT );
return( status );
}
/* Issue a cert from a cert request */
int caIssueCert( DBMS_INFO *dbmsInfo, CRYPT_CERTIFICATE *iCertificate,
const CRYPT_CERTIFICATE caKey,
const CRYPT_CERTIFICATE iCertRequest,
const CRYPT_CERTACTION_TYPE action )
{
CRYPT_CERTIFICATE iLocalCertificate;
MESSAGE_CREATEOBJECT_INFO createInfo;
BYTE certData[ MAX_CERT_SIZE ];
char issuerID[ DBXKEYID_BUFFER_SIZE ], certID[ DBXKEYID_BUFFER_SIZE ];
char reqCertID[ DBXKEYID_BUFFER_SIZE ];
CERTADD_TYPE addType = CERTADD_NORMAL;
int certDataLength, issueType, status;
assert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );
assert( isHandleRangeValid( iCertRequest ) );
assert( action == CRYPT_CERTACTION_ISSUE_CERT || \
action == CRYPT_CERTACTION_CERT_CREATION );
/* Clear return value */
if( iCertificate != NULL )
*iCertificate = CRYPT_ERROR;
/* Extract the information that we need from the cert request */
status = issueType = getCertIssueType( dbmsInfo, iCertRequest, FALSE );
if( !cryptStatusError( status ) )
status = getKeyID( reqCertID, iCertRequest,
CRYPT_CERTINFO_FINGERPRINT_SHA );
if( cryptStatusError( status ) )
return( cryptArgError( status ) ? CAMGMT_ARGERROR_REQUEST : status );
/* We're ready to perform the cert issue transaction. First, we turn the
request into a cert */
setMessageCreateObjectInfo( &createInfo, CRYPT_CERTTYPE_CERTIFICATE );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_CERTIFICATE );
if( cryptStatusError( status ) )
return( status );
iLocalCertificate = createInfo.cryptHandle;
status = krnlSendMessage( iLocalCertificate, IMESSAGE_SETATTRIBUTE,
( void * ) &iCertRequest,
CRYPT_CERTINFO_CERTREQUEST );
if( cryptStatusError( status ) )
{
krnlSendNotifier( iLocalCertificate, IMESSAGE_DECREFCOUNT );
return( status );
}
/* Sanitise the new cert of potentially dangerous attributes. For our
use we clear all CA and CA-equivalent attributes to prevent users
from submitting requests that turn them into CAs */
setMessageCreateObjectInfo( &createInfo, CRYPT_CERTTYPE_CERTIFICATE );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -