⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 keydbx.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 3 页
字号:
/****************************************************************************
*																			*
*					cryptlib Database Keyset Test Routines					*
*						Copyright Peter Gutmann 1995-2005					*
*																			*
****************************************************************************/

#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 */

/* Some LDAP keyset names and names of probably-present certs and CRLs.
   These keysets (and their contents) come and go, so we have a variety of
   them and try them in turn until something works.  There's a list of more
   LDAP servers at http://www.dante.net/np/pdi.html, but none of these are
   known to contain certificates.

   Note that the following strings have to be given on one line in order for
   the widechar conversion voodoo to work */

static const struct {
	const C_STR url;			/* LDAP URL for keyset */
	const char *asciiURL;		/* URL in ASCII */
	const C_STR certName;		/* DN for cert and CRL */
	const C_STR crlName;
	} ldapUrlInfo[] = {
	{ 0 },
	{ TEXT( "ldap.diginotar.nl" ), "ldap.diginotar.nl",
	  TEXT( "cn=Root Certificaat Productie, o=DigiNotar Root,c=NL" ),
	  TEXT( "CN=CRL Productie,O=DigiNotar CRL,C=NL" ) },
	{ TEXT( "ds.katalog.posten.se" ), "ds.katalog.posten.se",
	  TEXT( "cn=Posten CertPolicy_eIDKort_1 CA_nyckel_1, o=Posten_Sverige_AB 556451-4148, c=SE" ),
	  TEXT( "cn=Posten CertPolicy_eIDKort_1 CA_nyckel_1, o=Posten_Sverige_AB 556451-4148, c=SE" ) },
	{ TEXT( "ldap2.zebsign.com" ), "ldap2.zebsign.com",
	  TEXT( "pssUniqueIdentifier=24090, CN=First ZebSign Community ID CA, O=ZebSign - 983163432, C=NO" ) }
	};

#define LDAP_SERVER_NO		1
#define LDAP_ALT_SERVER_NO	2	/* Secondary svr.if main server unavailable */

/****************************************************************************
*																			*
*					Database Keyset Read/Write Tests						*
*																			*
****************************************************************************/

/* Read/write a certificate from a public-key keyset.  Returns 
   CRYPT_ERROR_NOTAVAIL if this keyset type isn't available from this 
   cryptlib build, CRYPT_ERROR_FAILED if the keyset/data source access 
   failed */

enum { READ_OPTION_NORMAL, READ_OPTION_MULTIPLE };

static int testKeysetRead( const CRYPT_KEYSET_TYPE keysetType,
						   const C_STR keysetName,
						   const CRYPT_KEYID_TYPE keyType,
						   const C_STR keyName, 
						   const CRYPT_CERTTYPE_TYPE type,
						   const int option )
	{
	CRYPT_KEYSET cryptKeyset;
	CRYPT_CERTIFICATE cryptCert;
	int value, 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, keysetType, 
							  keysetName, 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 the certificate from the keyset */
	status = cryptGetPublicKey( cryptKeyset, &cryptCert, keyType, keyName );
	if( cryptStatusError( status ) )
		{
		/* The access to network-accessible keysets can be rather 
		   temperamental and can fail at this point even though it's not a
		   fatal error.  The calling code knows this and will continue the
		   self-test with an appropriate warning, so we explicitly clean up 
		   after ourselves to make sure we don't get a CRYPT_ORPHAN on
		   shutdown */
		if( keysetType == CRYPT_KEYSET_HTTP && \
			status == CRYPT_ERROR_NOTFOUND )
			{
			/* 404's are relatively common, and non-fatal */
			extErrorExit( cryptKeyset, "cryptGetPublicKey()", status, __LINE__ );
			puts( "  (404 is a common HTTP error, and non-fatal)." );
			return( TRUE );
			}

		return( extErrorExit( cryptKeyset, "cryptGetPublicKey()", status, 
							  __LINE__ ) );
		}

	/* Make sure that we got what we were expecting */
	cryptGetAttribute( cryptCert, CRYPT_CERTINFO_CERTTYPE, &value );
	if( value != type )
		{
		printf( "Expecting certificate object type %d, got %d.", type, value );
		return( FALSE );
		}
	if( value == CRYPT_CERTTYPE_CERTCHAIN || value == CRYPT_CERTTYPE_CRL )
		{
		const BOOLEAN isCertChain = ( value == CRYPT_CERTTYPE_CERTCHAIN ) ? \
									TRUE : FALSE;

		value = 0;
		cryptSetAttribute( cryptCert, CRYPT_CERTINFO_CURRENT_CERTIFICATE, 
						   CRYPT_CURSOR_FIRST );
		do
			value++;
		while( cryptSetAttribute( cryptCert,
								  CRYPT_CERTINFO_CURRENT_CERTIFICATE, 
								  CRYPT_CURSOR_NEXT ) == CRYPT_OK );
		printf( isCertChain ? "Cert chain length = %d.\n" : \
							  "CRL has %d entries.\n", value );
		}

	/* Check the cert against the CRL.  Any kind of error is a failure since
	   the cert isn't in the CRL */
	if( keysetType != CRYPT_KEYSET_LDAP && \
		keysetType != CRYPT_KEYSET_HTTP )
		{
		puts( "Checking certificate against CRL." );
		status = cryptCheckCert( cryptCert, cryptKeyset );
		if( cryptStatusError( status ) )
			return( extErrorExit( cryptKeyset, "cryptCheckCert() (for CRL "
								  "in keyset)", status, __LINE__ ) );
		}
	cryptDestroyCert( cryptCert );

	/* If we're reading multiple certs using the same (cached) query type,
	   try re-reading the cert.  This can't be easily tested from the 
	   outside because it's database back-end specific, so it'll require
	   attaching a debugger to the read code to make sure that the cacheing
	   is working as required */
	if( option == READ_OPTION_MULTIPLE )
		{
		int i;

		for( i = 0; i < 3; i++ )
			{
			status = cryptGetPublicKey( cryptKeyset, &cryptCert, keyType, 
										keyName );
			if( cryptStatusError( status ) )
				{
				printf( "cryptGetPublicKey() with cached query failed with "
						"error code %d, line %d.\n", status, __LINE__ );
				return( FALSE );
				}
			cryptDestroyCert( cryptCert );
			}
		}

	/* Close the keyset */
	status = cryptKeysetClose( cryptKeyset );
	if( cryptStatusError( status ) )
		{
		printf( "cryptKeysetClose() failed with error code %d, line %d.\n",
				status, __LINE__ );
		return( FALSE );
		}

	return( TRUE );
	}

static int testKeysetWrite( const CRYPT_KEYSET_TYPE keysetType,
							const C_STR keysetName )
	{
	CRYPT_KEYSET cryptKeyset;
	CRYPT_CERTIFICATE cryptCert;
	C_CHR filenameBuffer[ FILENAME_BUFFER_SIZE ];
	C_CHR name[ CRYPT_MAX_TEXTSIZE + 1 ];
	int length, status;

	/* Import the certificate from a file - this is easier than creating one
	   from scratch.  We use one of the later certs in the text set, since 
	   this contains an email address, which the earlier ones don't */
	status = importCertFromTemplate( &cryptCert, CERT_FILE_TEMPLATE, 5 );
	if( cryptStatusError( status ) )
		{
		puts( "Couldn't read certificate from file, skipping test of keyset "
			  "write..." );
		return( TRUE );
		}

	/* Create the database keyset with a check to make sure 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( &cryptKeyset, CRYPT_UNUSED, keysetType, 
							  keysetName, CRYPT_KEYOPT_CREATE );
	if( cryptStatusOK( status ) )
		printf( "Created new certificate database '%s'.\n", keysetName );
	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 */
		cryptDestroyCert( cryptCert );
		return( CRYPT_ERROR_NOTAVAIL );
		}
	if( status == CRYPT_ERROR_DUPLICATE )
		status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, keysetType, 
								  keysetName, 0 );
	if( cryptStatusError( status ) )
		{
		cryptDestroyCert( cryptCert );
		printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
				status, __LINE__ );
		if( status == CRYPT_ERROR_OPEN )
			return( CRYPT_ERROR_FAILED );
		return( FALSE );
		}

	/* Write the key to the database */
	puts( "Adding certificate." );
	status = cryptAddPublicKey( cryptKeyset, cryptCert );
	if( status == CRYPT_ERROR_DUPLICATE )
		{
		/* The key is already present, delete it and retry the write */
		status = cryptGetAttributeString( cryptCert, 
								CRYPT_CERTINFO_COMMONNAME, name, &length );
		if( cryptStatusOK( status ) )
			{
#ifdef UNICODE_STRINGS
			length /= sizeof( wchar_t );
#endif /* UNICODE_STRINGS */
			name[ length ] = TEXT( '\0' );
			status = cryptDeleteKey( cryptKeyset, CRYPT_KEYID_NAME, name );
			}
		if( cryptStatusError( status ) )
			return( extErrorExit( cryptKeyset, "cryptDeleteKey()", status, 
								  __LINE__ ) );
		status = cryptAddPublicKey( cryptKeyset, cryptCert );
		}
	if( cryptStatusError( status ) )
		{
		printExtError( cryptKeyset, "cryptAddPublicKey()", status, __LINE__ );

		/* LDAP writes can fail due to the chosen directory not supporting the
		   schema du jour, so we're a bit more careful about cleaning up since
		   we'll skip the error and continue processing */
		cryptDestroyCert( cryptCert );
		cryptKeysetClose( cryptKeyset );
		return( FALSE );
		}
	cryptDestroyCert( cryptCert );

	/* Add a second cert with C=US so that we've got enough certs to properly 
	   exercise the query code.  This cert is highly unusual in that it 
	   doesn't have a DN, so we have to move up the DN looking for higher-up
	   values, in this case the OU */
	if( keysetType != CRYPT_KEYSET_LDAP )
		{
		status = importCertFromTemplate( &cryptCert, CERT_FILE_TEMPLATE, 2 );
		if( cryptStatusError( status ) )
			{
			puts( "Couldn't read second certificate from file, skipping "
				  "remaining keyset write tests..." );
			cryptKeysetClose( cryptKeyset );
			return( TRUE );
			}
		status = cryptAddPublicKey( cryptKeyset, cryptCert );
		if( status == CRYPT_ERROR_DUPLICATE )
			{
			status = cryptGetAttributeString( cryptCert, 
							CRYPT_CERTINFO_COMMONNAME, name, &length );
			if( cryptStatusError( status ) )
				status = cryptGetAttributeString( cryptCert, 
							CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, name, &length );
			if( cryptStatusOK( status ) )
				{
#ifdef UNICODE_STRINGS
				length /= sizeof( wchar_t );
#endif /* UNICODE_STRINGS */
				name[ length ] = TEXT( '\0' );
				status = cryptDeleteKey( cryptKeyset, CRYPT_KEYID_NAME, name );
				}
			if( cryptStatusOK( status ) )
				status = cryptAddPublicKey( cryptKeyset, cryptCert );
			}
		if( cryptStatusError( status ) )
			return( extErrorExit( cryptKeyset, "cryptAddPublicKey()", 
								  status, __LINE__ ) );
		cryptDestroyCert( cryptCert );
		}

	/* Now try the same thing with a CRL.  This code also tests the 
	   duplicate-detection mechanism, if we don't get a duplicate error 
	   there's a problem */
	puts( "Adding CRL." );
	status = importCertFromTemplate( &cryptCert, CRL_FILE_TEMPLATE, 1 );
	if( cryptStatusError( status ) )
		{
		puts( "Couldn't read CRL from file, skipping test of keyset "
			  "write..." );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -