📄 ca_issue.c
字号:
&createInfo, OBJECT_TYPE_CERTIFICATE );
if( cryptStatusOK( status ) )
{
const CRYPT_CERTIFICATE iTemplateCertificate = createInfo.cryptHandle;
int value;
/* Add the CA flag, CA-equivalent values (in this case the old
Netscape usage flags, which (incredibly) are still used today by
some CAs in place of the X.509 keyUsage extension), and the CA
keyUsages, as disallowed values */
status = krnlSendMessage( iTemplateCertificate, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_TRUE, CRYPT_CERTINFO_CA );
if( cryptStatusOK( status ) )
{
value = CRYPT_NS_CERTTYPE_SSLCA | CRYPT_NS_CERTTYPE_SMIMECA | \
CRYPT_NS_CERTTYPE_OBJECTSIGNINGCA;
status = krnlSendMessage( iTemplateCertificate, IMESSAGE_SETATTRIBUTE,
&value, CRYPT_CERTINFO_NS_CERTTYPE );
}
if( cryptStatusOK( status ) )
{
value = CRYPT_KEYUSAGE_KEYCERTSIGN | CRYPT_KEYUSAGE_CRLSIGN;
status = krnlSendMessage( iTemplateCertificate, IMESSAGE_SETATTRIBUTE,
&value, CRYPT_CERTINFO_KEYUSAGE );
}
if( cryptStatusOK( status ) )
status = krnlSendMessage( iLocalCertificate, IMESSAGE_SETATTRIBUTE,
( void * ) &iTemplateCertificate,
CRYPT_IATTRIBUTE_BLOCKEDATTRS );
if( status == CRYPT_ERROR_INVALID )
/* If the request would have resulted in the creation of an
invalid cert, report it as an error with the request */
status = CAMGMT_ARGERROR_REQUEST;
krnlSendNotifier( iTemplateCertificate, IMESSAGE_DECREFCOUNT );
}
if( cryptStatusError( status ) )
{
krnlSendNotifier( iLocalCertificate, IMESSAGE_DECREFCOUNT );
return( status );
}
/* Finally, sign the cert */
status = krnlSendMessage( iLocalCertificate, IMESSAGE_CRT_SIGN, NULL,
caKey );
if( cryptStatusError( status ) )
{
krnlSendNotifier( iLocalCertificate, IMESSAGE_DECREFCOUNT );
return( ( status == CRYPT_ARGERROR_VALUE ) ? \
CAMGMT_ARGERROR_CAKEY : status );
}
/* Extract the information that we need from the newly-created cert */
status = getKeyID( certID, iLocalCertificate,
CRYPT_CERTINFO_FINGERPRINT_SHA );
if( !cryptStatusError( status ) )
status = getKeyID( issuerID, iLocalCertificate,
CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
if( !cryptStatusError( status ) )
{
RESOURCE_DATA msgData;
setMessageData( &msgData, certData, MAX_CERT_SIZE );
status = krnlSendMessage( iLocalCertificate, IMESSAGE_CRT_EXPORT,
&msgData, CRYPT_CERTFORMAT_CERTIFICATE );
certDataLength = msgData.length;
}
if( cryptStatusError( status ) )
{
krnlSendNotifier( iLocalCertificate, IMESSAGE_DECREFCOUNT );
return( status );
}
/* If we're doing a partial cert creation, handle the complexities
created by things like cert renewals that create pseudo-duplicates
while the update is taking place */
if( action == CRYPT_CERTACTION_CERT_CREATION )
{
/* Make sure that this cert hasn't been added yet. In theory we
wouldn't need to do this since the keyID uniqueness constraint
will catch duplicates, however duplicates are allowed for updates
and won't automatically be caught for partial adds because the
keyID has to be added in a special form to enable the completion
of the partial add to work. What we therefore need to check for
is that a partial add (which will add the keyID in special form)
won't in the future clash with a keyID in standard form. The
checking for a keyID clash in special form happens automagically
through the uniqueness constraint.
There are two special cases in which the issue can fail during
the completion rather than initial add phase, one is during an
update (which can't be avoided, since clashes are legal for this
and we can't resolve things until the completion phase), and the
other is through a race condition caused by the following sequence
of updates:
1: check keyID -> OK
2: check keyID -> OK
1: add as ESC1+keyID
1: issue as keyID
2: add as ESC1+keyID
2: issue -> fails
This condition will be fairly rare. Note that in neither case are
the integrity constraints of the cert issuing process violated,
the only thing that happens is that a failure due to duplicates
is detected at a later stage than it normally would be */
if( issueType == CERTADD_PARTIAL )
{
char keyID[ DBXKEYID_BUFFER_SIZE ];
int length;
status = length = getCertKeyID( keyID, iLocalCertificate );
if( !cryptStatusError( status ) )
status = cryptStatusOK( \
dbmsQuery( \
"SELECT certData FROM certificates WHERE keyID = ?",
NULL, NULL, keyID, length, 0,
DBMS_CACHEDQUERY_NONE,
DBMS_QUERY_CHECK ) ) ? \
CRYPT_ERROR_DUPLICATE : CRYPT_OK;
if( cryptStatusError( status ) )
{
krnlSendNotifier( iLocalCertificate, IMESSAGE_DECREFCOUNT );
return( status );
}
resetErrorInfo( dbmsInfo );
}
/* This is a partial add, make sure that the cert is added in the
appropriate manner */
addType = CERTADD_PARTIAL;
}
/* Update the cert store */
status = addCert( dbmsInfo, iLocalCertificate, CRYPT_CERTTYPE_CERTIFICATE,
addType, DBMS_UPDATE_BEGIN );
if( cryptStatusOK( status ) )
status = updateCertLog( dbmsInfo, action, certID, reqCertID, NULL,
certData, certDataLength,
DBMS_UPDATE_CONTINUE );
if( cryptStatusOK( status ) )
{
char sqlBuffer[ MAX_SQL_QUERY_SIZE ];
dbmsFormatSQL( sqlBuffer,
"DELETE FROM certRequests WHERE certID = '$'",
reqCertID );
status = dbmsUpdate( sqlBuffer, NULL, 0, 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,
( action == CRYPT_CERTACTION_ISSUE_CERT ) ? \
"Certificate issue operation failed" : \
"Certificate creation operation failed",
NULL, reqCertID, NULL, NULL, 0 );
krnlSendNotifier( iLocalCertificate, IMESSAGE_DECREFCOUNT );
return( status );
}
/* The cert has been successfully issued, return it to the caller if
necessary */
if( iCertificate != NULL )
*iCertificate = iLocalCertificate;
else
/* The caller isn't interested in the cert, destroy it */
krnlSendNotifier( iLocalCertificate, IMESSAGE_DECREFCOUNT );
return( CRYPT_OK );
}
/* Complete a previously-started cert issue */
int caIssueCertComplete( DBMS_INFO *dbmsInfo,
const CRYPT_CERTIFICATE iCertificate,
const CRYPT_CERTACTION_TYPE action )
{
char certID[ DBXKEYID_BUFFER_SIZE ];
int status;
assert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );
assert( isHandleRangeValid( iCertificate ) );
assert( action == CRYPT_CERTACTION_CERT_CREATION_COMPLETE || \
action == CRYPT_CERTACTION_CERT_CREATION_DROP || \
action == CRYPT_CERTACTION_CERT_CREATION_REVERSE );
/* Extract the information that we need from the cert */
status = getKeyID( certID, iCertificate, CRYPT_CERTINFO_FINGERPRINT_SHA );
if( cryptStatusError( status ) )
return( status );
/* If we're completing the certificate issue process, replace the
incomplete cert with the completed one and exit */
if( action == CRYPT_CERTACTION_CERT_CREATION_COMPLETE )
{
CERTADD_TYPE issueType;
status = getCertIssueType( dbmsInfo, iCertificate, TRUE );
if( !cryptStatusError( status ) )
{
issueType = status;
status = completeCert( dbmsInfo, iCertificate, issueType );
}
if( cryptStatusError( status ) )
return( status );
/* If we're doing a cert renewal, complete the multi-phase update
required to replace an existing cert */
if( issueType == CERTADD_PARTIAL_RENEWAL )
status = completeCertRenewal( dbmsInfo, iCertificate );
return( status );
}
/* If we're abandoning the certificate issue process, delete the
incomplete cert and exit */
if( action == CRYPT_CERTACTION_CERT_CREATION_DROP )
{
char sqlBuffer[ MAX_SQL_QUERY_SIZE ];
dbmsFormatSQL( sqlBuffer,
"DELETE FROM certificates WHERE certID = '" KEYID_ESC1 "$'",
certID + 2 );
status = dbmsUpdate( sqlBuffer, NULL, 0, 0, DBMS_UPDATE_BEGIN );
if( cryptStatusOK( status ) )
status = updateCertLog( dbmsInfo, action, NULL, NULL, certID,
NULL, 0, DBMS_UPDATE_COMMIT );
else
/* Something went wrong, abort the transaction */
dbmsUpdate( NULL, NULL, 0, 0, DBMS_UPDATE_ABORT );
if( cryptStatusOK( status ) )
return( CRYPT_OK );
/* The operation failed, record the details and fall back to a
straight delete */
updateCertErrorLog( dbmsInfo, status,
"Certificate creation - drop operation failed, "
"performing straight delete", NULL, NULL,
certID, NULL, 0 );
status = dbmsStaticUpdate( sqlBuffer );
if( cryptStatusError( status ) )
updateCertErrorLogMsg( dbmsInfo, status, "Fallback straight "
"delete failed" );
return( status );
}
/* We're reversing a cert creation, we need to explicitly revoke the cert
rather than just deleting it */
assert( action == CRYPT_CERTACTION_CERT_CREATION_REVERSE );
return( revokeCertDirect( dbmsInfo, iCertificate,
CRYPT_CERTACTION_CERT_CREATION_REVERSE ) );
}
#endif /* USE_DBMS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -