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

📄 dbxldap.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 3 页
字号:
			return( CRYPT_ERROR_NOTFOUND );

#ifndef NETSCAPE_CLIENT
		case LDAP_NOT_SUPPORTED:
			return( CRYPT_ERROR_NOTAVAIL );
#endif /* NETSCAPE_CLIENT */

		case LDAP_RESULTS_TOO_LARGE:
			return( CRYPT_ERROR_OVERFLOW );
		}

	return( defaultError );
	}

/* Copy attribute information into an LDAPMod structure so it can be written to
   the directory */

static LDAPMod *copyAttribute( const char *attributeName,
							   const void *attributeValue,
							   const int attributeLength )
	{
	LDAPMod *ldapModPtr;

	/* Allocate room for the LDAPMod structure and the data pointers.
	   mod_values and mod_bvalues members have the same representation so we
	   can allocate them with the same malloc */
	if( ( ldapModPtr = ( LDAPMod * ) malloc( sizeof( LDAPMod ) ) ) == NULL )
		return( NULL );
	if( ( ldapModPtr->mod_values = malloc( 2 * sizeof( void * ) ) ) == NULL )
		{
		free( ldapModPtr );
		return( NULL );
		}

	/* Set up the pointers to the attribute information.  This differs
	   slightly depending on whether we're adding text or binary data */
	if( !attributeLength )
		{
		ldapModPtr->mod_op = LDAP_MOD_ADD;
		ldapModPtr->mod_type = ( char * ) attributeName;
		ldapModPtr->mod_values[ 0 ] = ( char * ) attributeValue;
		ldapModPtr->mod_values[ 1 ] = NULL;
		}
	else
		{
		if( ( ldapModPtr->mod_bvalues[ 0 ] = \
							malloc( sizeof( struct berval ) ) ) == NULL )
			{
			free( ldapModPtr->mod_values );
			free( ldapModPtr );
			return( NULL );
			}
		ldapModPtr->mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES;
		ldapModPtr->mod_type = ( char * ) attributeName;
		ldapModPtr->mod_bvalues[ 0 ]->bv_len = attributeLength;
		ldapModPtr->mod_bvalues[ 0 ]->bv_val = ( char * ) attributeValue;
		ldapModPtr->mod_bvalues[ 1 ] = NULL;
		}

	return( ldapModPtr );
	}

/* Encode DN information in the RFC 1779 reversed format.  We don't have to 
   check for overflows because the cert.management code limits the size of 
   each component to a small fraction of the total buffer size */

static void copyComponent( char *dest, char *src )
	{
	while( *src )
		{
		const char ch = *src++;

		if( ch == ',' )
			*dest++ = '\\';
		*dest++ = ch;
		}
	*dest++ = '\0';
	}

static int encodeDN( char *dn, char *C, char *SP, char *L, char *O, char *OU, 
					 char *CN )
	{
	char *bufPtr = dn;

	strcpy( dn, "CN=" );
	strcpy( dn + 3, CN );
	bufPtr += strlen( bufPtr );
	if( *OU )
		{
		strcpy( bufPtr, ",OU=" );
		copyComponent( bufPtr + 4, OU );
		bufPtr += strlen( bufPtr );
		}
	if( *O )
		{
		strcpy( bufPtr, ",O=" );
		copyComponent( bufPtr + 3, O );
		bufPtr += strlen( bufPtr );
		}
	if( *L )
		{
		strcpy( bufPtr, ",L=" );
		copyComponent( bufPtr + 3, L );
		bufPtr += strlen( bufPtr );
		}
	if( *SP )
		{
		strcpy( bufPtr, ",ST=" );	/* Not to be confused with ST=street */
		copyComponent( bufPtr + 4, SP );
		bufPtr += strlen( bufPtr );
		}
	strcpy( bufPtr, ",C=" );
	copyComponent( bufPtr + 3, C );

	return( CRYPT_OK );
	}

/* Decompose an LDAP URL into a server name and optional port */

static int parseURL( char *ldapServer, const char *url )
	{
	int ldapPort = LDAP_PORT, len;

	/* Skip a leading URL specifier if this is present */
	if( !strnicmp( url, "ldap://", 7 ) )
		url += 7;
	else
		if( !strnicmp( url, "ldaps://", 8 ) )
			url += 8;

	/* Decompose what's left into a FQDN and port */
	for( len = 0; url[ len ]; len++ )
		if( url[ len ] == ':' )
			break;
	strncpy( ldapServer, url, len );
	ldapServer[ len ] = '\0';
	if( url[ len ] )
		ldapPort = atoi( url + len + 1 );

	return( ldapPort );
	}

/****************************************************************************
*																			*
*						 	Directory Open/Close Routines					*
*																			*
****************************************************************************/

/* Close a previously-opened LDAP connection.  We have to have this before
   the init function since it may be called by it if the open process fails.  
   This is necessary because the complex LDAP open may require a fairly 
   extensive cleanup afterwards */

static void shutdownFunction( KEYSET_INFO *keysetInfo )
	{
	ldap_unbind( keysetInfo->keysetLDAP.ld );
	keysetInfo->keysetLDAP.ld = NULL;
	}

/* Open a connection to an LDAP directory */

static int initFunction( KEYSET_INFO *keysetInfo, const char *server,
						 const char *user, const CRYPT_KEYOPT_TYPE options )
	{
	char ldapServer[ MAX_URL_SIZE ];
	int maxEntries = 2, timeout, ldapPort, ldapStatus = LDAP_OTHER;

	/* Check the URL.  The Netscape API provides the function
	   ldap_is_ldap_url() for this, but this requires a complete LDAP URL
	   rather than just a server name and port */
	if( strlen( server ) > MAX_URL_SIZE - 1 )
		return( CRYPT_ARGERROR_STR1 );
	ldapPort = parseURL( ldapServer, server );

	/* Open the connection to the server */
	if( ( keysetInfo->keysetLDAP.ld = \
				ldap_init( ldapServer, ldapPort ) ) == NULL )
		return( CRYPT_ERROR_OPEN );
	if( ( ldapStatus = \
				ldap_simple_bind_s( keysetInfo->keysetLDAP.ld, 
									( char * ) user, NULL ) ) != LDAP_SUCCESS )
		{
		getErrorInfo( keysetInfo, ldapStatus );
		ldap_unbind( keysetInfo->keysetLDAP.ld );
		keysetInfo->keysetLDAP.ld = NULL;
		return( mapLDAPerror( ldapStatus, CRYPT_ERROR_OPEN ) );
		}

	/* Set the search timeout and limit the maximum number of returned 
	   entries to 2 */
	krnlSendMessage( keysetInfo->ownerHandle, RESOURCE_IMESSAGE_GETATTRIBUTE, 
					 &timeout, CRYPT_OPTION_NET_CONNECTTIMEOUT );
	ldap_set_option( keysetInfo->keysetLDAP.ld, LDAP_OPT_TIMELIMIT, &timeout );
	ldap_set_option( keysetInfo->keysetLDAP.ld, LDAP_OPT_SIZELIMIT, &maxEntries );

	/* Set up the names of the objects and attributes */
	assignFieldName( keysetInfo->ownerHandle, 
					 keysetInfo->keysetLDAP.nameObjectClass,
					 CRYPT_OPTION_KEYS_LDAP_OBJECTCLASS );
	assignFieldName( keysetInfo->ownerHandle, 
					 keysetInfo->keysetLDAP.nameFilter,
					 CRYPT_OPTION_KEYS_LDAP_FILTER );
	assignFieldName( keysetInfo->ownerHandle, 
					 keysetInfo->keysetLDAP.nameCACert,
					 CRYPT_OPTION_KEYS_LDAP_CACERTNAME );
	assignFieldName( keysetInfo->ownerHandle, 
					 keysetInfo->keysetLDAP.nameCert,
					 CRYPT_OPTION_KEYS_LDAP_CERTNAME );
	assignFieldName( keysetInfo->ownerHandle, 
					 keysetInfo->keysetLDAP.nameCRL,
					 CRYPT_OPTION_KEYS_LDAP_CRLNAME );
	assignFieldName( keysetInfo->ownerHandle, 
					 keysetInfo->keysetLDAP.nameEmail,
					 CRYPT_OPTION_KEYS_LDAP_EMAILNAME );
	krnlSendMessage( keysetInfo->ownerHandle, RESOURCE_IMESSAGE_GETATTRIBUTE, 
					 &keysetInfo->keysetLDAP.objectType, 
					 CRYPT_OPTION_KEYS_LDAP_OBJECTTYPE );

	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*						 	Directory Access Routines						*
*																			*
****************************************************************************/

/* Retrieve a key attribute from an LDAP directory */

static int getItemFunction( KEYSET_INFO *keysetInfo, 
							CRYPT_HANDLE *iCryptHandle, 
							const KEYMGMT_ITEM_TYPE itemType,
							const CRYPT_KEYID_TYPE keyIDtype, 
							const void *keyID,  const int keyIDlength, 
							void *auxInfo, int *auxInfoLength, 
							const int flags )
	{
	LDAPMessage *result, *resultEntry;
	BerElement *ber;
	struct berval **valuePtrs;
	char *attributePtr;
	int status = CRYPT_OK;

	assert( keyIDtype != CRYPT_KEYID_NONE || iCryptHandle != NULL );
	assert( itemType == KEYMGMT_ITEM_PUBLICKEY );
	assert( auxInfo == NULL ); assert( *auxInfoLength == 0 );

	/* If we're not in the middle of an ongoing fetch, send the query to the
	   server */
	if( !keysetInfo->queryInProgress )
		{
		const CRYPT_CERTTYPE_TYPE objectType = keysetInfo->keysetLDAP.objectType;
		const char *certAttributes[] = { keysetInfo->keysetLDAP.nameCert, NULL };
		const char *caCertAttributes[] = { keysetInfo->keysetLDAP.nameCACert, NULL };
		const char *crlAttributes[] = { keysetInfo->keysetLDAP.nameCRL, NULL };
		char dn[ MAX_DN_STRINGSIZE ];
		int ldapStatus = LDAP_OTHER;

		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';

		/* Try and retrieve the entry for this DN from the directory.  We use
		   a base specified by the DN, a chop of 0 (to return only the
		   current entry), any object class (to get around the problem of
		   implementations which stash certs in whatever they feel like), and
		   look for a certificate attribute.  If the search fails for this
		   attribute, we try again but this time go for a CA certificate
		   attribute which unfortunately slows down the search somewhat when
		   the cert isn't found but can't really be avoided since there's no
		   way to tell in advance whether a cert will be an end entity or a
		   CA cert.  To complicate things even further, we may also need to 
		   check for a CRL in case this is what the user is after */
		if( objectType == CRYPT_CERTTYPE_NONE || \
			objectType == CRYPT_CERTTYPE_CERTIFICATE )
			ldapStatus = ldap_search_s( keysetInfo->keysetLDAP.ld, dn,
								LDAP_SCOPE_BASE, 
								keysetInfo->keysetLDAP.nameFilter, 
								( char ** ) certAttributes, 0, &result );
		if( ldapStatus != LDAP_SUCCESS && \
			( objectType == CRYPT_CERTTYPE_NONE || \
			  objectType == CRYPT_CERTTYPE_CERTIFICATE ) )
			ldapStatus = ldap_search_s( keysetInfo->keysetLDAP.ld, dn,
								LDAP_SCOPE_BASE, 
								keysetInfo->keysetLDAP.nameFilter, 
								( char ** ) caCertAttributes, 0, &result );
		if( ldapStatus != LDAP_SUCCESS && \
			( objectType == CRYPT_CERTTYPE_NONE || \
			  objectType == CRYPT_CERTTYPE_CRL ) )
			ldapStatus = ldap_search_s( keysetInfo->keysetLDAP.ld, dn,
								LDAP_SCOPE_BASE, 
								keysetInfo->keysetLDAP.nameFilter, 
								( char ** ) crlAttributes, 0, &result );
		if( ldapStatus != LDAP_SUCCESS )
			{
			getErrorInfo( keysetInfo, ldapStatus );
			return( mapLDAPerror( ldapStatus, CRYPT_ERROR_READ ) );
			}

		/* We got something, start fetching the results */
		if( ( resultEntry = ldap_first_entry( keysetInfo->keysetLDAP.ld, result ) ) == NULL )
			{
			ldap_msgfree( result );
			return( CRYPT_ERROR_NOTFOUND );
			}

		/* If we've been passed a null crypt handle, this is the start of a 
		   general-purpose query rather than a single cert fetch, save the 
		   query state and record the fact that we're in the middle of a 
		   query */
		if( iCryptHandle == NULL )
			{
			keysetInfo->keysetLDAP.result = result;
			keysetInfo->queryInProgress = TRUE;
			}
		}
	else
		{
		/* We're in an ongoing query, try and fetch the next set of results */
		if( ( resultEntry = ldap_next_entry( keysetInfo->keysetLDAP.ld,
								keysetInfo->keysetLDAP.result ) ) == NULL )
			{
			/* No more results, wrap up the processing */
			ldap_msgfree( keysetInfo->keysetLDAP.result );
			keysetInfo->keysetLDAP.result = NULL;
			return( CRYPT_ERROR_COMPLETE );
			}
		}

	/* Copy out the certificate */
	if( ( attributePtr = ldap_first_attribute( keysetInfo->keysetLDAP.ld,
											   resultEntry, &ber ) ) == NULL )
		{
		if( keysetInfo->queryInProgress )
			ldap_msgfree( result );
		return( CRYPT_ERROR_NOTFOUND );
		}
	valuePtrs = ldap_get_values_len( keysetInfo->keysetLDAP.ld, resultEntry,
									 attributePtr );
	if( valuePtrs != NULL )
		{
		MESSAGE_CREATEOBJECT_INFO createInfo;

		/* Create a certificate object from the returned data */
		setMessageCreateObjectIndirectInfo( &createInfo, valuePtrs[ 0 ]->bv_val, 
											valuePtrs[ 0 ]->bv_len );
		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, 

⌨️ 快捷键说明

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