📄 s_scep.c
字号:
/* Get an SCEP CA cert */
static int getScepCACert( const C_STR caCertUrl,
CRYPT_CERTIFICATE *cryptCACert )
{
CRYPT_KEYSET cryptKeyset;
int status;
status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_HTTP,
caCertUrl, CRYPT_KEYOPT_READONLY );
if( cryptStatusOK( status ) )
{
status = cryptGetPublicKey( cryptKeyset, cryptCACert, CRYPT_KEYID_NAME,
TEXT( "[None]" ) );
cryptKeysetClose( cryptKeyset );
}
if( cryptStatusError( status ) )
return( extErrorExit( cryptKeyset, "cryptGetPublicKey()",
status, __LINE__ ) );
return( TRUE );
}
/* Perform an SCEP test */
static int connectSCEP( const BOOLEAN localSession,
const BOOLEAN userSuppliesCACert )
{
CRYPT_SESSION cryptSession;
CRYPT_CERTIFICATE cryptRequest, cryptResponse, cryptCACert;
CRYPT_CONTEXT cryptContext;
#if ( SCEP_NO == 1 )
C_CHR userID[ 64 ], password[ 64 ];
#endif /* cryptlib SCEP_NO == 1 */
const C_STR userPtr = scepInfo[ SCEP_NO ].user;
const C_STR passwordPtr = scepInfo[ SCEP_NO ].password;
int status;
printf( "Testing %s SCEP session%s...\n", scepInfo[ SCEP_NO ].name,
userSuppliesCACert ? "" : " with CA cert read" );
/* Wait for the server to finish initialising */
if( localSession && waitMutex() == CRYPT_ERROR_TIMEOUT )
{
printf( "Timed out waiting for server to initialise, line %d.\n",
__LINE__ );
return( FALSE );
}
#if ( SCEP_NO == 1 )
/* If we're doing a loopback test, make sure that the required user info
is present. If it isn't, the CA auditing will detect a request from
a nonexistant user and refuse to issue a certificate */
if( !pkiGetUserInfo( NULL, NULL, NULL, TEXT( "Test SCEP PKI user" ) ) )
{
puts( "CA certificate store doesn't contain the PKI user "
"information needed to\nauthenticate certificate issue "
"operations, can't perform SCEP test.\n" );
return( CRYPT_ERROR_NOTAVAIL );
}
#endif /* cryptlib SCEP_NO == 1 */
/* Get the issuing CA's cert if required */
if( userSuppliesCACert )
{
if( scepInfo[ SCEP_NO ].caCertUrl != NULL )
{
if( !getScepCACert( scepInfo[ SCEP_NO ].caCertUrl,
&cryptCACert ) )
return( FALSE );
}
else
{
status = importCertFromTemplate( &cryptCACert,
SCEP_CA_FILE_TEMPLATE, SCEP_NO );
if( cryptStatusError( status ) )
{
printf( "Couldn't get SCEP CA certificate, status = %d, "
"line %d.\n", status, __LINE__ );
return( FALSE );
}
}
}
/* cryptlib implements per-user (rather than shared interop) IDs and
passwords so we need to read the user ID and password information
before we can perform any operations */
#if ( SCEP_NO == 1 )
status = pkiGetUserInfo( userID, password, NULL,
TEXT( "Test SCEP PKI user" ) );
if( !status || status == CRYPT_ERROR_NOTAVAIL )
{
if( userSuppliesCACert )
cryptDestroyCert( cryptCACert );
/* If cert store operations aren't available, exit but continue with
other tests, otherwise abort the tests */
return( ( status == CRYPT_ERROR_NOTAVAIL ) ? TRUE : FALSE );
}
userPtr = userID;
passwordPtr = password;
#endif /* cryptlib SCEP_NO == 1 */
/* Create the SCEP session */
status = cryptCreateSession( &cryptSession, CRYPT_UNUSED,
CRYPT_SESSION_SCEP );
if( status == CRYPT_ERROR_PARAM3 ) /* SCEP session access not available */
return( CRYPT_ERROR_NOTAVAIL );
if( cryptStatusError( status ) )
{
printf( "cryptCreateSession() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
/* Set up the user and server information */
status = cryptSetAttributeString( cryptSession,
CRYPT_SESSINFO_USERNAME,
userPtr, paramStrlen( userPtr ) );
if( cryptStatusOK( status ) )
status = cryptSetAttributeString( cryptSession,
CRYPT_SESSINFO_PASSWORD,
passwordPtr, paramStrlen( passwordPtr ) );
if( cryptStatusOK( status ) )
status = cryptSetAttributeString( cryptSession,
CRYPT_SESSINFO_SERVER_NAME,
scepInfo[ SCEP_NO ].url,
paramStrlen( scepInfo[ SCEP_NO ].url ) );
if( userSuppliesCACert )
{
if( cryptStatusOK( status ) )
status = cryptSetAttribute( cryptSession,
CRYPT_SESSINFO_CACERTIFICATE,
cryptCACert );
cryptDestroyCert( cryptCACert );
}
if( cryptStatusError( status ) )
{
printf( "Addition of SCEP user/server information failed with error "
"code %d, line %d.\n", status, __LINE__ );
return( FALSE );
}
/* Create the (unsigned) PKCS #10 request */
#if ( SCEP_NO == 1 )
status = cryptCreateContext( &cryptContext, CRYPT_UNUSED,
CRYPT_ALGO_RSA );
if( cryptStatusError( status ) )
return( FALSE );
cryptSetAttributeString( cryptContext, CRYPT_CTXINFO_LABEL,
USER_PRIVKEY_LABEL,
paramStrlen( USER_PRIVKEY_LABEL ) );
status = cryptGenerateKey( cryptContext );
if( cryptStatusOK( status ) )
#else
loadRSAContextsEx( CRYPT_UNUSED, NULL, &cryptContext, NULL,
USER_PRIVKEY_LABEL );
#endif /* cryptlib SCEP_NO == 1 */
status = cryptCreateCert( &cryptRequest, CRYPT_UNUSED,
CRYPT_CERTTYPE_CERTREQUEST );
if( cryptStatusOK( status ) )
status = cryptSetAttribute( cryptRequest,
CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptContext );
if( cryptStatusOK( status ) && \
!addCertFields( cryptRequest, scepRequestData, __LINE__ ) )
status = CRYPT_ERROR_FAILED;
#if 0
if( cryptStatusOK( status ) )
status = cryptSignCert( cryptRequest, cryptContext );
#endif
if( cryptStatusError( status ) )
{
printf( "Creation of PKCS #10 request failed with error code %d, "
"line %d.\n", status, __LINE__ );
return( FALSE );
}
/* Set up the private key and request, and activate the session */
status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_PRIVATEKEY,
cryptContext );
cryptDestroyContext( cryptContext );
if( cryptStatusOK( status ) )
status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_REQUEST,
cryptRequest );
cryptDestroyCert( cryptRequest );
if( cryptStatusError( status ) )
{
printf( "cryptSetAttribute() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );
if( cryptStatusError( status ) )
{
printExtError( cryptSession, "Attempt to activate SCEP client "
"session", status, __LINE__ );
cryptDestroySession( cryptSession );
if( status == CRYPT_ERROR_OPEN || status == CRYPT_ERROR_READ )
{
/* These servers are constantly appearing and disappearing so if
we get a straight connect error we don't treat it as a serious
failure */
puts( " (Server could be down, faking it and continuing...)\n" );
return( CRYPT_ERROR_FAILED );
}
return( FALSE );
}
/* Print the session security information */
printFingerprint( cryptSession, FALSE );
/* Obtain the response information */
status = cryptGetAttribute( cryptSession, CRYPT_SESSINFO_RESPONSE,
&cryptResponse );
if( cryptStatusOK( status ) && !userSuppliesCACert )
status = cryptGetAttribute( cryptSession, CRYPT_SESSINFO_RESPONSE,
&cryptCACert );
cryptDestroySession( cryptSession );
if( cryptStatusError( status ) )
{
printf( "cryptGetAttribute() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
#if ( SCEP_NO != 1 )
puts( "Returned certificate details are:" );
printCertInfo( cryptResponse );
if( !userSuppliesCACert )
{
puts( "Returned CA certificate details are:" );
printCertInfo( cryptCACert );
}
#endif /* Keep the cryptlib results on one screen */
/* Clean up */
cryptDestroyCert( cryptResponse );
cryptDestroyCert( cryptCACert );
puts( "SCEP client session succeeded.\n" );
return( TRUE );
}
int testSessionSCEP( void )
{
return( connectSCEP( FALSE, TRUE ) );
}
int testSessionSCEPCACert( void )
{
return( connectSCEP( FALSE, FALSE ) );
}
int testSessionSCEPServer( void )
{
CRYPT_SESSION cryptSession;
CRYPT_CONTEXT cryptCAKey;
CRYPT_KEYSET cryptCertStore;
int status;
puts( "SVR: Testing SCEP server session ..." );
/* Perform a test create of a SCEP server session to verify that we can
do this test */
status = cryptCreateSession( &cryptSession, CRYPT_UNUSED,
CRYPT_SESSION_SCEP_SERVER );
if( status == CRYPT_ERROR_PARAM3 ) /* SCEP session access not available */
return( CRYPT_ERROR_NOTAVAIL );
if( cryptStatusError( status ) )
{
printf( "SVR: cryptCreateSession() failed with error code %d, "
"line %d.\n", status, __LINE__ );
return( FALSE );
}
cryptDestroySession( cryptSession );
/* Set up the server-side objects */
if( !pkiServerInit( &cryptCAKey, &cryptCertStore, SCEPCA_PRIVKEY_FILE,
USER_PRIVKEY_LABEL, scepPkiUserData, NULL, "SCEP" ) )
return( FALSE );
/* Create the SCEP session and add the CA key and cert store */
status = cryptCreateSession( &cryptSession, CRYPT_UNUSED,
CRYPT_SESSION_SCEP_SERVER );
if( cryptStatusError( status ) )
{
printf( "SVR: cryptCreateSession() failed with error code %d, line "
"%d.\n", status, __LINE__ );
return( FALSE );
}
status = cryptSetAttribute( cryptSession,
CRYPT_SESSINFO_PRIVATEKEY, cryptCAKey );
if( cryptStatusOK( status ) )
status = cryptSetAttribute( cryptSession,
CRYPT_SESSINFO_KEYSET, cryptCertStore );
if( cryptStatusError( status ) )
return( attrErrorExit( cryptSession, "SVR: cryptSetAttribute()",
status, __LINE__ ) );
/* Tell the client that we're ready to go */
releaseMutex();
/* Activate the session */
status = activatePersistentServerSession( cryptSession, FALSE );
if( cryptStatusError( status ) )
{
cryptKeysetClose( cryptCertStore );
cryptDestroyContext( cryptCAKey );
return( extErrorExit( cryptSession, "SVR: Attempt to activate SCEP "
"server session", status, __LINE__ ) );
}
/* Clean up */
cryptDestroySession( cryptSession );
cryptKeysetClose( cryptCertStore );
cryptDestroyContext( cryptCAKey );
puts( "SVR: SCEP session succeeded.\n" );
return( TRUE );
}
/* Perform a client/server loopback test */
#ifdef WINDOWS_THREADS
unsigned __stdcall scepServerThread( void *dummy )
{
acquireMutex();
testSessionSCEPServer();
_endthreadex( 0 );
return( 0 );
}
int testSessionSCEPClientServer( void )
{
HANDLE hThread;
unsigned threadID;
int status;
#if ( SCEP_NO != 1 )
/* Because the code has to handle so many CA-specific peculiarities, we
can only perform this test when the CA being used is the cryptlib
CA */
puts( "Error: The local SCEP session test only works with SCEP_NO == 1." );
return( FALSE );
#endif /* cryptlib CA */
/* Start the server and wait for it to initialise */
createMutex();
hThread = ( HANDLE ) _beginthreadex( NULL, 0, scepServerThread,
NULL, 0, &threadID );
Sleep( 1000 );
/* Connect to the local server */
status = connectSCEP( TRUE, TRUE );
waitForThread( hThread );
destroyMutex();
return( status );
}
int testSessionSCEPCACertClientServer( void )
{
HANDLE hThread;
unsigned threadID;
int status;
#if ( SCEP_NO != 1 )
/* Because the code has to handle so many CA-specific peculiarities, we
can only perform this test when the CA being used is the cryptlib
CA */
puts( "Error: The local SCEP session test only works with SCEP_NO == 1." );
return( FALSE );
#endif /* cryptlib CA */
/* Start the server and wait for it to initialise */
createMutex();
hThread = ( HANDLE ) _beginthreadex( NULL, 0, scepServerThread,
NULL, 0, &threadID );
Sleep( 1000 );
/* Connect to the local server */
status = connectSCEP( TRUE, FALSE );
waitForThread( hThread );
destroyMutex();
return( status );
}
#endif /* WINDOWS_THREADS */
#endif /* TEST_SESSION || TEST_SESSION_LOOPBACK */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -