📄 sreqresp.c
字号:
/****************************************************************************
* *
* cryptlib Request/Response Session Test Routines *
* Copyright Peter Gutmann 1998-2004 *
* *
****************************************************************************/
#ifdef _MSC_VER
#include "../cryptlib.h"
#include "test.h"
#else
#include "cryptlib.h"
#include "test/test.h"
#endif /* Braindamaged MSC include handling */
#if defined( __MVS__ ) || defined( __VMCMS__ )
/* Suspend conversion of literals to ASCII. */
#pragma convlit( suspend )
#endif /* IBM big iron */
#if defined( __ILEC400__ )
#pragma convert( 0 )
#endif /* IBM medium iron */
/* Prototypes for functions in testcert.c */
int initRTCS( CRYPT_CERTIFICATE *cryptRTCSRequest, const int number,
const BOOLEAN multipleCerts );
int initOCSP( CRYPT_CERTIFICATE *cryptOCSPRequest, const int number,
const BOOLEAN ocspv2, const BOOLEAN revokedCert,
const BOOLEAN multipleCerts,
const CRYPT_SIGNATURELEVEL_TYPE sigLevel,
const CRYPT_CONTEXT privKeyContext );
/****************************************************************************
* *
* HTTP Certstore Routines Test *
* *
****************************************************************************/
/* This isn't really a proper session but just an HTTP cert store interface,
but the semantics for the server side fit the session interface better
than the keyset interface */
static int connectCertstoreServer( void )
{
CRYPT_SESSION cryptSession;
CRYPT_KEYSET cryptCertStore;
int connectionActive, status;
puts( "Testing HTTP certstore server session..." );
/* Create the HTTP certstore session */
status = cryptCreateSession( &cryptSession, CRYPT_UNUSED,
CRYPT_SESSION_CERTSTORE_SERVER );
if( status == CRYPT_ERROR_PARAM3 ) /* Certstore 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( !setLocalConnect( cryptSession, 80 ) )
return( FALSE );
/* Add the cert store that we'll be using to provide certs (it's
actually just the generic database keyset and not the full cert
store, because this contains more test certs) */
status = cryptKeysetOpen( &cryptCertStore, CRYPT_UNUSED,
DATABASE_KEYSET_TYPE, DATABASE_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( "SVR: No certificate store available, aborting HTTP certstore "
"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__ ) );
/* Activate the server */
status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );
printConnectInfo( cryptSession );
if( cryptStatusError( status ) )
{
printExtError( cryptSession, "SVR: Attempt to activate HTTP "
"certstore server session", status, __LINE__ );
cryptDestroySession( cryptSession );
return( FALSE );
}
/* Check whether the session connection is still open */
status = cryptGetAttribute( cryptSession, CRYPT_SESSINFO_CONNECTIONACTIVE,
&connectionActive );
if( cryptStatusError( status ) || !connectionActive )
{
printExtError( cryptSession, "SVR: Persistent connection has been "
"closed, operation", status, __LINE__ );
return( FALSE );
}
/* Activate the connection to handle two more requests */
status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );
if( cryptStatusError( status ) )
{
printExtError( cryptSession, "SVR: Attempt to perform second HTTP "
"certstore server transaction", status, __LINE__ );
cryptDestroySession( cryptSession );
return( status );
}
status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );
if( cryptStatusError( status ) )
{
printExtError( cryptSession, "SVR: Attempt to perform third HTTP "
"certstore server transaction", status, __LINE__ );
cryptDestroySession( cryptSession );
return( status );
}
/* Clean up */
status = cryptDestroySession( cryptSession );
if( cryptStatusError( status ) )
{
printf( "cryptDestroySession() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
puts( "SVR: HTTP certstore server session succeeded.\n" );
return( TRUE );
}
static int connectCertstoreClient( void )
{
CRYPT_KEYSET cryptKeyset;
CRYPT_CERTIFICATE cryptCert;
const C_STR cert1ID = TEXT( "dave@wetaburgers.com" );
const C_STR cert2ID = TEXT( "notpresent@absent.com" );
int status;
/* Open the keyset with a check to make sure this access method exists
so we can return an appropriate error message */
status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_HTTP,
TEXT( "localhost" ), CRYPT_KEYOPT_READONLY );
if( status == CRYPT_ERROR_PARAM3 )
/* This type of keyset access not available */
return( CRYPT_ERROR_NOTAVAIL );
if( cryptStatusError( status ) )
{
printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
status, __LINE__ );
return( CRYPT_ERROR_FAILED );
}
/* Read a present certificate from the keyset using the ASCII email
address */
status = cryptGetPublicKey( cryptKeyset, &cryptCert, CRYPT_KEYID_EMAIL,
cert1ID );
if( cryptStatusError( status ) )
return( extErrorExit( cryptKeyset, "cryptGetPublicKey()", status,
__LINE__ ) );
printf( "Successfully read cert for '%s'.\n", cert1ID );
cryptDestroyCert( cryptCert );
/* Read a non-present certificate from the keyset */
status = cryptGetPublicKey( cryptKeyset, &cryptCert, CRYPT_KEYID_EMAIL,
cert2ID );
if( status == CRYPT_ERROR_NOTFOUND )
printf( "Successfully processed not-present code for '%s'.\n",
cert2ID );
else
return( extErrorExit( cryptKeyset, "cryptGetPublicKey()", status,
__LINE__ ) );
/* Read the certificate from the keyset using the base64-encoded certID.
Since this uses an internal identifier, we can't actually do it from
here, this requires modifying the internal keyset read code to
substitute the different identifier type */
status = cryptGetPublicKey( cryptKeyset, &cryptCert, CRYPT_KEYID_EMAIL,
cert1ID );
if( cryptStatusError( status ) )
return( extErrorExit( cryptKeyset, "cryptGetPublicKey()", status,
__LINE__ ) );
printf( "Successfully read cert for '%s'.\n", cert1ID );
cryptDestroyCert( cryptCert );
/* Clean up */
cryptKeysetClose( cryptKeyset );
return( TRUE );
}
int testSessionHTTPCertstoreServer( void )
{
return( connectCertstoreServer() );
}
/* Perform a client/server loopback test */
#ifdef WINDOWS_THREADS
unsigned __stdcall certstoreServerThread( void *dummy )
{
connectCertstoreServer();
_endthreadex( 0 );
return( 0 );
}
int testSessionHTTPCertstoreClientServer( void )
{
HANDLE hThread;
unsigned threadID;
int status;
/* Start the server and wait for it to initialise */
hThread = ( HANDLE ) _beginthreadex( NULL, 0, &certstoreServerThread,
NULL, 0, &threadID );
Sleep( 1000 );
/* Connect to the local server */
status = connectCertstoreClient();
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 */
/****************************************************************************
* *
* RTCS Routines Test *
* *
****************************************************************************/
/* There are various test RTCS servers running, the following remapping
allows us to switch between them. Implementation peculiarities:
#1 - cryptlib:
None */
#define RTCS_SERVER_NO 1
#if RTCS_SERVER_NO == 1
#define RTCS_SERVER_NAME TEXT( "http://localhost" )
#endif /* RTCS server name kludge */
/* Perform an RTCS test */
static int connectRTCS( const CRYPT_SESSION_TYPE sessionType,
const BOOLEAN multipleCerts,
const BOOLEAN localSession )
{
CRYPT_SESSION cryptSession;
CRYPT_CERTIFICATE cryptRTCSRequest, cryptRTCSResponse;
const BOOLEAN isServer = ( sessionType == CRYPT_SESSION_RTCS_SERVER ) ? \
TRUE : FALSE;
int status;
printf( "%sTesting %sRTCS session...\n", isServer ? "SVR: " : "",
localSession ? "local " : "" );
/* Create the RTCS session */
status = cryptCreateSession( &cryptSession, CRYPT_UNUSED, sessionType );
if( status == CRYPT_ERROR_PARAM3 ) /* RTCS 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 ) )
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 that 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( "SVR: No certificate store available, aborting RTCS "
"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 RTCS request */
if( !initRTCS( &cryptRTCSRequest, localSession ? 1 : RTCS_SERVER_NO,
multipleCerts ) )
return( FALSE );
/* Set up the server information and activate the session. In
theory the RTCS 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 RTCS request (via the cert) */
status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_REQUEST,
cryptRTCSRequest );
if( cryptStatusError( status ) )
return( attrErrorExit( cryptSession, "cryptSetAttribute()",
status, __LINE__ ) );
cryptDestroyCert( cryptRTCSRequest );
if( localSession && !setLocalConnect( cryptSession, 80 ) )
return( FALSE );
#ifdef RTCS_SERVER_NAME
if( !localSession )
{
printf( "Setting RTCS server to %s.\n", RTCS_SERVER_NAME );
cryptDeleteAttribute( cryptSession, CRYPT_SESSINFO_SERVER_NAME );
status = cryptSetAttributeString( cryptSession,
CRYPT_SESSINFO_SERVER_NAME, RTCS_SERVER_NAME,
paramStrlen( RTCS_SERVER_NAME ) );
if( cryptStatusError( status ) )
return( attrErrorExit( cryptSession,
"cryptSetAttributeString()", status,
__LINE__ ) );
}
#endif /* Kludges for incorrect/missing authorityInfoAccess values */
}
status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );
if( isServer )
printConnectInfo( cryptSession );
if( cryptStatusError( status ) )
{
printExtError( cryptSession, isServer ? \
"SVR: Attempt to activate RTCS server session" : \
"Attempt to activate RTCS client session", status,
__LINE__ );
cryptDestroySession( cryptSession );
if( status == CRYPT_ERROR_OPEN || status == CRYPT_ERROR_NOTFOUND || \
status == CRYPT_ERROR_TIMEOUT || 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 that 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,
&cryptRTCSResponse );
if( cryptStatusError( status ) )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -