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

📄 ldap.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 4 页
字号:
	errorInfo->errorCode = LdapGetLastError();
	if( errorInfo->errorCode == LDAP_SUCCESS )
		{
		/* In true Microsoft fashion LdapGetLastError() can return
		   LDAP_SUCCESS with the error string set to "Success.", so if we
		   get this we use the status value returned by the original LDAP
		   function call instead */
		errorInfo->errorCode = ldapStatus;
		}
	errorMessage = ldap_err2string( errorInfo->errorCode );
  #if 0
	/* The exact conditions under which ldap_err2string() does something
	   useful are somewhat undefined, it may be necessary to use the
	   following which works with general Windows error codes rather than
	   special-case LDAP function result codes */
	errorInfo->errorCode = GetLastError();
	FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
				   NULL, errorInfo->errorCode,
				   MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
				   ldapInfo->errorMessage, MAX_ERRMSG_SIZE - 1, NULL );
  #endif /* 0 */
#elif defined( NETSCAPE_CLIENT )
	errorInfo->errorCode = ldap_get_lderrno( ldapInfo->ld, NULL,
											 &errorMessage );
#else
  /* As usual there are various incompatible ways of getting the necessary
	 information, we use whatever's available */
  #ifdef LDAP_OPT_ERROR_NUMBER
	ldap_get_option( ldapInfo->ld, LDAP_OPT_ERROR_NUMBER, 
					 &errorInfo->errorCode );
  #else
	ldap_get_option( ldapInfo->ld, LDAP_OPT_RESULT_CODE, 
					 &errorInfo->errorCode );
  #endif /* Various ways of getting the error information */
	ldap_get_option( ldapInfo->ld, LDAP_OPT_ERROR_STRING, 
					 &errorMessage );
#endif /* Different LDAP client types */
	if( errorMessage != NULL )
		setErrorString( errorInfo, errorMessage, strlen( errorMessage ) );
	else
		clearErrorString( errorInfo );
	}

/* Map an LDAP error to the corresponding cryptlib error.  The various LDAP
   imlpementations differ slightly in their error codes, so we have to 
   adjust them as appropriate */

static int mapLdapError( const int ldapError, const int defaultError )
	{
	switch( ldapError )
		{
		case LDAP_INAPPROPRIATE_AUTH:
		case LDAP_INVALID_CREDENTIALS:
		case LDAP_AUTH_UNKNOWN:
#if defined( __WINDOWS__ )
		case LDAP_INSUFFICIENT_RIGHTS:
		case LDAP_AUTH_METHOD_NOT_SUPPORTED:
#elif defined( NETSCAPE_CLIENT )
		case LDAP_INSUFFICIENT_ACCESS:
#else
		case LDAP_INSUFFICIENT_ACCESS:
		case LDAP_AUTH_METHOD_NOT_SUPPORTED:
#endif /* Different client types */
			return( CRYPT_ERROR_PERMISSION );

#if defined( __WINDOWS__ )
		case LDAP_ATTRIBUTE_OR_VALUE_EXISTS:
		case LDAP_ALREADY_EXISTS:
#elif defined( NETSCAPE_CLIENT )
		case LDAP_TYPE_OR_VALUE_EXISTS:
#else
		case LDAP_TYPE_OR_VALUE_EXISTS:
		case LDAP_ALREADY_EXISTS:
#endif /* Different client types */
			return( CRYPT_ERROR_DUPLICATE );

#if defined( __WINDOWS__ )
		case LDAP_CONFIDENTIALITY_REQUIRED:
#elif defined( NETSCAPE_CLIENT )
		/* Nothing */
#else
		case LDAP_CONFIDENTIALITY_REQUIRED:
		case LDAP_STRONG_AUTH_REQUIRED:
			return( CRYPT_ERROR_NOSECURE );
#endif /* Different client types */

		case LDAP_INVALID_DN_SYNTAX:
			return( CRYPT_ARGERROR_STR1 );

		case LDAP_TIMELIMIT_EXCEEDED:
		case LDAP_TIMEOUT:
			return( CRYPT_ERROR_TIMEOUT );

#ifndef NETSCAPE_CLIENT
		case LDAP_NO_RESULTS_RETURNED:
#endif /* NETSCAPE_CLIENT */
		case LDAP_NO_SUCH_ATTRIBUTE:
		case LDAP_NO_SUCH_OBJECT:
			return( CRYPT_ERROR_NOTFOUND );

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

		case LDAP_SIZELIMIT_EXCEEDED:
		case LDAP_RESULTS_TOO_LARGE:
			return( CRYPT_ERROR_OVERFLOW );

		case LDAP_NO_MEMORY:
			return( CRYPT_ERROR_MEMORY );
		}

	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 * ) clAlloc( "copyAttribute", \
											  sizeof( LDAPMod ) ) ) == NULL )
		return( NULL );
	if( ( ldapModPtr->mod_values = clAlloc( "copyAttribute", \
											2 * sizeof( void * ) ) ) == NULL )
		{
		clFree( "copyAttribute", 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 ] = \
				clAlloc( "copyAttribute", sizeof( struct berval ) ) ) == NULL )
			{
			clFree( "copyAttribute", ldapModPtr->mod_values );
			clFree( "copyAttribute", 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
   explicitly check for overflows (which will lead to truncation of the 
   resulting encoded DN) because the certificate management code limits the 
   size of each component to a small fraction of the total buffer size.  
   Besides which, it's LDAP, anyone using this crap as a certificate store 
   is asking for it anyway */

static void catComponent( char *dest, const int destLen, char *src )
	{
	int i;

	/* Find the end of the existing destination string */
	for( i = 0; i < destLen && dest[ i ] != '\0'; i++ );
	if( i >= destLen )
		retIntError_Void();

	/* Append the source string, escaping special chars */
	while( i < destLen - 1 && *src != '\0' )
		{
		const char ch = *src++;

		if( ch == ',' )
			{
			dest[ i++ ] = '\\';
			if( i >= destLen )
				break;
			}
		dest[ i++ ] = ch;
		}
	dest[ i ] = '\0';
	}

static int encodeDN( char *dn, const int maxDnLen, char *C, char *SP, 
					 char *L, char *O, char *OU, char *CN )
	{
	strlcpy_s( dn, maxDnLen, "CN=" );
	catComponent( dn, maxDnLen, CN );
	if( *OU )
		{
		strlcat_s( dn, maxDnLen, ",OU=" );
		catComponent( dn, maxDnLen, OU );
		}
	if( *O )
		{
		strlcat_s( dn, maxDnLen, ",O=" );
		catComponent( dn, maxDnLen, O );
		}
	if( *L )
		{
		strlcat_s( dn, maxDnLen, ",L=" );
		catComponent( dn, maxDnLen, L );
		}
	if( *SP )
		{
		strlcat_s( dn, maxDnLen, ",ST=" );	/* Not to be confused with ST=street */
		catComponent( dn, maxDnLen, SP );
		}
	strlcat_s( dn, maxDnLen, ",C=" );
	catComponent( dn, maxDnLen, C );

	return( CRYPT_OK );
	}

/* Decompose an LDAP URL of the general form ldap://server:port/user into its
   various components */

static int parseURL( char *ldapServer, char **ldapUser, int *ldapPort )
	{
	char *strPtr;

	/* Clear return value */
	*ldapUser = NULL;
	*ldapPort = LDAP_PORT;

	/* Handle a leading URL specifier if this is present */
	if( !strCompare( ldapServer, "ldaps://", 8 ) )
		/* We can't do LDAP over SSL without a lot of extra work */
		return( CRYPT_ERROR_BADDATA );
	if( !strCompare( ldapServer, "ldap://", 7 ) )
		memmove( ldapServer, ldapServer + 7, strlen( ldapServer ) - 6 );

	/* Decompose what's left into a FQDN, port, and user name */
	if( ( strPtr = strchr( ldapServer, '/' ) ) != NULL )
		{
		*strPtr++ = '\0';
		*ldapUser = strPtr;
		}
	if( ( strPtr = strchr( ldapServer, ':' ) ) != NULL )
		{
		*strPtr++ = '\0';
		*ldapPort = atoi( strPtr );
		if( *ldapPort < 26 || *ldapPort > 65534L )
			return( CRYPT_ERROR_BADDATA );
		}

	return( CRYPT_OK );
	}

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

STDC_NONNULL_ARG( ( 1 ) ) \
static int shutdownFunction( INOUT KEYSET_INFO *keysetInfoPtr )
	{
	LDAP_INFO *ldapInfo = keysetInfoPtr->keysetLDAP;

	assert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );

	REQUIRES( keysetInfoPtr->type == KEYSET_LDAP );

	ldap_unbind( ldapInfo->ld );
	ldapInfo->ld = NULL;

	return( CRYPT_OK );
	}

/* Open a connection to an LDAP directory */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int initFunction( INOUT KEYSET_INFO *keysetInfoPtr, 
						 IN_BUFFER( nameLength ) const char *name,
						 IN_LENGTH_SHORT const int nameLength,
						 IN_ENUM( CRYPT_KEYOPT ) const CRYPT_KEYOPT_TYPE options )
	{
	LDAP_INFO *ldapInfo = keysetInfoPtr->keysetLDAP;
	char ldapServer[ MAX_URL_SIZE + 8 ], *ldapUser;
	int maxEntries = 2, timeout, ldapPort, ldapStatus = LDAP_OTHER, status;

	assert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );
	assert( isReadPtr( name, nameLength ) );

	REQUIRES( keysetInfoPtr->type == KEYSET_LDAP );
	REQUIRES( nameLength >= MIN_URL_SIZE && nameLength < MAX_URL_SIZE );
	REQUIRES( options >= CRYPT_KEYOPT_NONE && options < CRYPT_KEYOPT_LAST );

	/* Check the URL.  The Netscape and OpenLDAP APIs provide the function
	   ldap_is_ldap_url() for this, but this requires a complete LDAP URL
	   rather than just a server name and port */
	if( nameLength > MAX_URL_SIZE - 1 )
		return( CRYPT_ARGERROR_STR1 );
	memcpy( ldapServer, name, nameLength );
	ldapServer[ nameLength ] = '\0';
	status = parseURL( ldapServer, &ldapUser, &ldapPort );
	if( cryptStatusError( status ) )
		return( CRYPT_ARGERROR_STR1 );

	/* Open the connection to the server */
	if( ( ldapInfo->ld = ldap_init( ldapServer, ldapPort ) ) == NULL )
		return( CRYPT_ERROR_OPEN );
	if( ( ldapStatus = ldap_simple_bind_s( ldapInfo->ld, ldapUser, 
										   NULL ) ) != LDAP_SUCCESS )
		{
		getErrorInfo( keysetInfoPtr, ldapStatus );
		ldap_unbind( ldapInfo->ld );
		ldapInfo->ld = NULL;
		return( mapLdapError( ldapStatus, CRYPT_ERROR_OPEN ) );
		}

	/* Set the search timeout and limit the maximum number of returned
	   entries to 2 (setting the search timeout is mostly redundant since we
	   use search_st anyway, however there may be other operations which also
	   require some sort of timeout which can't be explicitly specified */
	krnlSendMessage( keysetInfoPtr->ownerHandle, IMESSAGE_GETATTRIBUTE,
					 &timeout, CRYPT_OPTION_NET_READTIMEOUT );
	if( timeout < 15 )
		/* Network I/O may be set to be nonblocking, so we make sure we try
		   for at least 15s before timing out */

⌨️ 快捷键说明

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