📄 certproc.c
字号:
return( TRUE );
if( isExpired && status == CRYPT_ERROR_INVALID )
{
puts( "The short-expiry-time certificate has already expired at "
"the time of issue.\nThis happened because there was a "
"delay of more than 5s between adding the\nrequest and "
"issuing the certificate for it. Try re-running the test "
"on a\nless-heavily-loaded system, or increase the expiry "
"delay to more than 5s." );
return( FALSE );
}
return( extErrorExit( cryptCertStore, "cryptCACertManagement()",
status, __LINE__ ) );
}
return( issueShouldFail ? FALSE : TRUE );
}
/* Issue a CRL. Although we can't do this directly (see the comment above
for the revocation request code) we can at least test the ability to
create an empty CRL (and if the CMP code has been run there will probably
be a few revocation entries present to fill the CRL) */
static int issueCRL( const CRYPT_KEYSET cryptCertStore,
const CRYPT_CONTEXT cryptCAKey )
{
CRYPT_CERTIFICATE cryptCRL;
int noEntries = 0, status;
/* Issue the CRL via the cert store */
status = cryptCACertManagement( &cryptCRL, CRYPT_CERTACTION_ISSUE_CRL,
cryptCertStore, cryptCAKey,
CRYPT_UNUSED );
if( cryptStatusError( status ) )
return( extErrorExit( cryptCertStore, "cryptCACertManagement()",
status, __LINE__ ) );
/* Print information on the CRL */
if( cryptStatusOK( cryptSetAttribute( cryptCRL,
CRYPT_CERTINFO_CURRENT_CERTIFICATE,
CRYPT_CURSOR_FIRST ) ) )
do
noEntries++;
while( cryptSetAttribute( cryptCRL,
CRYPT_CERTINFO_CURRENT_CERTIFICATE,
CRYPT_CURSOR_NEXT ) == CRYPT_OK );
printf( "CRL has %d entr%s.\n", noEntries,
( noEntries == 1 ) ? "y" : "ies" );
if( !noEntries )
puts( " (This is probably because there haven't been any revocation "
"entries added\n via the CMP test yet)." );
/* Clean up */
cryptDestroyCert( cryptCRL );
return( TRUE );
}
/* Fetch the issued cert that was created from a given cert template */
static CRYPT_CERTIFICATE getCertFromTemplate( const CRYPT_KEYSET cryptCertStore,
const CERT_DATA *certReqData )
{
CRYPT_CERTIFICATE cryptCert;
int i, status;
for( i = 0; certReqData[ i ].componentType != CRYPT_ATTRIBUTE_NONE; i++ )
if( certReqData[ i ].type == CRYPT_CERTINFO_COMMONNAME )
break;
status = cryptGetPublicKey( cryptCertStore, &cryptCert, CRYPT_KEYID_NAME,
certReqData[ i ].stringValue );
return( cryptStatusOK( status ) ? cryptCert : status );
}
int testCertManagement( void )
{
CRYPT_CERTIFICATE cryptCert, cryptCertRequest;
CRYPT_CONTEXT cryptCAKey;
CRYPT_KEYSET cryptCertStore;
time_t certTime;
int dummy, status;
puts( "Testing certificate management using cert store..." );
/* Get the CA's private key */
status = getPrivateKey( &cryptCAKey, CA_PRIVKEY_FILE,
CA_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );
if( cryptStatusError( status ) )
{
printf( "CA private key read failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
/* Create the cert store keyset with a check to make sure that this
access method exists so we can return an appropriate error message.
If the database table already exists, this will return a duplicate
data error so we retry the open with no flags to open the existing
database keyset for write access */
status = cryptKeysetOpen( &cryptCertStore, CRYPT_UNUSED,
CERTSTORE_KEYSET_TYPE, CERTSTORE_KEYSET_NAME,
CRYPT_KEYOPT_CREATE );
if( cryptStatusOK( status ) )
puts( "Created new certificate store '" CERTSTORE_KEYSET_NAME_ASCII
"'." );
if( status == CRYPT_ERROR_PARAM3 )
{
/* This type of keyset access isn't available, return a special error
code to indicate that the test wasn't performed, but that this
isn't a reason to abort processing */
cryptDestroyContext( cryptCAKey );
return( CRYPT_ERROR_NOTAVAIL );
}
if( status == CRYPT_ERROR_DUPLICATE )
status = cryptKeysetOpen( &cryptCertStore, CRYPT_UNUSED,
CERTSTORE_KEYSET_TYPE, CERTSTORE_KEYSET_NAME,
CRYPT_KEYOPT_NONE );
if( cryptStatusError( status ) )
{
printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
status, __LINE__ );
if( status == CRYPT_ERROR_OPEN )
{
cryptDestroyContext( cryptCAKey );
return( CRYPT_ERROR_FAILED );
}
return( FALSE );
}
/* Create a cert request, add it to the store, and destroy it, simulating
a delayed cert issue in which the request can't immediately be
converted into a cert. Then read the request back from the store and
issue a certificate based on it */
puts( "Issuing certificate for 'Test user 1'..." );
cryptCertRequest = addCertRequest( cryptCertStore, cert1Data, FALSE );
if( !cryptCertRequest )
return( FALSE );
cryptDestroyCert( cryptCertRequest );
status = cryptCAGetItem( cryptCertStore, &cryptCertRequest,
CRYPT_CERTTYPE_REQUEST_CERT, CRYPT_KEYID_NAME,
TEXT( "Test user 1" ) );
if( cryptStatusError( status ) )
return( extErrorExit( cryptCertStore, "cryptCAGetItem()", status,
__LINE__ ) );
status = cryptCACertManagement( &cryptCert, CRYPT_CERTACTION_ISSUE_CERT,
cryptCertStore, cryptCAKey,
cryptCertRequest );
cryptDestroyCert( cryptCertRequest );
if( cryptStatusError( status ) )
return( extErrorExit( cryptCertStore, "cryptCACertManagement()",
status, __LINE__ ) );
cryptDestroyCert( cryptCert );
/* Issue some more certs, this time directly from the request and without
bothering to obtain the resulting cert. The first two have a validity
time that expires in a few seconds so that we can use them to test
cert expiry processing, we issue these first to ensure that as much
time as possible passes due to other operations occurring before we
run the expiry. The second two are for revocation and CRL testing */
if( !issueCert( cryptCertStore, cryptCAKey, expiredCert1Data, TRUE, FALSE ) )
return( FALSE );
if( !issueCert( cryptCertStore, cryptCAKey, expiredCert2Data, TRUE, FALSE ) )
return( FALSE );
if( !issueCert( cryptCertStore, cryptCAKey, revokableCert1Data, FALSE, FALSE ) )
return( FALSE );
if( !issueCert( cryptCertStore, cryptCAKey, revokableCert2Data, FALSE, FALSE ) )
return( FALSE );
/* The following tests are specifically inserted at this point (rather
than at some other point in the test run) because they'll add some
further delay before the expiry operation */
/* Try and get a CA cert issued. This should fail, since new CAs can
only be created if the issuing CA specifies it (either directly when
it creates the cert manually or via the PKI user info), but never at
the request of the user */
if( !issueCert( cryptCertStore, cryptCAKey, certCAData, FALSE, TRUE ) )
{
printf( "Issue of cert from invalid request succeeded when it "
"should have failed,\nline %d.\n", __LINE__ );
return( FALSE );
}
/* Get a cert and (to-be-)revoked cert from the store and save them to
disk for later tests */
status = cryptCert = getCertFromTemplate( cryptCertStore, cert1Data );
if( !cryptStatusError( status ) )
{
BYTE fileName[ BUFFER_SIZE ];
FILE *filePtr;
int length;
/* First save the CA cert */
filenameFromTemplate( fileName, OCSP_CA_FILE_TEMPLATE, 1 );
status = cryptExportCert( certBuffer, BUFFER_SIZE, &length,
CRYPT_CERTFORMAT_CERTIFICATE,
cryptCAKey );
if( cryptStatusOK( status ) && \
( filePtr = fopen( fileName, "wb" ) ) != NULL )
{
fwrite( certBuffer, length, 1, filePtr );
fclose( filePtr );
}
/* Then the EE cert */
filenameFromTemplate( fileName, OCSP_EEOK_FILE_TEMPLATE, 1 );
status = cryptExportCert( certBuffer, BUFFER_SIZE, &length,
CRYPT_CERTFORMAT_CERTIFICATE,
cryptCert );
if( cryptStatusOK( status ) && \
( filePtr = fopen( fileName, "wb" ) ) != NULL )
{
fwrite( certBuffer, length, 1, filePtr );
fclose( filePtr );
}
cryptDestroyCert( cryptCert );
}
if( !cryptStatusError( status ) )
status = cryptCert = getCertFromTemplate( cryptCertStore,
revokableCert1Data );
if( !cryptStatusError( status ) )
{
BYTE fileName[ BUFFER_SIZE ];
FILE *filePtr;
int length;
filenameFromTemplate( fileName, OCSP_EEREV_FILE_TEMPLATE, 1 );
status = cryptExportCert( certBuffer, BUFFER_SIZE, &length,
CRYPT_CERTFORMAT_CERTIFICATE,
cryptCert );
if( cryptStatusOK( status ) && \
( filePtr = fopen( fileName, "wb" ) ) != NULL )
{
fwrite( certBuffer, length, 1, filePtr );
fclose( filePtr );
}
cryptDestroyCert( cryptCert );
}
if( cryptStatusError( status ) )
{
puts( "Issued certificates couldn't be fetched from the cert store "
"and written to\ndisk, the OCSP server test will abort when it "
"fails to find these\ncertificates." );
}
/* Issue a CRL. This will probably be a zero-length CRL unless we've run
the CMP tests because we can't directly revoke a cert. Again, we
perform it before the expiry test because it'll add some further
delay */
if( !issueCRL( cryptCertStore, cryptCAKey ) )
return( FALSE );
/* Get the most recent of the expired certs and wait for it to expire
if necessary */
status = cryptCert = getCertFromTemplate( cryptCertStore,
expiredCert1Data );
if( !cryptStatusError( status ) )
status = cryptGetAttributeString( cryptCert, CRYPT_CERTINFO_VALIDTO,
&certTime, &dummy );
if( cryptStatusError( status ) )
{
puts( "Couldn't get expiry information for expired cert." );
return( FALSE );
}
#ifndef _WIN32_WCE
if( certTime >= time( NULL ) )
{
printf( "Waiting for certificates to expire.." );
while( certTime >= time( NULL ) )
{
delayThread( 1 );
printf( "." );
}
puts( " done." );
}
#endif /* _WIN32_WCE */
cryptDestroyCert( cryptCert );
/* Expire the certs */
puts( "Expiring certificates..." );
status = cryptCACertManagement( NULL, CRYPT_CERTACTION_EXPIRE_CERT,
cryptCertStore, CRYPT_UNUSED,
CRYPT_UNUSED );
if( cryptStatusError( status ) )
return( extErrorExit( cryptCertStore, "cryptCACertManagement()",
status, __LINE__ ) );
/* Clean up */
cryptDestroyContext( cryptCAKey );
cryptKeysetClose( cryptCertStore );
puts( "Certificate management using cert store succeeded.\n" );
return( TRUE );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -