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

📄 ldap.c

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

/* The following code can be built to use the Netscape or Windows LDAP
   clients.  By default the Windows client is used under Windows and the
   Netscape client is used elsewhere, this can be overridden by defining
   NETSCAPE_CLIENT which causes the Netscape client to be used in all
   cases.  The Windows client appears to be considerably more buggy than
   the Netscape one, so if you get data corruption and other problems try
   switching to the Netscape client (see the comment next to ber_free() for
   more details on some of these problems).

   A generalisation of this is that you shouldn't be using LDAP for
   certificate storage at all unless you're absolutely forced to.  LDAP
   is a truly awful mechanism for storing and retrieving certificates,
   technical reasons for this may be found in the Godzilla crypto tutorial
   and in any database text written within the last 20 years */

#include <stdlib.h>
#include <string.h>
#if defined( INC_ALL )
  #include "crypt.h"
  #include "keyset.h"
#elif defined( INC_CHILD )
  #include "../crypt.h"
  #include "keyset.h"
#else
  #include "crypt.h"
  #include "keyset/keyset.h"
#endif /* Compiler-specific includes */

#ifdef USE_LDAP

/* LDAP requires us to set up complicated structures to handle DN's.  The
   following values define the upper limit for DN string data and the
   maximum number of attributes we write to a directory */

#define MAX_DN_STRINGSIZE		1024
#define MAX_LDAP_ATTRIBUTES		20

/* These should really be taken from the system include directory but this
   leads to too many complaints from people who don't read the LDAP
   installation section of the manual */

#if defined( __WINDOWS__ ) && !defined( NETSCAPE_CLIENT )
  /* cryptlib.h includes a trap for inclusion of wincrypt.h before 
     cryptlib.h which results in a compiler error if both files are 
	 included.  To disable this, we need to undefine the CRYPT_MODE_ECB 
	 defined in cryptlib.h */
  #undef CRYPT_MODE_ECB
  #include <winldap.h>
  #define LDAP_API		LDAPAPI		/* Windows LDAP API type */
  #define timeval		l_timeval	/* Windows uses nonstandard name */
#else
  #define NETSCAPE_CLIENT			/* Force use of Netscape on non-Win.sys.*/
  #if defined( INC_ALL ) || defined( INC_CHILD )
	#include "ldap.h"
  #else
	#include "keyset/ldap.h"
  #endif /* Compiler-specific includes */
  #define LDAP_API		LDAP_CALL	/* Netscape LDAP API type */
  #define ber_free		ldap_ber_free	/* Netscape uses nonstandard name */
#endif /* Windows vs Netscape client */

/****************************************************************************
*																			*
*						 	Windows Init/Shutdown Routines					*
*																			*
****************************************************************************/

#ifdef __WINDOWS__

/* Global function pointers.  These are necessary because the functions need
   to be dynamically linked since few older systems contain the necessary
   DLL's (LDAP?  Get real).  Explicitly linking to them will make cryptlib
   unloadable on most systems */

#define NULL_HINSTANCE	( HINSTANCE ) NULL

static HINSTANCE hLDAP = NULL_HINSTANCE;

typedef void ( LDAP_API *BER_FREE )( BerElement *ber, int freebuf );
typedef int ( LDAP_API *LDAP_ADD_S )( LDAP *ld, const char *dn, LDAPMod **attrs );
typedef int ( LDAP_API *LDAP_DELETE_S )( LDAP *ld, const char *dn );
typedef char * ( LDAP_API *LDAP_ERR2STRING )( int err );
typedef char * ( LDAP_API *LDAP_FIRST_ATTRIBUTE )( LDAP *ld, LDAPMessage *entry,
										  BerElement **ber );
typedef LDAPMessage * ( LDAP_API *LDAP_FIRST_ENTRY )( LDAP *ld, LDAPMessage *result );
#ifdef NETSCAPE_CLIENT
  typedef int ( LDAP_API *LDAP_GET_LDERRNO )( LDAP *ld, char **m, char **s );
#else
  typedef int ( LDAP_API *LDAP_GETLASTERROR )( void );
#endif /* NETSCAPE_CLIENT */
typedef struct berval ** ( LDAP_API *LDAP_GET_VALUES_LEN )( LDAP *ld, LDAPMessage *entry,
												   const char *attr );
typedef LDAP * ( LDAP_API *LDAP_INIT )( const char *host, int port );
typedef int ( LDAP_API *LDAP_IS_LDAP_URL )( char *url );
typedef void ( LDAP_API *LDAP_MEMFREE )( void *p );
typedef void ( LDAP_API *LDAP_MODSFREE )( LDAPMod **mods, int freemods );
typedef int ( LDAP_API *LDAP_MSGFREE )( LDAPMessage *lm );
typedef LDAPMessage * ( LDAP_API *LDAP_NEXT_ENTRY )( LDAP *ld, LDAPMessage *result );
typedef int ( LDAP_API *LDAP_SEARCH_ST )( LDAP *ld, const char *base, int scope,
								const char *filter, char **attrs,
								int attrsonly, struct timeval *timeout,
								LDAPMessage **res );
typedef int ( LDAP_API *LDAP_SET_OPTION )( LDAP *ld, int option, void *optdata );
typedef int ( LDAP_API *LDAP_SIMPLE_BIND_S )( LDAP *ld, const char *who,
									 const char *passwd );
typedef int ( LDAP_API *LDAP_UNBIND )( LDAP *ld );
typedef int ( LDAP_API *LDAP_URL_SEARCH_ST )( LDAP *ld, char *url, int attrsonly,
											  struct timeval *timeout,
											  LDAPMessage **res );
typedef void ( LDAP_API *LDAP_VALUE_FREE_LEN )( struct berval **vals );
static BER_FREE p_ber_free = NULL;
static LDAP_ADD_S p_ldap_add_s = NULL;
static LDAP_DELETE_S p_ldap_delete_s = NULL;
static LDAP_ERR2STRING p_ldap_err2string = NULL;
static LDAP_FIRST_ATTRIBUTE p_ldap_first_attribute = NULL;
static LDAP_FIRST_ENTRY p_ldap_first_entry = NULL;
#ifdef NETSCAPE_CLIENT
  static LDAP_GET_LDERRNO p_ldap_get_lderrno = NULL;
#else
  static LDAP_GETLASTERROR p_LdapGetLastError = NULL;
#endif /* NETSCAPE_CLIENT */
static LDAP_GET_VALUES_LEN p_ldap_get_values_len = NULL;
static LDAP_INIT p_ldap_init = NULL;
static LDAP_IS_LDAP_URL p_ldap_is_ldap_url = NULL;
static LDAP_MEMFREE p_ldap_memfree = NULL;
static LDAP_NEXT_ENTRY p_ldap_next_entry = NULL;
static LDAP_MSGFREE p_ldap_msgfree = NULL;
static LDAP_SEARCH_ST p_ldap_search_st = NULL;
static LDAP_SET_OPTION p_ldap_set_option = NULL;
static LDAP_SIMPLE_BIND_S p_ldap_simple_bind_s = NULL;
static LDAP_UNBIND p_ldap_unbind = NULL;
static LDAP_URL_SEARCH_ST p_ldap_url_search_st = NULL;
static LDAP_VALUE_FREE_LEN p_ldap_value_free_len = NULL;

/* The use of dynamically bound function pointers vs statically linked
   functions requires a bit of sleight of hand since we can't give the
   pointers the same names as prototyped functions.  To get around this we
   redefine the actual function names to the names of the pointers */

#define ber_free				p_ber_free
#define ldap_add_s				p_ldap_add_s
#define ldap_delete_s			p_ldap_delete_s
#define ldap_err2string			p_ldap_err2string
#define ldap_first_attribute	p_ldap_first_attribute
#define ldap_first_entry		p_ldap_first_entry
#ifdef NETSCAPE_CLIENT
  #define ldap_get_lderrno		p_ldap_get_lderrno
#else
  #define LdapGetLastError		p_LdapGetLastError
#endif /* NETSCAPE_CLIENT */
#define ldap_get_values_len		p_ldap_get_values_len
#define ldap_init				p_ldap_init
#define ldap_is_ldap_url		p_ldap_is_ldap_url
#define ldap_memfree			p_ldap_memfree
#define ldap_msgfree			p_ldap_msgfree
#define ldap_next_entry			p_ldap_next_entry
#define ldap_search_st			p_ldap_search_st
#define ldap_set_option			p_ldap_set_option
#define ldap_simple_bind_s		p_ldap_simple_bind_s
#define ldap_unbind				p_ldap_unbind
#define ldap_url_search_st		p_ldap_url_search_st
#define ldap_value_free_len		p_ldap_value_free_len

/* The name of the LDAP driver, in this case the Netscape LDAPv3 driver */

#ifdef __WIN16__
  #define LDAP_LIBNAME			"NSLDSS16.DLL"
#else
  #ifdef NETSCAPE_CLIENT
	#define LDAP_LIBNAME		"NSLDAP32v30.DLL"
  #else
	#define LDAP_LIBNAME		"wldap32.dll"
  #endif /* NETSCAPE_CLIENT */
#endif /* __WIN16__ */

/* Dynamically load and unload any necessary LDAP libraries */

int dbxInitLDAP( void )
	{
#ifdef __WIN16__
	UINT errorMode;
#endif /* __WIN16__ */

	/* If the LDAP module is already linked in, don't do anything */
	if( hLDAP != NULL_HINSTANCE )
		return( CRYPT_OK );

	/* Obtain a handle to the module containing the LDAP functions */
#ifdef __WIN16__
	errorMode = SetErrorMode( SEM_NOOPENFILEERRORBOX );
	hLDAP = LoadLibrary( LDAP_LIBNAME );
	SetErrorMode( errorMode );
	if( hLDAP < HINSTANCE_ERROR )
		{
		hLDAP = NULL_HINSTANCE;
		return( CRYPT_ERROR );
		}
#else
	if( ( hLDAP = LoadLibrary( LDAP_LIBNAME ) ) == NULL_HINSTANCE )
		return( CRYPT_ERROR );
#endif /* __WIN32__ */

	/* Now get pointers to the functions */
#ifdef NETSCAPE_CLIENT
	p_ber_free = ( BER_FREE ) GetProcAddress( hLDAP, "ldap_ber_free" );
#else
	p_ber_free = ( BER_FREE ) GetProcAddress( hLDAP, "ber_free" );
#endif /* NETSCAPE_CLIENT */
	p_ldap_add_s = ( LDAP_ADD_S ) GetProcAddress( hLDAP, "ldap_add_s" );
	p_ldap_delete_s = ( LDAP_DELETE_S ) GetProcAddress( hLDAP, "ldap_delete_s" );
	p_ldap_err2string = ( LDAP_ERR2STRING ) GetProcAddress( hLDAP, "ldap_err2string" );
	p_ldap_first_attribute = ( LDAP_FIRST_ATTRIBUTE ) GetProcAddress( hLDAP, "ldap_first_attribute" );
	p_ldap_first_entry = ( LDAP_FIRST_ENTRY ) GetProcAddress( hLDAP, "ldap_first_entry" );
#ifdef NETSCAPE_CLIENT
	p_ldap_get_lderrno = ( LDAP_GET_LDERRNO ) GetProcAddress( hLDAP, "ldap_get_lderrno" );
#else
	p_LdapGetLastError = ( LDAP_GETLASTERROR ) GetProcAddress( hLDAP, "LdapGetLastError" );
#endif /* NETSCAPE_CLIENT */
	p_ldap_get_values_len = ( LDAP_GET_VALUES_LEN ) GetProcAddress( hLDAP, "ldap_get_values_len" );
	p_ldap_init = ( LDAP_INIT ) GetProcAddress( hLDAP, "ldap_init" );
	p_ldap_is_ldap_url = ( LDAP_IS_LDAP_URL ) GetProcAddress( hLDAP, "ldap_is_ldap_url" );
	p_ldap_memfree = ( LDAP_MEMFREE ) GetProcAddress( hLDAP, "ldap_memfree" );
	p_ldap_msgfree = ( LDAP_MSGFREE ) GetProcAddress( hLDAP, "ldap_msgfree" );
	p_ldap_next_entry = ( LDAP_NEXT_ENTRY ) GetProcAddress( hLDAP, "ldap_next_entry" );
	p_ldap_search_st = ( LDAP_SEARCH_ST ) GetProcAddress( hLDAP, "ldap_search_st" );
	p_ldap_set_option = ( LDAP_SET_OPTION ) GetProcAddress( hLDAP, "ldap_set_option" );
	p_ldap_simple_bind_s = ( LDAP_SIMPLE_BIND_S ) GetProcAddress( hLDAP, "ldap_simple_bind_s" );
	p_ldap_unbind = ( LDAP_UNBIND ) GetProcAddress( hLDAP, "ldap_unbind" );
	p_ldap_url_search_st = ( LDAP_URL_SEARCH_ST ) GetProcAddress( hLDAP, "ldap_url_search_st" );
	p_ldap_value_free_len = ( LDAP_VALUE_FREE_LEN ) GetProcAddress( hLDAP, "ldap_value_free_len" );

	/* Make sure we got valid pointers for every LDAP function */
	if( p_ldap_add_s == NULL ||
#ifdef NETSCAPE_CLIENT
		p_ber_free == NULL ||
#endif /* NETSCAPE_CLIENT */
		p_ldap_delete_s == NULL || p_ldap_err2string == NULL || \
		p_ldap_first_attribute == NULL || p_ldap_first_entry == NULL || \
		p_ldap_init == NULL ||
#ifdef NETSCAPE_CLIENT
		p_ldap_get_lderrno == NULL || p_ldap_is_ldap_url == NULL ||
		p_ldap_url_search_st == NULL ||
#else
		p_LdapGetLastError == NULL ||
#endif /* NETSCAPE_CLIENT */
		p_ldap_get_values_len == NULL || p_ldap_memfree == NULL || \
		p_ldap_msgfree == NULL || p_ldap_next_entry == NULL || \
		p_ldap_search_st == NULL || p_ldap_set_option == NULL || \
		p_ldap_simple_bind_s == NULL || p_ldap_unbind == NULL || \
		p_ldap_value_free_len == NULL )
		{
		/* Free the library reference and reset the handle */
		FreeLibrary( hLDAP );
		hLDAP = NULL_HINSTANCE;
		return( CRYPT_ERROR );
		}

	return( CRYPT_OK );
	}

void dbxEndLDAP( void )
	{
	if( hLDAP != NULL_HINSTANCE )
		FreeLibrary( hLDAP );
	hLDAP = NULL_HINSTANCE;
	}
#endif /* __WINDOWS__ */

/****************************************************************************
*																			*
*						 		Utility Routines							*
*																			*
****************************************************************************/

/* Assign a name for an LDAP object/attribute field */

static void assignFieldName( const CRYPT_USER cryptOwner, char *buffer,
							 CRYPT_ATTRIBUTE_TYPE option )
	{
	RESOURCE_DATA msgData;
	int status;

	setMessageData( &msgData, buffer, CRYPT_MAX_TEXTSIZE );
	status = krnlSendMessage( cryptOwner, IMESSAGE_GETATTRIBUTE_S,
							  &msgData, option );
	assert( cryptStatusOK( status ) );
	buffer[ msgData.length ] = '\0';
	}

/* Get information on an LDAP error */

static void getErrorInfo( KEYSET_INFO *keysetInfo, int ldapStatus )
	{
	LDAP_INFO *ldapInfo = keysetInfo->keysetLDAP;
	char *errorMessage;

#ifdef NETSCAPE_CLIENT
	keysetInfo->errorCode = ldap_get_lderrno( ldapInfo->ld, NULL,
											  &errorMessage );
#else
	ldapInfo->errorCode = LdapGetLastError();
	if( ldapInfo->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 */
		ldapInfo->errorCode = ldapStatus;
	errorMessage = ldap_err2string( ldapInfo->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 */
	ldapInfo->errorCode = GetLastError();
	FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
				   NULL, ldapInfo->errorCode,
				   MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
				   ldapInfo->errorMessage, MAX_ERRMSG_SIZE - 1, NULL );
  #endif /* 0 */
#endif /* Netscape vs MS LDAP client */
	if( errorMessage != NULL )
		{
		strncpy( ldapInfo->errorMessage, errorMessage, MAX_ERRMSG_SIZE - 1 );
		ldapInfo->errorMessage[ MAX_ERRMSG_SIZE - 1 ] = '\0';
		}
	else
		*ldapInfo->errorMessage = '\0';
	}

/* Map an LDAP error to the corresponding cryptlib error.  Some Windows LDAP
   error codes differ slightly from the standard LDAP names 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:
#ifdef NETSCAPE_CLIENT
		case LDAP_INSUFFICIENT_ACCESS:
#else
		case LDAP_INSUFFICIENT_RIGHTS:
		case LDAP_AUTH_METHOD_NOT_SUPPORTED:
#endif /* NETSCAPE_CLIENT */
			return( CRYPT_ERROR_PERMISSION );

#ifdef NETSCAPE_CLIENT
		case LDAP_TYPE_OR_VALUE_EXISTS:
#else
		case LDAP_ATTRIBUTE_OR_VALUE_EXISTS:
#endif /* NETSCAPE_CLIENT */
			return( CRYPT_ERROR_DUPLICATE );

#ifndef NETSCAPE_CLIENT
		case LDAP_CONFIDENTIALITY_REQUIRED:
			return( CRYPT_ERROR_NOSECURE );
#endif /* NETSCAPE_CLIENT */

		case LDAP_INVALID_DN_SYNTAX:
			return( CRYPT_ARGERROR_STR1 );

#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:
			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;

⌨️ 快捷键说明

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