📄 testsess.c
字号:
the SmartTrust server name below to override the AIA value.
#3 - Identrus aka Xetex:
AuthorityInfoAccess doesn't match the real server URL, requires
the Xetex server name below to override the AIA value.
#4 - Thawte aka Valicert
No AuthorityInfoAccess, requires the Valicert server name below
to provide a server
#5 - Verisign
No AuthorityInfoAccess, requires the Verisign server name below
to provide a server */
#define OCSP_SERVER_NO 5
#if OCSP_SERVER_NO == 2
#define OCSP_SERVER_NAME "http://ocsp.smarttrust.com:82/ocsp"
#elif OCSP_SERVER_NO == 3
#define OCSP_SERVER_NAME "http://ocsp.xetex.com:8080/servlet/ocsp"
#elif OCSP_SERVER_NO == 4
#define OCSP_SERVER_NAME "http://ocsp2.valicert.net"
#elif OCSP_SERVER_NO == 5
#define OCSP_SERVER_NAME "http://ocsp.verisign.com/ocsp/status"
#endif /* OCSP server name kludge */
/* Perform an OCSP test */
static int connectOCSP( const CRYPT_SESSION_TYPE sessionType,
const BOOLEAN revokedCert,
const BOOLEAN multipleCerts,
const BOOLEAN localSession )
{
CRYPT_SESSION cryptSession;
CRYPT_CERTIFICATE cryptOCSPRequest, cryptOCSPResponse;
const BOOLEAN isServer = ( sessionType == CRYPT_SESSION_OCSP_SERVER ) ? \
TRUE : FALSE;
int status;
printf( "Testing %sOCSP %ssession...\n", localSession ? "local " : "",
isServer ? "server " : "client " );
/* Create the OCSP session */
status = cryptCreateSession( &cryptSession, CRYPT_UNUSED, sessionType );
if( status == CRYPT_ERROR_PARAM3 ) /* OCSP 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 );
}
if( isServer )
{
CRYPT_CONTEXT cryptPrivateKey;
CRYPT_KEYSET cryptCertStore;
if( !setLocalConnect( cryptSession, 80, TRUE ) )
return( FALSE );
/* Add the responder private key */
status = getPrivateKey( &cryptPrivateKey, SERVER_PRIVKEY_FILE,
USER_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );
if( cryptStatusOK( status ) )
{
status = cryptSetAttribute( cryptSession,
CRYPT_SESSINFO_PRIVATEKEY, cryptPrivateKey );
cryptDestroyContext( cryptPrivateKey );
}
if( cryptStatusError( status ) )
return( attrErrorExit( cryptSession, "cryptSetAttribute()",
status, __LINE__ ) );
/* Add the cert store which we'll be using to provide revocation
information */
status = cryptKeysetOpen( &cryptCertStore, CRYPT_UNUSED,
DATABASE_KEYSET_TYPE, CERTSTORE_KEYSET_NAME,
CRYPT_KEYOPT_READONLY );
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 */
puts( "No certificate store available, aborting OCSP responder "
"test.\n" );
cryptDestroySession( cryptSession );
return( CRYPT_ERROR_NOTAVAIL );
}
if( cryptStatusOK( status ) )
{
status = cryptSetAttribute( cryptSession,
CRYPT_SESSINFO_KEYSET, cryptCertStore );
cryptKeysetClose( cryptCertStore );
}
if( cryptStatusError( status ) )
return( attrErrorExit( cryptSession, "cryptSetAttribute()",
status, __LINE__ ) );
}
else
{
/* Create the OCSP request */
if( !initOCSP( &cryptOCSPRequest, localSession ? 1 : OCSP_SERVER_NO,
( OCSP_SERVER_NO == 1 || localSession ) ? TRUE : FALSE,
revokedCert, multipleCerts, CRYPT_UNUSED ) )
return( FALSE );
/* Set up the server information and activate the session. In
theory the OCSP request will contain all the information needed
for the session so there'd be nothing else to add before we
activate it, however many certs contain incorrect server URLs so
we set the server name manually if necessary, overriding the
value present in the OCSP request (via the cert) */
status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_REQUEST,
cryptOCSPRequest );
if( cryptStatusError( status ) )
return( attrErrorExit( cryptSession, "cryptSetAttribute()",
status, __LINE__ ) );
cryptDestroyCert( cryptOCSPRequest );
if( localSession && !setLocalConnect( cryptSession, 80, FALSE ) )
return( FALSE );
#ifdef OCSP_SERVER_NAME
if( !localSession )
{
printf( "Setting OCSP server to %s.\n", OCSP_SERVER_NAME );
status = cryptSetAttributeString( cryptSession,
CRYPT_SESSINFO_SERVER_NAME, OCSP_SERVER_NAME,
strlen( OCSP_SERVER_NAME ) );
if( cryptStatusError( status ) )
return( attrErrorExit( cryptSession,
"cryptSetAttributeString()", status,
__LINE__ ) );
}
#endif /* Kludges for incorrect authorityInfoAccess values */
if( OCSP_SERVER_NO == 1 || localSession )
{
/* The cryptlib server doesn't handle the weird v1 certIDs */
status = cryptSetAttribute( cryptSession,
CRYPT_SESSINFO_PROTOCOLVERSION, 2 );
if( cryptStatusError( status ) )
return( attrErrorExit( cryptSession, "cryptSetAttribute()",
status, __LINE__ ) );
}
}
status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );
if( isServer )
printConnectInfo( cryptSession );
if( cryptStatusError( status ) )
{
printExtError( cryptSession, isServer ? \
"Attempt to activate OCSP server session" : \
"Attempt to activate OCSP client session", status,
__LINE__ );
cryptDestroySession( cryptSession );
if( status == CRYPT_ERROR_OPEN || status == CRYPT_ERROR_BUSY || \
status == CRYPT_ERROR_PERMISSION )
{
/* These servers are constantly appearing and disappearing so if
we get a straight connect error we don't treat it as a serious
failure. In addition we can get server busy and no permission
to access errors which are also treated as soft errors */
puts( " (Server could be down or busy or unavailable, faking it "
"and continuing...)\n" );
return( CRYPT_ERROR_FAILED );
}
return( FALSE );
}
/* Obtain the response information */
if( !isServer )
{
status = cryptGetAttribute( cryptSession, CRYPT_SESSINFO_RESPONSE,
&cryptOCSPResponse );
if( cryptStatusError( status ) )
{
printf( "cryptGetAttribute() failed with error code %d, line "
"%d.\n", status, __LINE__ );
return( FALSE );
}
printCertInfo( cryptOCSPResponse );
}
/* There are so many weird ways to delegate trust and signing authority
mentioned in the OCSP RFC without any indication of which one
implementors will follow that we can't really perform any sort of
automated check since every responder seems to interpret this
differently, and many require manual installation of responder certs
in order to function */
#if 0
status = cryptCheckCert( cryptOCSPResponse , CRYPT_UNUSED );
if( cryptStatusError( status ) )
return( attrErrorExit( cryptOCSPResponse , "cryptCheckCert()",
status, __LINE__ ) );
#endif /* 0 */
cryptDestroyCert( cryptOCSPResponse );
/* Clean up */
status = cryptDestroySession( cryptSession );
if( cryptStatusError( status ) )
{
printf( "cryptDestroySession() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
puts( isServer ? "OCSP server session succeeded.\n" : \
"OCSP client session succeeded.\n" );
return( TRUE );
}
int testSessionOCSP( void )
{
if( !connectOCSP( CRYPT_SESSION_OCSP, FALSE, FALSE, FALSE ) )
return( FALSE );
#if OCSP_SERVER_NO == 1
if( !( connectOCSP( CRYPT_SESSION_OCSP, TRUE, FALSE, FALSE ) ) )
return( FALSE );
return( connectOCSP( CRYPT_SESSION_OCSP, FALSE, TRUE, FALSE ) );
#else
return( TRUE );
#endif /* Server which has a revoked cert */
}
int testSessionOCSPServer( void )
{
return( connectOCSP( CRYPT_SESSION_OCSP_SERVER, FALSE, FALSE, FALSE ) );
}
/* Perform a local client/server test */
#ifdef WINDOWS_THREADS
unsigned __stdcall ocspServerThread( void *dummy )
{
connectOCSP( CRYPT_SESSION_OCSP_SERVER, FALSE, FALSE, TRUE );
_endthreadex( 0 );
return( 0 );
}
int testSessionOCSPClientServer( void )
{
HANDLE hThread;
unsigned threadID;
int status;
/* Start the server and wait for it to initialise */
hThread = ( HANDLE ) _beginthreadex( NULL, 0, &ocspServerThread,
NULL, 0, &threadID );
Sleep( 1000 );
/* Connect to the local server */
status = connectOCSP( CRYPT_SESSION_OCSP, FALSE, FALSE, TRUE );
if( WaitForSingleObject( hThread, 15000 ) == WAIT_TIMEOUT )
{
puts( "Warning: Server thread is still active due to session "
"negotiation failure,\n this will cause an error "
"condition when cryptEnd() is called due\n to "
"resources remaining allocated. Press a key to continue." );
getchar();
}
CloseHandle( hThread );
return( status );
}
#endif /* WINDOWS_THREADS */
/****************************************************************************
* *
* TSP Routines Test *
* *
****************************************************************************/
/* There are various test OCSP servers running, the following remapping
allows us to switch between them. Implementation peculiarities:
#1 - cryptlib:
None
#2 - Peter Sylvester
None
#3 - Timeproof
None
#4 - ????
#5 - IAIK Graz
Never been seen active */
#define TSP_SERVER1_NAME "localhost"
#define TSP_SERVER2_NAME "http://www.edelweb.fr/cgi-bin/tspservice"
#define TSP_SERVER3_NAME "test.timeproof.de"
#define TSP_SERVER4_NAME "203.238.37.132:3318"
#define TSP_SERVER5_NAME "193.171.241.44:318"
#define TSP_SERVER_NAME TSP_SERVER3_NAME
/* Perform a timestamping test */
static int connectTSP( const CRYPT_SESSION_TYPE sessionType,
const CRYPT_HANDLE externalCryptContext,
const BOOLEAN localSession )
{
CRYPT_SESSION cryptSession;
CRYPT_CONTEXT hashContext;
const BOOLEAN isServer = ( sessionType == CRYPT_SESSION_TSP_SERVER ) ? \
TRUE : FALSE;
int status;
printf( "Testing %sTSP %ssession...\n", localSession ? "local " : "",
isServer ? "server " : "" );
/* Create the TSP session */
status = cryptCreateSession( &cryptSession, CRYPT_UNUSED, sessionType );
if( status == CRYPT_ERROR_PARAM3 ) /* TSP 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 );
}
if( isServer )
{
CRYPT_CONTEXT privateKey = externalCryptContext;
if( !setLocalConnect( cryptSession, 318, TRUE ) )
return( FALSE );
if( externalCryptContext == CRYPT_UNUSED )
status = getPrivateKey( &privateKey, TSA_PRIVKEY_FILE,
USER_PRIVKEY_LABEL,
TEST_PRIVKEY_PASSWORD );
if( cryptStatusOK( status ) )
{
status = cryptSetAttribute( cryptSession,
CRYPT_SESSINFO_PRIVATEKEY, privateKey );
if( externalCryptContext == CRYPT_UNUSED )
cryptDestroyContext( privateKey );
}
#ifdef __UNIX__
/* If we're running under Unix, set the port to a nonprivileged
one so we don't have to run as root */
if( cryptStatusOK( status ) )
status = cryptSetAttribute( cryptSession,
CRYPT_SESSINFO_SERVER_PORT, 3318 );
#endif /* __UNIX__ */
}
else
{
/* Create the hash value to add to the TSP request */
cryptCreateContext( &hashContext, CRYPT_UNUSED, CRYPT_ALGO_SHA );
cryptEncrypt( hashContext, "12345678", 8 );
cryptEncrypt( hashContext, "", 0 );
/* Set up the server information and activate the session */
status = cryptSetAttribute( cryptSession,
CRYPT_SESSINFO_TSP_MSGIMPRINT, hashContext );
if( cryptStatusError( status ) )
{
printf( "cryptSetAttribute() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
cryptDestroyContext( hashContext );
if( localSession )
{
if( !setLocalConnect( cryptSession, 318, FALSE ) )
return( FALSE );
}
else
status = cryptSetAttributeString( cryptSession,
CRYPT_SESSINFO_SERVER_NAME, TSP_SERVER_NAME,
strlen( TSP_SERVER_NAME ) );
}
if( cryptStatusError( status ) )
{
printf( "cryptSetAttribute/cryptSetAttributeString() failed with "
"error code %d, line %d.\n", status, __LINE__ );
return( FALSE );
}
status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );
if( isServer )
printConnectInfo( cryptSession );
if( cryptStatusError( status ) )
{
printExtError( cryptSession, isServer ? \
"Attempt to activate TSP server session" : \
"Attempt to activate TSP client session", status,
__LINE__ );
cryptDestroySession( cryptSession );
if( status == CRYPT_ERROR_OPEN || status == CRYPT_ERROR_BUSY || \
status == CRYPT_ERROR_PERMISSION )
{
/* These servers are constantly appearing and disappearing so if
we get a straight connect error we don't treat it as a serious
failure. In addition we can get server busy and no permission
to access errors which are also treated as soft errors */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -