📄 ca_add.c
字号:
dbmsUpdate( NULL, NULL, 0, 0, DBMS_UPDATE_ABORT );
return( status );
}
/* Delete a PKI user from the cert store */
int caDeletePKIUser( DBMS_INFO *dbmsInfo, const CRYPT_KEYID_TYPE keyIDtype,
const void *keyID, const int keyIDlength )
{
CRYPT_CERTIFICATE iPkiUser;
char sqlBuffer[ MAX_SQL_QUERY_SIZE ];
char certID[ DBXKEYID_BUFFER_SIZE ];
int dummy, status;
assert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );
assert( keyIDtype == CRYPT_KEYID_NAME || keyIDtype == CRYPT_KEYID_URI );
assert( isReadPtr( keyID, keyIDlength ) );
/* Get info on the user that we're about to delete */
status = getItemData( dbmsInfo, &iPkiUser, &dummy, keyIDtype,
keyID, keyIDlength, KEYMGMT_ITEM_PKIUSER,
KEYMGMT_FLAG_NONE );
if( cryptStatusOK( status ) )
{
status = getKeyID( certID, iPkiUser,
CRYPT_CERTINFO_FINGERPRINT_SHA );
krnlSendNotifier( iPkiUser, IMESSAGE_DECREFCOUNT );
}
if( cryptStatusError( status ) )
return( status );
/* Delete the PKI user info and record the deletion */
dbmsFormatSQL( sqlBuffer,
"DELETE FROM pkiUsers WHERE certID = '$'",
certID );
status = dbmsUpdate( sqlBuffer, NULL, 0, 0, DBMS_UPDATE_BEGIN );
if( cryptStatusOK( status ) )
status = updateCertLog( dbmsInfo, CRYPT_CERTACTION_DELETEUSER,
NULL, NULL, certID, NULL, 0,
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 reqCertIDlength, certDataLength, status;
assert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );
assert( isHandleRangeValid( 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 );
if( cryptStatusError( status ) )
return( status );
}
/* Extract the information that we need from the cert request */
status = getKeyID( certID, iCertRequest,
CRYPT_CERTINFO_FINGERPRINT_SHA );
if( !cryptStatusError( status ) )
{
RESOURCE_DATA msgData;
setMessageData( &msgData, certData, MAX_CERT_SIZE );
status = krnlSendMessage( iCertRequest, IMESSAGE_CRT_EXPORT,
&msgData,
( requestType == CRYPT_CERTTYPE_REQUEST_REVOCATION ) ? \
CRYPT_ICERTFORMAT_DATA : CRYPT_CERTFORMAT_CERTIFICATE );
certDataLength = msgData.length;
}
if( cryptStatusOK( status ) )
{
status = reqCertIDlength = getKeyID( reqCertID, iCertRequest,
CRYPT_IATTRIBUTE_AUTHCERTID );
if( cryptStatusError( status ) )
{
/* If the request is being added directly by the user, there's no
authorising certificate/PKI user info present */
reqCertIDptr = NULL;
reqCertIDlength = 0;
status = CRYPT_OK;
}
}
if( cryptStatusError( status ) )
return( status );
/* Check that the PKI user who authorised this cert issue still exists.
If the CA has deleted them, all further requests for certs fail */
if( reqCertIDptr != NULL )
{
CRYPT_CERTIFICATE iPkiUser;
status = caGetIssuingUser( dbmsInfo, &iPkiUser, reqCertID,
reqCertIDlength );
if( cryptStatusOK( status ) )
krnlSendNotifier( iPkiUser, IMESSAGE_DECREFCOUNT );
else
{
reqCertID[ reqCertIDlength ] = '\0';
updateCertErrorLog( dbmsInfo, CRYPT_ERROR_DUPLICATE,
"Cert request submitted for nonexistant PKI "
"user", NULL, reqCertID, NULL, NULL, 0 );
return( CRYPT_ERROR_PERMISSION );
}
}
/* If there's an authorising PKI user present, make sure that it hasn't
already been used to authorise the issuance of a cert. This is
potentially vulnerable to the following race condition:
1: check authCertID -> OK
2: check authCertID -> OK
1: add
2: add
In theory we could detect this by requiring the reqCertID to be
unique, however a PKI user can be used to request both a cert and
a revocation for the cert, and a signing cert can be used to request
an update or revocation of both itself and one or more associated
encryption certs. We could probably handle this via the ID-mangling
used for certIDs, but this makes tracing events through the audit log
complex since there'll now be different effective IDs for the
authorising cert depending on what it was authorising. In addition
it's not certain how many further operations a cert (rather than a PKI
user) can authorise, in theory a single signing cert can authorise at
least four further operations, these being the update of itself, the
update of an associated encryption cert, and the revocation of itself
and the encryption cert. In addition its possible that a signing cert
could be used to authorise a series of short-duration encryption
certs, or a variety of other combinations of operations.
Because of these issues, we can't use a uniqueness constraint on the
reqCertID to enforce a single use of issuing authorisation by the
database ifself, but have to do a manual check here, checking
specifically for the case where a PKI user authorises a cert issue */
#if 0 /* This check is too restrictive because it blocks any further cert
issues after the first one. This is because as soon as a single
issue has been authorised for a user, there'll be a request for
that user logged so all further attempts to submit a request (for
example for a renewal, or an encryption cert to go with a signing
one) will fail */
if( reqCertIDptr != NULL )
{
status = dbmsQuery(
"SELECT certID FROM certLog WHERE reqCertID = ? "
"AND action = " TEXT_CERTACTION_REQUEST_CERT,
NULL, 0, reqCertID, reqCertIDlength, 0,
DBMS_CACHEDQUERY_NONE, DBMS_QUERY_CHECK );
if( cryptStatusOK( status ) )
{
/* This user has already authorised the issue of a cert, it
can't be used to issue a second cert */
reqCertID[ reqCertIDlength ] = '\0';
updateCertErrorLog( dbmsInfo, CRYPT_ERROR_DUPLICATE,
"Attempt to authorise additional cert issue "
"when a cert for this user has already been "
"issued", NULL, reqCertID, NULL, NULL, 0 );
return( CRYPT_ERROR_DUPLICATE );
}
}
#endif /* 0 */
/* Update the cert store. Since a revocation request generally won't
have any fields of any significance set, we have to use a special cut-
down insert statement that doesn't expect to find any fields except
the cert ID */
if( requestType == CRYPT_CERTTYPE_REQUEST_REVOCATION )
{
char sqlBuffer[ MAX_SQL_QUERY_SIZE ];
if( !hasBinaryBlobs( dbmsInfo ) )
{
char encodedCertData[ MAX_ENCODED_CERT_SIZE ];
int length;
length = base64encode( encodedCertData, MAX_ENCODED_CERT_SIZE,
certData, certDataLength,
CRYPT_CERTTYPE_NONE );
encodedCertData[ length ] = '\0';
dbmsFormatSQL( sqlBuffer,
"INSERT INTO certRequests VALUES ("
TEXT_CERTTYPE_REQUEST_REVOCATION ", '', '', '', '', '', '', "
"'', '$', '$')",
certID, encodedCertData );
}
else
{
dbmsFormatSQL( sqlBuffer,
"INSERT INTO certRequests VALUES ("
TEXT_CERTTYPE_REQUEST_REVOCATION ", '', '', '', '', '', '', "
"'', '$', ?)",
certID );
}
status = dbmsUpdate( sqlBuffer, hasBinaryBlobs( dbmsInfo ) ? \
certData : NULL, certDataLength, 0,
DBMS_UPDATE_BEGIN );
}
else
status = addCert( dbmsInfo, iCertRequest, CRYPT_CERTTYPE_REQUEST_CERT,
CERTADD_NORMAL, DBMS_UPDATE_BEGIN );
if( cryptStatusOK( status ) )
status = updateCertLog( dbmsInfo,
( requestType == CRYPT_CERTTYPE_REQUEST_REVOCATION ) ? \
CRYPT_CERTACTION_REQUEST_REVOCATION : \
( isRenewal ) ? \
CRYPT_CERTACTION_REQUEST_RENEWAL : \
CRYPT_CERTACTION_REQUEST_CERT,
certID, reqCertIDptr, NULL, certData,
certDataLength, DBMS_UPDATE_COMMIT );
else
/* Something went wrong, abort the transaction */
dbmsUpdate( NULL, NULL, 0, 0, DBMS_UPDATE_ABORT );
return( status );
}
#endif /* USE_DBMS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -