📄 testscrt.c
字号:
/****************************************************************************
* *
* cryptlib Cert Management Session Test Routines *
* Copyright Peter Gutmann 1998-2003 *
* *
****************************************************************************/
#ifdef _MSC_VER
#include "../cryptlib.h"
#include "../test/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 /* EBCDIC systems */
/* Prototypes for functions in testsreq.c */
BOOLEAN setLocalConnect( const CRYPT_SESSION cryptSession, const int port );
void printConnectInfo( const CRYPT_SESSION cryptSession );
/****************************************************************************
* *
* Utility Functions *
* *
****************************************************************************/
/* Run a persistent server session, recycling the connection if the client
kept the link open */
static int activatePersistentServerSession( const CRYPT_SESSION cryptSession,
const BOOLEAN showOperationType )
{
BOOLEAN connectionActive = FALSE;
int status;
do
{
/* Activate the connection */
status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE,
TRUE );
if( status == CRYPT_ERROR_READ && connectionActive )
/* The other side closed the connection after a previous
successful transaction, this isn't an error */
return( CRYPT_OK );
/* Print connection info and check whether the connection is still
active. If it is, we recycle the session so that we can process
another request */
printConnectInfo( cryptSession );
if( cryptStatusOK( status ) && showOperationType )
{
char userID[ CRYPT_MAX_TEXTSIZE ];
int userIDsize, requestType;
status = cryptGetAttribute( cryptSession,
CRYPT_SESSINFO_CMP_REQUESTTYPE,
&requestType );
if( cryptStatusOK( status ) )
status = cryptGetAttributeString( cryptSession,
CRYPT_SESSINFO_USERNAME,
userID, &userIDsize );
if( cryptStatusError( status ) )
printf( "cryptGetAttribute/AttributeString() failed with "
"error code %d, line %d.\n", status, __LINE__ );
else
{
userID[ userIDsize ] = '\0';
printf( "SVR: Operation type was %d, user '%s'.\n",
requestType, userID );
}
}
cryptGetAttribute( cryptSession, CRYPT_SESSINFO_CONNECTIONACTIVE,
&connectionActive );
}
while( cryptStatusOK( status ) && connectionActive );
return( status );
}
/* Get information on a PKI user */
static int getPkiUserInfo( char *userID, char *issuePW, char *revPW )
{
CRYPT_KEYSET cryptCertStore;
CRYPT_CERTIFICATE cryptPKIUser;
int length, status;
/* 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. First we get the PkiUser
object */
status = cryptKeysetOpen( &cryptCertStore, CRYPT_UNUSED,
CERTSTORE_KEYSET_TYPE, CERTSTORE_KEYSET_NAME,
CRYPT_KEYOPT_NONE );
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 CMP test.\n" );
return( CRYPT_ERROR_NOTAVAIL );
}
if( cryptStatusError( status ) )
{
printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
status = cryptCAGetItem( cryptCertStore, &cryptPKIUser,
CRYPT_CERTTYPE_PKIUSER, CRYPT_KEYID_NAME,
"Test PKI user" );
cryptKeysetClose( cryptCertStore );
if( cryptStatusError( status ) )
return( extErrorExit( cryptCertStore, "cryptCAGetItem()", status,
__LINE__ ) );
/* If it's a presence check only, we're done */
if( userID == NULL )
{
cryptDestroyCert( cryptPKIUser );
return( CRYPT_OK );
}
/* Then we extract the information from the PkiUser object */
status = cryptGetAttributeString( cryptPKIUser,
CRYPT_CERTINFO_PKIUSER_ID,
userID, &length );
if( cryptStatusOK( status ) )
{
userID[ length ] = '\0';
status = cryptGetAttributeString( cryptPKIUser,
CRYPT_CERTINFO_PKIUSER_ISSUEPASSWORD,
issuePW, &length );
}
if( cryptStatusOK( status ) )
issuePW[ length ] = '\0';
if( cryptStatusOK( status ) && revPW != NULL )
{
status = cryptGetAttributeString( cryptPKIUser,
CRYPT_CERTINFO_PKIUSER_REVPASSWORD,
revPW, &length );
if( cryptStatusOK( status ) )
revPW[ length ] = '\0';
}
cryptDestroyCert( cryptPKIUser );
if( cryptStatusError( status ) )
return( attrErrorExit( cryptPKIUser, "cryptGetAttribute()", status,
__LINE__ ) );
/* We've got what we need, tell the user what we're doing */
printf( "Using user name %s, password %s.\n", userID, issuePW );
return( CRYPT_OK );
}
/****************************************************************************
* *
* SCEP Routines Test *
* *
****************************************************************************/
/* There are various SCEP test servers available, the following mappings
can be used to test different ones. Implementation peculiarities:
#1 - cryptlib:
#2 - SSH (www.ssh.com/support/testzone/pki.html): Invalid CA certs.
#3 - OpenSCEP (openscep.othello.ch): Seems to be permanently unavailable.
#4 - Entrust (freecerts.entrust.com/vpncerts/cep.htm): Only seems to be
set up to handle Cisco gear */
#define SCEP_NO 1
typedef struct {
const char *name, *url, *user, *password, *caCertUrl;
} SCEP_INFO;
static const SCEP_INFO scepInfo[] = {
{ NULL }, /* Dummy so index == SCEP_NO */
{ /*1*/ "cryptlib", "http://localhost", NULL, NULL, NULL },
{ /*2*/ "SSH", "http://pki.ssh.com:8080/scep/", "ssh", "ssh",
"http://pki.ssh.com:8080/scep/pkiclient.exe?operation=GetCACert&message=test-ca1.ssh.com" },
{ /*3*/ "OpenSCEP", "http://openscep.othello.ch/", "????", "????", NULL },
{ /*4*/ "Entrust", "http://vpncerts.entrust.com/", "????", "????", NULL },
};
/* Cert request data for the cert from the SCEP server. Note that we have
to set the CN to the PKI user CN, for CMP ir's we just omit the DN
entirely and have the server provide it for us but since SCEP uses PKCS
#10 requests we need to provide a DN, and since we provide it it has to
match the PKI user DN */
static const CERT_DATA scepRequestData[] = {
/* Identification information */
{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, "NZ" },
{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, "Dave's Wetaburgers" },
{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, "Procurement" },
{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, "Test PKI user" },
/* Subject altName */
{ CRYPT_CERTINFO_RFC822NAME, IS_STRING, 0, "dave@wetas-r-us.com" },
{ CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, IS_STRING, 0, "http://www.wetas-r-us.com" },
{ CRYPT_ATTRIBUTE_NONE, IS_VOID }
};
/* Get an SCEP CA cert */
static int getScepCACert( const char *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,
"[None]" );
cryptKeysetClose( cryptKeyset );
}
if( cryptStatusError( status ) )
return( extErrorExit( cryptKeyset, "cryptGetPublicKey()",
status, __LINE__ ) );
return( CRYPT_OK );
}
/* Perform an SCEP test */
int testSessionSCEP( void )
{
CRYPT_SESSION cryptSession;
CRYPT_CERTIFICATE cryptRequest, cryptResponse, cryptCACert;
CRYPT_CONTEXT cryptContext;
char userID[ 64 ], password[ 64 ];
const char *userPtr = scepInfo[ SCEP_NO ].user;
const char *passwordPtr = scepInfo[ SCEP_NO ].password;
int status;
puts( "Testing SCEP session..." );
/* Get the issuing CA's cert */
if( scepInfo[ SCEP_NO ].caCertUrl != NULL )
status = getScepCACert( scepInfo[ SCEP_NO ].caCertUrl,
&cryptCACert );
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 = getPkiUserInfo( userID, password, NULL );
if( cryptStatusError( status ) )
{
cryptDestroyCert( cryptCACert );
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, strlen( userPtr ) );
if( cryptStatusOK( status ) )
status = cryptSetAttributeString( cryptSession,
CRYPT_SESSINFO_PASSWORD,
passwordPtr, strlen( passwordPtr ) );
if( cryptStatusOK( status ) )
status = cryptSetAttributeString( cryptSession,
CRYPT_SESSINFO_SERVER_NAME,
scepInfo[ SCEP_NO ].url,
strlen( scepInfo[ SCEP_NO ].url ) );
if( cryptStatusOK( status ) )
status = cryptSetAttribute( cryptSession,
CRYPT_SESSINFO_CACERTIFICATE,
cryptCACert );
cryptDestroyCert( cryptCACert );
if( cryptStatusError( status ) )
{
printf( "Addition of session information failed with error code %d, "
"line %d.\n", status, __LINE__ );
return( FALSE );
}
/* Create the (unsigned) PKCS #10 request */
#if ( SCEP_NO == 1 )
cryptCreateContext( &cryptContext, CRYPT_UNUSED, CRYPT_ALGO_RSA );
cryptSetAttributeString( cryptContext, CRYPT_CTXINFO_LABEL,
USER_PRIVKEY_LABEL,
strlen( USER_PRIVKEY_LABEL ) );
cryptSetAttribute( cryptContext, CRYPT_CTXINFO_KEYSIZE, 64 );
status = cryptGenerateKey( cryptContext );
#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 ) )
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 );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -