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

📄 dbxldap.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 3 页
字号:
								  RESOURCE_IMESSAGE_DEV_CREATEOBJECT_INDIRECT,
								  &createInfo, OBJECT_TYPE_CERTIFICATE );
		if( cryptStatusOK( status ) )
			*iCryptHandle = createInfo.cryptHandle;

		ldap_value_free_len( valuePtrs );
		}
	else
		status = CRYPT_ERROR_NOTFOUND;

	/* Clean up.  The ber_free() function is rather problematic because 
	   Netscape uses the nonstandard ldap_ber_free() name (which can be fixed
	   with proprocessor trickery) and Microsoft first omitted it entirely
	   (up to NT4 SP4) and then later added it as a stub (Win2K, rumour has 
	   it that the only reason this function even exists is because the 
	   Netscape client required it).  Because it may or may not exist in the 
	   MS client, we call it if we resolved its address, otherwise we skip 
	   it.
	   
	   The function is further complicated by the fact that LDAPv3 says the 
	   second parameter should be 0, however the Netscape client docs 
	   require it to be 1 and the MS client ignores it so we pass in a 1 
	   (actually the way the MS implementation handles the BER data is that 
	   the BerElement returned by ldap_first_attribute() is (despite what the
	   MSDN docs claim) just a data structure pointed to by lm_ber in the 
	   LDAPMessage structure, all that ldap_first_attribute() does is 
	   redirect the lm_ber pointer inside the LDAPMessage, so actually 
	   freeing this wouldn't be a good idea).

	   It gets worse than this though.  Calling ber_free() with newer 
	   versions of the Windows LDAP client causes internal data corruption 
	   which typically first results in a soft failure (eg a data fetch 
	   fails) and then eventually a hard failure such as an access violation 
	   after further calls are made.  The only real way to fix this is to
	   avoid calling it entirely, this doesn't seem to leak any more memory
	   than Winsock leaks anyway (that is, there are a considerable number
	   of memory and handle leaks, but the number doesn't increase if
	   ber_free() isn't called).
	   
	   There have been reports that with some older versions of the Windows
	   LDAP client (eg the one in Win95) the ldap_msgfree() call generates 
	   an exception in wldap.dll, if this is a problem you need to either
	   install a newer LDAP DLL or switch to the Netscape one */
#ifdef NETSCAPE_CLIENT
	if( ber_free != NULL )
		ber_free( ber, 1 );
#endif /* NETSCAPE_CLIENT */
	ldap_memfree( attributePtr );
	if( !keysetInfo->queryInProgress )
		ldap_msgfree( result );
	return( status );
	}

/* Add an entry/attribute to an LDAP directory.  The LDAP behaviour differs
   somewhat from DAP in that assigning a value to a nonexistant attribute 
   implicitly creates the required attribute.  In addition deleting the last
   value automatically deletes the entire attribute, the delete item code
   assumes the user is requesting a superset of this behaviour and deletes 
   the entire entry */

static int addCert( KEYSET_INFO *keysetInfo, const CRYPT_HANDLE iCryptHandle )
	{
	RESOURCE_DATA msgData;
	LDAPMod *ldapMod[ MAX_LDAP_ATTRIBUTES ];
	BYTE keyData[ MAX_CERT_SIZE ];
	char dn[ MAX_DN_STRINGSIZE ];
	char C[ CRYPT_MAX_TEXTSIZE + 1 ], SP[ CRYPT_MAX_TEXTSIZE + 1 ],
		L[ CRYPT_MAX_TEXTSIZE + 1 ], O[ CRYPT_MAX_TEXTSIZE + 1 ],
		OU[ CRYPT_MAX_TEXTSIZE + 1 ], CN[ CRYPT_MAX_TEXTSIZE + 1 ],
		email[ CRYPT_MAX_TEXTSIZE + 1 ];
	int keyDataLength, ldapModIndex = 1, status = CRYPT_OK;

	*C = *SP = *L = *O = *OU = *CN = *email = '\0';

	/* Extract the DN and altName components.  This changes the currently
	   selected DN components, but this is OK since we've got the cert
	   locked and the prior state will be restored when we unlock it */
	krnlSendMessage( iCryptHandle, RESOURCE_IMESSAGE_SETATTRIBUTE,
					 MESSAGE_VALUE_UNUSED, CRYPT_CERTINFO_SUBJECTNAME );
	setResourceData( &msgData, C, CRYPT_MAX_TEXTSIZE );
	status = krnlSendMessage( iCryptHandle, RESOURCE_IMESSAGE_GETATTRIBUTE_S,
							  &msgData, CRYPT_CERTINFO_COUNTRYNAME );
	if( cryptStatusOK( status ) )
		C[ msgData.length ] = '\0';
	if( cryptStatusOK( status ) || status == CRYPT_ERROR_NOTFOUND )
		{
		setResourceData( &msgData, SP, CRYPT_MAX_TEXTSIZE );
		status = krnlSendMessage( iCryptHandle,
							RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
							CRYPT_CERTINFO_STATEORPROVINCENAME );
		}
	if( cryptStatusOK( status ) )
		SP[ msgData.length ] = '\0';
	if( cryptStatusOK( status ) || status == CRYPT_ERROR_NOTFOUND )
		{
		setResourceData( &msgData, L, CRYPT_MAX_TEXTSIZE );
		status = krnlSendMessage( iCryptHandle,
							RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
							CRYPT_CERTINFO_LOCALITYNAME );
		}
	if( cryptStatusOK( status ) )
		L[ msgData.length ] = '\0';
	if( cryptStatusOK( status ) || status == CRYPT_ERROR_NOTFOUND )
		{
		setResourceData( &msgData, O, CRYPT_MAX_TEXTSIZE );
		status = krnlSendMessage( iCryptHandle,
							RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
							CRYPT_CERTINFO_ORGANIZATIONNAME );
		}
	if( cryptStatusOK( status ) )
		O[ msgData.length ] = '\0';
	if( cryptStatusOK( status ) || status == CRYPT_ERROR_NOTFOUND )
		{
		setResourceData( &msgData, OU, CRYPT_MAX_TEXTSIZE );
		status = krnlSendMessage( iCryptHandle,
							RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
							CRYPT_CERTINFO_ORGANIZATIONALUNITNAME );
		}
	if( cryptStatusOK( status ) )
		OU[ msgData.length ] = '\0';
	if( cryptStatusOK( status ) || status == CRYPT_ERROR_NOTFOUND )
		{
		setResourceData( &msgData, CN, CRYPT_MAX_TEXTSIZE );
		status = krnlSendMessage( iCryptHandle,
							RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
							CRYPT_CERTINFO_COMMONNAME );
		}
	if( cryptStatusOK( status ) )
		CN[ msgData.length ] = '\0';
	if( cryptStatusOK( status ) || status == CRYPT_ERROR_NOTFOUND )
		/* Get the string form of the DN */
		status = encodeDN( dn, C, SP, L, O, OU, CN );
	if( cryptStatusOK( status ) )
		{
		/* Get the certificate data */
		setResourceData( &msgData, keyData, MAX_CERT_SIZE );
		status = krnlSendMessage( iCryptHandle, RESOURCE_IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_IATTRIBUTE_ENC_CERT );
		keyDataLength = msgData.length;
		}
	if( cryptStatusError( status ) )
		/* Convert any low-level cert-specific error into something generic
		   which makes a bit more sense to the caller */
		return( CRYPT_ARGERROR_NUM1 );

	/* Set up the fixed attributes and certificate data.  This currently
	   always adds a cert as a standard certificate rather than a CA
	   certificate because of uncertainty over what other implementations
	   will try and look for, once enough other software uses the CA cert
	   attribute this can be switched over */
	if( ( ldapMod[ 0 ] = copyAttribute( keysetInfo->keysetLDAP.nameObjectClass,
										"certPerson", 0 ) ) == NULL )
		return( CRYPT_ERROR_MEMORY );
	if( ( ldapMod[ ldapModIndex++ ] = copyAttribute( keysetInfo->keysetLDAP.nameCert,
										keyData, keyDataLength ) ) == NULL )
		status = CRYPT_ERROR_MEMORY;

	/* Set up the DN/identification information */
	if( cryptStatusOK( status ) && *email && \
		( ldapMod[ ldapModIndex++ ] = \
				copyAttribute( keysetInfo->keysetLDAP.nameEmail, email, 0 ) ) == NULL )
		status = CRYPT_ERROR_MEMORY;
	if( cryptStatusOK( status ) && *CN && \
		( ldapMod[ ldapModIndex++ ] = copyAttribute( "CN", CN, 0 ) ) == NULL )
		status = CRYPT_ERROR_MEMORY;
	if( cryptStatusOK( status ) && *OU && \
		( ldapMod[ ldapModIndex++ ] = copyAttribute( "OU", OU, 0 ) ) == NULL )
		status = CRYPT_ERROR_MEMORY;
	if( cryptStatusOK( status ) && *O && \
		( ldapMod[ ldapModIndex++ ] = copyAttribute( "O", O, 0 ) ) == NULL )
		status = CRYPT_ERROR_MEMORY;
	if( cryptStatusOK( status ) && *L && \
		( ldapMod[ ldapModIndex++ ] = copyAttribute( "L", L, 0 ) ) == NULL )
		status = CRYPT_ERROR_MEMORY;
	if( cryptStatusOK( status ) && *SP && \
		( ldapMod[ ldapModIndex++ ] = copyAttribute( "SP", SP, 0 ) ) == NULL )
		status = CRYPT_ERROR_MEMORY;
	if( cryptStatusOK( status ) && *C && \
		( ldapMod[ ldapModIndex++ ] = copyAttribute( "C", C, 0 ) ) == NULL )
		status = CRYPT_ERROR_MEMORY;
	ldapMod[ ldapModIndex ] = NULL;

	/* Add the new attribute/entry */
	if( cryptStatusOK( status ) )
		{
		int ldapStatus;

		if( ( ldapStatus = ldap_add_s( keysetInfo->keysetLDAP.ld, dn,
									   ldapMod ) ) != LDAP_SUCCESS )
			{
			getErrorInfo( keysetInfo, ldapStatus );
			status = mapLDAPerror( ldapStatus, CRYPT_ERROR_WRITE );
			}
		}

	/* Clean up.  We do it the hard way rather than using 
	   ldap_mods_free() here partially because the ldapMod[] array 
	   isn't malloc()'d, but mostly because for the Netscape client
	   library ldap_mods_free() causes some sort of memory corruption, 
	   possibly because it's trying to free the mod_values[] entries 
	   which are statically allocated, and for the MS client the
	   function doesn't exist */
	for( ldapModIndex = 0; ldapMod[ ldapModIndex ] != NULL; 
		 ldapModIndex++ )
		{
		if( ldapMod[ ldapModIndex ]->mod_op & LDAP_MOD_BVALUES )
			free( ldapMod[ ldapModIndex ]->mod_bvalues[ 0 ] );
		free( ldapMod[ ldapModIndex ]->mod_values );
		free( ldapMod[ ldapModIndex ] );
		}
	return( status );
	}

static int setItemFunction( KEYSET_INFO *keysetInfo, 
							const CRYPT_HANDLE iCryptHandle,
							const KEYMGMT_ITEM_TYPE itemType,
							const char *password, const int passwordLength,
							const int flags )
	{
	BOOLEAN seenNonDuplicate = FALSE;
	int type, status;

	assert( itemType == KEYMGMT_ITEM_PUBLICKEY );
	assert( password == NULL ); assert( passwordLength == 0 );

	/* Make sure we've been given a cert or cert chain */
	status = krnlSendMessage( iCryptHandle, RESOURCE_MESSAGE_GETATTRIBUTE,
							  &type, CRYPT_CERTINFO_CERTTYPE );
	if( cryptStatusError( status ) )
		return( CRYPT_ARGERROR_NUM1 );
	if( type != CRYPT_CERTTYPE_CERTIFICATE && \
		type != CRYPT_CERTTYPE_CERTCHAIN )
		return( CRYPT_ARGERROR_NUM1 );

	/* Lock the cert for our exclusive use (in case it's a cert chain, we 
	   also select the first cert in the chain), update the keyset with the 
	   cert(s), and unlock it to allow others access */
	krnlSendMessage( iCryptHandle, RESOURCE_IMESSAGE_SETATTRIBUTE, 
					 MESSAGE_VALUE_CURSORFIRST, 
					 CRYPT_CERTINFO_CURRENT_CERTIFICATE );
	status = krnlSendNotifier( iCryptHandle, RESOURCE_IMESSAGE_LOCK );
	if( cryptStatusError( status ) )
		return( status );
	do
		{
		/* Add the certificate */
		status = addCert( keysetInfo, iCryptHandle );

		/* A cert being added may already be present, however we can't fail
		   immediately because what's being added may be a chain containing 
		   further certs, so we keep track of whether we've successfully 
		   added at least one cert and clear data duplicate errors */
		if( status == CRYPT_OK )
			seenNonDuplicate = TRUE;
		else
			if( status == CRYPT_ERROR_DUPLICATE )
				status = CRYPT_OK;
		}
	while( cryptStatusOK( status ) && \
		   krnlSendMessage( iCryptHandle, RESOURCE_IMESSAGE_SETATTRIBUTE, 
							MESSAGE_VALUE_CURSORNEXT,
							CRYPT_CERTINFO_CURRENT_CERTIFICATE ) == CRYPT_OK );
	krnlSendNotifier( iCryptHandle, RESOURCE_IMESSAGE_UNLOCK );
	if( cryptStatusOK( status ) && !seenNonDuplicate )
		/* We reached the end of the chain without finding anything we could
		   add, return a data duplicate error */
		status = CRYPT_ERROR_DUPLICATE;

	return( status );
	}

/* Delete an entry from an LDAP directory */

static int deleteItemFunction( KEYSET_INFO *keysetInfo,
							   const KEYMGMT_ITEM_TYPE itemType,
							   const CRYPT_KEYID_TYPE keyIDtype,
							   const void *keyID, const int keyIDlength )
	{
	char dn[ MAX_DN_STRINGSIZE ];
	int ldapStatus;

	assert( itemType == KEYMGMT_ITEM_PUBLICKEY );
	assert( keyIDtype == CRYPT_KEYID_NAME || keyIDtype == CRYPT_KEYID_EMAIL );

	/* Convert the DN into a null-terminated form */
	if( keyIDlength > MAX_DN_STRINGSIZE - 1 )
		return( CRYPT_ARGERROR_STR1 );
	memcpy( dn, keyID, keyIDlength );
	dn[ keyIDlength ] = '\0';

	/* Delete the entry */
	if( ( ldapStatus = ldap_delete_s( keysetInfo->keysetLDAP.ld, 
									  dn ) ) != LDAP_SUCCESS )
		{
		getErrorInfo( keysetInfo, ldapStatus );
		return( mapLDAPerror( ldapStatus, CRYPT_ERROR_WRITE ) );
		}

	return( CRYPT_OK );
	}

/* Perform a getFirst/getNext query on the LDAP directory */

static int getFirstItemFunction( KEYSET_INFO *keysetInfo, 
								 CRYPT_CERTIFICATE *iCertificate,
								 int *stateInfo, 
								 const CRYPT_KEYID_TYPE keyIDtype,
								 const void *keyID, const int keyIDlength,
								 const KEYMGMT_ITEM_TYPE itemType, 
								 const int options )
	{
	assert( stateInfo == NULL );
	assert( itemType == KEYMGMT_ITEM_PUBLICKEY );
	assert( options == KEYMGMT_FLAG_NONE );

	return( getItemFunction( keysetInfo, NULL, KEYMGMT_ITEM_PUBLICKEY,
							 CRYPT_KEYID_NAME, keyID, keyIDlength, NULL, 
							 0, 0 ) );
	}

static int getNextItemFunction( KEYSET_INFO *keysetInfo, 
								CRYPT_CERTIFICATE *iCertificate,
								int *stateInfo, const int options )
	{
	assert( stateInfo == NULL );

	return( getItemFunction( keysetInfo, iCertificate, KEYMGMT_ITEM_PUBLICKEY,
							 CRYPT_KEYID_NONE, NULL, 0, NULL, 0, 0 ) );
	}

int setAccessMethodLDAP( KEYSET_INFO *keysetInfo )
	{
#ifdef __WINDOWS__
	/* Make sure the LDAP driver is bound in */
	if( hLDAP == NULL_HINSTANCE )
		return( CRYPT_ERROR_OPEN );
#endif /* __WINDOWS__ */

	/* Set the access method pointers */
	keysetInfo->initFunction = initFunction;
	keysetInfo->shutdownFunction = shutdownFunction;
	keysetInfo->getItemFunction = getItemFunction;
	keysetInfo->setItemFunction = setItemFunction;
	keysetInfo->deleteItemFunction = deleteItemFunction;
	keysetInfo->getFirstItemFunction = getFirstItemFunction;
	keysetInfo->getNextItemFunction = getNextItemFunction;

	return( CRYPT_OK );
	}
#endif /* ( __WINDOWS__ || __UNIX__ ) && DBX_LDAP */

⌨️ 快捷键说明

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