📄 ldap.c
字号:
/****************************************************************************
* *
* cryptlib LDAP Mapping Routines *
* Copyright Peter Gutmann 1998-2004 *
* *
****************************************************************************/
/* The following code can be built to use most of the various subtly
incompatible LDAP clients. By default the Windows client is used under
Windows and the OpenLDAP client is used elsewhere, this can be overridden
by defining NETSCAPE_CLIENT which causes the Netscape client to be used
instead. Old versions of the Windows client were 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). Note that there are at least
five incompatible LDAP APIs, the one defined in the RFCs, the older
OpenLDAP API, the newer OpenLDAP API, the Windows API, and the Netscape
API. The following code tries to auto-adjust itself for all of the
different versions, but it may need some hand-tweaking.
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 */
#if defined( INC_ALL )
#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__ )
/* 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 */
#elif defined( NETSCAPE_CLIENT )
#include <ldap.h>
#define LDAP_API LDAP_CALL /* Netscape LDAP API type */
#define ber_free ldap_ber_free /* Netscape uses nonstandard name */
#else
#include <ldap.h>
#include <sys/time.h> /* For 'struct timeval' */
#ifdef LDAP_API
/* Some OpenLDAP versions have their own LDAP_API macro which is
incompatible with the usage here, so we clear it before we define our
own */
#undef LDAP_API
#endif /* LDAP_API */
#define LDAP_API /* OpenLDAP LDAP API type */
#endif /* Different LDAP client types */
/****************************************************************************
* *
* Windows Init/Shutdown Routines *
* *
****************************************************************************/
#ifdef DYNAMIC_LOAD
/* Global function pointers. These are necessary because the functions need
to be dynamically linked since older systems won't contain the necessary
DLL's. Explicitly linking to them will make cryptlib unloadable on these
systems */
static INSTANCE_HANDLE hLDAP = NULL_INSTANCE;
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 );
#if defined( __WINDOWS__ )
typedef int ( LDAP_API *LDAP_GETLASTERROR )( void );
#elif defined( NETSCAPE_CLIENT )
typedef int ( LDAP_API *LDAP_GET_LDERRNO )( LDAP *ld, char **m, char **s );
#else
typedef int ( LDAP_API *LDAP_GET_OPTION )( LDAP *ld, int option, void *outvalue );
#endif /* Different LDAP client types */
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 );
#if defined( __WINDOWS__ ) || defined( NETSCAPE_CLIENT )
static BER_FREE p_ber_free = NULL;
#endif /* __WINDOWS__ || NETSCAPE_CLIENT */
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;
#if defined( __WINDOWS__ )
static LDAP_GETLASTERROR p_LdapGetLastError = NULL;
#elif defined( NETSCAPE_CLIENT )
static LDAP_GET_LDERRNO p_ldap_get_lderrno = NULL;
#else
static LDAP_GET_OPTION p_ldap_get_option = NULL;
#endif /* Different LDAP client types */
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
#if defined( __WINDOWS__ )
#define LdapGetLastError p_LdapGetLastError
#elif defined( NETSCAPE_CLIENT )
#define ldap_get_lderrno p_ldap_get_lderrno
#else
#define ldap_get_option p_ldap_get_option
#endif /* Different LDAP client types */
#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"
#elif defined( __WIN32__ )
#define LDAP_LIBNAME "wldap32.dll"
#elif defined( __UNIX__ )
#if defined( __APPLE__ )
/* OS X has built-in LDAP support via OpenLDAP */
#define LDAP_LIBNAME "libldap.dylib"
#elif defined NETSCAPE_CLIENT
#define LDAP_LIBNAME "libldap50.so"
#else
#define LDAP_LIBNAME "libldap.so"
#endif /* NETSCAPE_CLIENT */
#endif /* System-specific ODBC library names */
/* 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_INSTANCE )
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_INSTANCE;
return( CRYPT_ERROR );
}
#else
if( ( hLDAP = DynamicLoad( LDAP_LIBNAME ) ) == NULL_INSTANCE )
return( CRYPT_ERROR );
#endif /* __WIN32__ */
/* Now get pointers to the functions */
#if defined( __WINDOWS__ )
p_ber_free = ( BER_FREE ) DynamicBind( hLDAP, "ber_free" );
#elif defined( NETSCAPE_CLIENT )
p_ber_free = ( BER_FREE ) DynamicBind( hLDAP, "ldap_ber_free" );
#endif /* __WINDOWS__ || NETSCAPE_CLIENT */
p_ldap_add_s = ( LDAP_ADD_S ) DynamicBind( hLDAP, "ldap_add_s" );
p_ldap_delete_s = ( LDAP_DELETE_S ) DynamicBind( hLDAP, "ldap_delete_s" );
p_ldap_err2string = ( LDAP_ERR2STRING ) DynamicBind( hLDAP, "ldap_err2string" );
p_ldap_first_attribute = ( LDAP_FIRST_ATTRIBUTE ) DynamicBind( hLDAP, "ldap_first_attribute" );
p_ldap_first_entry = ( LDAP_FIRST_ENTRY ) DynamicBind( hLDAP, "ldap_first_entry" );
#if defined( __WINDOWS__ )
p_LdapGetLastError = ( LDAP_GETLASTERROR ) DynamicBind( hLDAP, "LdapGetLastError" );
#elif defined( NETSCAPE_CLIENT )
p_ldap_get_lderrno = ( LDAP_GET_LDERRNO ) DynamicBind( hLDAP, "ldap_get_lderrno" );
#else
p_ldap_get_option = ( LDAP_GET_OPTION ) DynamicBind( hLDAP, "ldap_get_option" );
#endif /* Different LDAP client types */
p_ldap_get_values_len = ( LDAP_GET_VALUES_LEN ) DynamicBind( hLDAP, "ldap_get_values_len" );
p_ldap_init = ( LDAP_INIT ) DynamicBind( hLDAP, "ldap_init" );
p_ldap_is_ldap_url = ( LDAP_IS_LDAP_URL ) DynamicBind( hLDAP, "ldap_is_ldap_url" );
p_ldap_memfree = ( LDAP_MEMFREE ) DynamicBind( hLDAP, "ldap_memfree" );
p_ldap_msgfree = ( LDAP_MSGFREE ) DynamicBind( hLDAP, "ldap_msgfree" );
p_ldap_next_entry = ( LDAP_NEXT_ENTRY ) DynamicBind( hLDAP, "ldap_next_entry" );
p_ldap_search_st = ( LDAP_SEARCH_ST ) DynamicBind( hLDAP, "ldap_search_st" );
p_ldap_set_option = ( LDAP_SET_OPTION ) DynamicBind( hLDAP, "ldap_set_option" );
p_ldap_simple_bind_s = ( LDAP_SIMPLE_BIND_S ) DynamicBind( hLDAP, "ldap_simple_bind_s" );
p_ldap_unbind = ( LDAP_UNBIND ) DynamicBind( hLDAP, "ldap_unbind" );
p_ldap_url_search_st = ( LDAP_URL_SEARCH_ST ) DynamicBind( hLDAP, "ldap_url_search_st" );
p_ldap_value_free_len = ( LDAP_VALUE_FREE_LEN ) DynamicBind( hLDAP, "ldap_value_free_len" );
/* Make sure that 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 ||
#if defined( __WINDOWS__ )
p_LdapGetLastError == NULL ||
#elif defined( NETSCAPE_CLIENT )
p_ldap_get_lderrno == NULL || p_ldap_is_ldap_url == NULL ||
p_ldap_url_search_st == NULL ||
#else
p_ldap_get_option == 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 */
DynamicUnload( hLDAP );
hLDAP = NULL_INSTANCE;
return( CRYPT_ERROR );
}
/* Some versions of OpenLDAP define ldap_is_ldap_url() but not
ldap_url_search_st() (which makes the former more or less useless),
so if the latter isn't defined we remove the former as well */
if( p_ldap_url_search_st == NULL )
p_ldap_is_ldap_url = NULL;
return( CRYPT_OK );
}
void dbxEndLDAP( void )
{
if( hLDAP != NULL_INSTANCE )
DynamicUnload( hLDAP );
hLDAP = NULL_INSTANCE;
}
#else
int dbxInitLDAP( void )
{
return( CRYPT_OK );
}
void dbxEndLDAP( void )
{
}
#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 )
{
MESSAGE_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 *keysetInfoPtr, int ldapStatus )
{
ERROR_INFO *errorInfo = &keysetInfoPtr->errorInfo;
#ifndef __WINDOWS__
LDAP_INFO *ldapInfo = keysetInfoPtr->keysetLDAP;
#endif /* !__WINDOWS__ */
char *errorMessage;
#if defined( __WINDOWS__ )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -