📄 dbxdca.c
字号:
return( status );
status = addCert( dbmsInfo, iCertificate, CRYPT_CERTTYPE_CERTIFICATE,
( addType == CERTADD_PARTIAL_RENEWAL ) ? \
CERTADD_PARTIAL_RENEWAL : CERTADD_NORMAL,
DBMS_UPDATE_BEGIN );
if( cryptStatusOK( status ) )
{
dbmsFormatSQL( sqlBuffer, ( addType == CERTADD_RENEWAL_COMPLETE ) ? \
"DELETE FROM certificates WHERE certID = '++$'" : \
"DELETE FROM certificates WHERE certID = '--$'",
certID + 2 );
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 */
static int completeCertRenewal( DBMS_INFO *dbmsInfo,
const CRYPT_CERTIFICATE iReplaceCertificate )
{
CRYPT_CERTIFICATE iOrigCertificate;
const char *keyName = getKeyName( CRYPT_IKEYID_KEYID );
char keyID[ DBXKEYID_BUFFER_SIZE ];
int dummy, status;
/* Extract the key ID from the new cert and use it to fetch the existing
cert issued for the same key */
status = getCertKeyID( keyID, iReplaceCertificate );
if( cryptStatusOK( status ) )
status = getItemData( dbmsInfo, &iOrigCertificate, &dummy,
keyName, keyID, 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 */
static int caIssueCert( DBMS_INFO *dbmsInfo,
const CRYPT_CERTIFICATE iCertificate,
const CRYPT_CERTIFICATE iCertRequest,
const CRYPT_CERTACTION_TYPE action )
{
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, status;
assert( isWritePtr( dbmsInfo, DBMS_INFO ) );
assert( checkHandleRange( iCertificate ) );
assert( checkHandleRange( iCertRequest ) );
assert( action == CRYPT_CERTACTION_ISSUE_CERT || \
action == CRYPT_CERTACTION_CERT_CREATION );
/* Extract the information that we need from the cert */
status = getKeyID( certID, iCertificate, CRYPT_CERTINFO_FINGERPRINT_SHA );
if( cryptStatusOK( status ) )
status = getKeyID( issuerID, iCertificate,
CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
if( cryptStatusOK( status ) )
{
RESOURCE_DATA msgData;
setMessageData( &msgData, certData, MAX_CERT_SIZE );
status = krnlSendMessage( iCertificate, IMESSAGE_CRT_EXPORT,
&msgData, CRYPT_CERTFORMAT_CERTIFICATE );
certDataLength = msgData.length;
}
if( cryptStatusOK( status ) )
status = getKeyID( reqCertID, iCertRequest,
CRYPT_CERTINFO_FINGERPRINT_SHA );
if( cryptStatusError( status ) )
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 --keyID
1: issue as keyID
2: add as --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 */
status = getCertIssueType( dbmsInfo, iCertRequest, FALSE );
if( status == CERTADD_PARTIAL )
{
char sqlBuffer[ MAX_SQL_QUERY_SIZE ];
char keyID[ DBXKEYID_BUFFER_SIZE ];
status = getCertKeyID( keyID, iCertificate );
if( cryptStatusError( status ) )
return( status );
dbmsFormatSQL( sqlBuffer,
"SELECT certData FROM certificates WHERE keyID = '$'",
keyID );
status = cryptStatusOK( dbmsStaticQuery( sqlBuffer, \
DBMS_QUERY_CHECK ) ) ? \
CRYPT_ERROR_DUPLICATE : CRYPT_OK;
}
if( cryptStatusError( status ) )
return( status );
/* 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, iCertificate, 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 );
return( status );
}
/* Complete a previously-started cert issue */
static int caIssueCertComplete( DBMS_INFO *dbmsInfo,
const CRYPT_CERTIFICATE iCertificate,
const CRYPT_CERTACTION_TYPE action )
{
char certID[ DBXKEYID_BUFFER_SIZE ];
int status;
assert( isWritePtr( dbmsInfo, DBMS_INFO ) );
assert( checkHandleRange( iCertificate ) );
assert( action == CRYPT_CERTACTION_CERT_CREATION_COMPLETE || \
action == CRYPT_CERTACTION_CERT_CREATION_DROP || \
action == CRYPT_CERTACTION_CERT_CREATION_REVERSE );
/* Extract the information we need from the cert */
status = getKeyID( certID, iCertificate, CRYPT_CERTINFO_FINGERPRINT_SHA );
if( cryptStatusError( status ) )
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 = '--$'",
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 );
}
/* 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 );
}
/* 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 ) );
}
/****************************************************************************
* *
* Cert Add Functions *
* *
****************************************************************************/
/* Add a new PKI user to the cert store */
int caAddPKIUser( DBMS_INFO *dbmsInfo, const CRYPT_CERTIFICATE iPkiUser )
{
RESOURCE_DATA msgData;
BYTE certData[ MAX_CERT_SIZE ];
char certID[ DBXKEYID_BUFFER_SIZE ];
int certDataLength, status;
assert( isWritePtr( dbmsInfo, DBMS_INFO ) );
assert( checkHandleRange( iPkiUser ) );
/* Extract the information we need from the PKI user object. In
addition to simply obtaining the information for logging purposes we
also need to perform this action to tell the cert management code to
fill in the remainder of the (implicitly-added) user info before we
start querying fields as we add it to the cert store. Because of this
we also need to place the certID read after the object export, since
it's in an incomplete state before this point */
setMessageData( &msgData, certData, MAX_CERT_SIZE );
status = krnlSendMessage( iPkiUser, IMESSAGE_CRT_EXPORT, &msgData,
CRYPT_ICERTFORMAT_DATA );
if( cryptStatusOK( status ) )
status = getKeyID( certID, iPkiUser, CRYPT_CERTINFO_FINGERPRINT_SHA );
if( cryptStatusError( status ) )
return( status );
certDataLength = msgData.length;
/* Update the cert store */
status = addCert( dbmsInfo, iPkiUser, CRYPT_CERTTYPE_PKIUSER,
CERTADD_NORMAL, DBMS_UPDATE_BEGIN );
if( cryptStatusOK( status ) )
status = updateCertLog( dbmsInfo, CRYPT_CERTACTION_ADDUSER, certID,
NULL, NULL, certData, certDataLength,
DBMS_UPDATE_COMMIT );
else
/* Something went wrong, abort the transaction */
dbmsUpdate( NULL, NULL, 0, 0, DBMS_UPDATE_ABORT );
return( status );
}
/* Add a cert issue or revocation request to the cert store */
int caAddCertRequest( DBMS_INFO *dbmsInfo,
const CRYPT_CERTIFICATE iCertRequest,
const CRYPT_CERTTYPE_TYPE requestType,
const BOOLEAN isRenewal )
{
BYTE certData[ MAX_CERT_SIZE ];
char certID[ DBXKEYID_BUFFER_SIZE ];
char reqCertID[ DBXKEYID_BUFFER_SIZE ], *reqCertIDptr = reqCertID;
int certDataLength, status;
assert( isWritePtr( dbmsInfo, DBMS_INFO ) );
assert( checkHandleRange( iCertRequest ) );
assert( requestType == CRYPT_CERTTYPE_CERTREQUEST || \
requestType == CRYPT_CERTTYPE_REQUEST_CERT || \
requestType == CRYPT_CERTTYPE_REQUEST_REVOCATION );
/* Make sure that the request is OK, and if it's a revocation request
make sure that it refers to a cert which is both present in the store
and currently active */
if( !checkRequest( iCertRequest, CRYPT_CERTACTION_NONE ) )
return( CRYPT_ARGERROR_NUM1 );
if( requestType == CRYPT_CERTTYPE_REQUEST_REVOCATION )
{
status = checkRevRequest( dbmsInfo, iCertRequest );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -