Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

711 lines
18 KiB

/**********************************************************************/
/** Microsoft Windows NT **/
/** Copyright(c) Microsoft Corp., 2001 **/
/**********************************************************************/
#ifndef __ADIO_HXX__
#define __ADIO_HXX__
/*
adio.hxx
Class definition for module to manage access to Active Directory.
FILE HISTORY:
RobSol 17-May-2001 Created.
*/
//------------------------------------------------------------------------------------------
//
// this class maintains caching of a LDAP connections. One instance per LDAP connection
//
//------------------------------------------------------------------------------------------
class LdapCacheItem
{
friend class LDAP_CONN_CACHE;
private:
//
// used by the linked list routines
//
LIST_ENTRY m_Link;
//
// name of domain for which LDAP connection established
//
StatStr<DNLEN+1> m_strDomainName;
//
// Distingushed Name of domain - needed for the ldap_search routine
//
StatStr<MAX_PATH+1> m_strForestDN;
//
// cached LDAP connection
//
LDAP *m_ldapConnection;
//
// reference count of users of this instance
//
LONG m_RefCount;
DWORD Forest2DN( PCSTR pszForest);
public:
LdapCacheItem(
const STR & DomainName,
const STR & strUser,
const STR & strDomain,
const STR & strPassword);
~LdapCacheItem();
VOID AddRef()
{ InterlockedIncrement( &m_RefCount ); }
VOID Release() {
if (InterlockedDecrement( &m_RefCount ) > 0) {
return;
}
delete this;
}
BOOL IsDomainNameMatch( const STR & DomainName) const
{ return m_strDomainName.Equ( DomainName ); }
LDAP *QueryConnection() const
{ return m_ldapConnection; }
PCHAR QueryForestDN() const
{ return m_strForestDN.QueryStr(); }
};
typedef LdapCacheItem *PLdapCacheItem;
//------------------------------------------------------------------------------------------
//
// this class interfaces and manages caching of all LDAP connection cache objects for a
// single server instance. it maintains the connection credentials for that server instance.
//
//------------------------------------------------------------------------------------------
class LDAP_CONN_CACHE
{
private:
//
// linked list head for LdapCacheItem instances
//
LIST_ENTRY m_ConnList;
//
// critical section to control access to the list.
//
CRITICAL_SECTION m_cs;
//
// name domain and password for user to authenticate LDAP connections.
//
StatStr<UNLEN+1> m_User;
StatStr<DNLEN+1> m_Domain;
StatStr<PWLEN+1> m_Pass;
inline VOID Lock() { ::EnterCriticalSection( &m_cs ); }
inline VOID Unlock() { ::LeaveCriticalSection( &m_cs ); }
public:
LDAP_CONN_CACHE();
~LDAP_CONN_CACHE();
DWORD Configure(
const STR & strUser,
const STR & strDomain,
const STR & strPassword);
PLdapCacheItem QueryLdapConnection( const STR & Domain );
};
typedef LDAP_CONN_CACHE *PLDAP_CONN_CACHE;
//------------------------------------------------------------------------------------------
//
// anonymous user AD property cache. one instance per site
// refreshes itself after a global timeout
//
//------------------------------------------------------------------------------------------
class ADIO_ANONYM_CACHE {
private:
//
// indicates whether the instance is valid. Set to TRUE when object initialized
// successfully, set to FALSE when shuting down
//
BOOL m_Valid;
//
// reference count of usage. One count for the AD_IO object that points to this instance,
// and one more for each query while the content is refreshed with data from AD or until
// the ceched data is copied.
//
DWORD m_Reference;
//
// time when object has last been refreshed.
//
ULONGLONG m_TimeStamp;
//
// name and domain of user impersonating the anonymous ftp user
//
StatStr<UNLEN+1> m_User;
StatStr<DNLEN+1> m_Domain;
//
// cached home directory path for the anonymous user
//
StatStr<MAX_PATH+1> m_Path;
//
// critical section to lock the instance when reconfidured or the cached data updated.
//
CRITICAL_SECTION m_cs;
VOID Lock() { ::EnterCriticalSection( &m_cs ); }
VOID Unlock() { ::LeaveCriticalSection( &m_cs ); }
public:
ADIO_ANONYM_CACHE();
~ADIO_ANONYM_CACHE();
DWORD Configure(
IN PCSTR pszUser,
IN PCSTR pszDomain);
BOOL Reference();
VOID Release(
BOOL Shutdown = FALSE);
DWORD GetCachedPath(
STR & TargetPath,
PLDAP_CONN_CACHE pConnCache);
};
typedef ADIO_ANONYM_CACHE *LPADIO_ANONYM_CACHE;
//------------------------------------------------------------------------------------------
//
// Asynchronous IO to the Active Directory
//
//------------------------------------------------------------------------------------------
//
// states for an asynchronously serviced request.
//
typedef enum _eState {
RequestStateInitial = 0,
RequestStateRetrieve,
RequestStateDone
} eAdioAsyncState;
typedef VOID (*tpAdioAsyncCallback)( HANDLE Ctx, DWORD Result );
class ADIO_ASYNC
{
private:
// STATIC (GLOBAL) DATA
//
// critical section to lock access to the static members of the ADIO_ASYNC service
// (lists, etc)
//
static CRITICAL_SECTION m_cs;
//
// total allocated request objects
//
static volatile LONG m_NumTotalAlloc;
//
// total request objects in the free list cache
//
static volatile LONG m_NumTotalFree;
//
// list head for active (pending) requests
//
static LIST_ENTRY m_WorkListHead;
//
// list head for free request object cache
//
static LIST_ENTRY m_FreeListHead;
//
// number of threads started to service async requests
//
static LONG m_ActiveThreads;
//
// handles to active threads
//
static HANDLE m_Threads[];
//
// array of events the async service threads sleep on
//
static HANDLE m_Events[];
// PER INSTANCE DATA
//
// status of last operation on the instance
//
DWORD m_Status;
//
// next state of processing for this instance
//
eAdioAsyncState m_State;
//
// handle of the ldap connection cache
//
PLDAP_CONN_CACHE m_pConnCache;
//
// pointer to the DLAP cache item with the ldap connection for the current user domain
//
PLdapCacheItem m_pLdapCacheItem;
//
// reference number to the ldap asynchronous request
//
ULONG m_AsyncMsgNum;
//
// account name of current user
//
StatStr<UNLEN+1> m_strUser;
//
// domain name of current user
//
StatStr<DNLEN+1> m_strDomain;
//
// pointer to buffer where path name will be stored
//
STR *m_pstrTarget;
//
// ldap message pointer
//
LDAPMessage *m_pLdapMsg;
//
// ldap message type
//
ULONG m_LdapMsgType;
//
// pointer to callback routine where client is notified when request completed
//
tpAdioAsyncCallback m_pfnClientCallback;
//
// client context user passed back with callback routine
//
HANDLE m_hClientCtx;
//
// link this instance into the global lists
//
LIST_ENTRY m_Link;
static inline VOID Lock() { ::EnterCriticalSection( &m_cs ); }
static inline VOID Unlock() { ::LeaveCriticalSection( &m_cs ); }
static ADIO_ASYNC *Alloc();
static VOID Free( ADIO_ASYNC *pReq);
static BOOL FetchRequest( ADIO_ASYNC **ppRec );
VOID QueueWork( VOID ) {
Lock();
InsertTailList( &m_WorkListHead, &m_Link );
Unlock();
}
static DWORD WorkerThread( LPVOID pParam);
BOOL IsResultReady();
VOID Reset( VOID );
BOOL ProcessSearch(BOOL fSyncSearch = FALSE);
BOOL ProcessRetrieve();
VOID ProcessComplete();
public:
ADIO_ASYNC() {}
~ADIO_ASYNC() {}
static BOOL Initialize();
static BOOL Terminate();
static DWORD QueryRootDir(
const STR & strUser,
const STR & strDomain,
PLDAP_CONN_CACHE pConnCache,
STR * pstrTarget,
ADIO_ASYNC ** ppadioReqCtx,
tpAdioAsyncCallback pfnCallback,
HANDLE hClientCtx);
static DWORD QueryRootDir_Sync(
const STR & strUser,
const STR & strDomain,
PLDAP_CONN_CACHE pConnCache,
STR & strTarget);
VOID EndRequest();
};
typedef ADIO_ASYNC *PADIO_ASYNC;
//------------------------------------------------------------------------------------------
//
// The AD_IO class is the interface to the active directory. It provides these services
// - dynamically load ldap libraries and binds to the needed functions
// - maintains reference and unloads ldap libs when no longer needed
// - interfaces the LDAP connection cache
// - interfaces the anonymous user property cache
//
//------------------------------------------------------------------------------------------
//
// function pointers for dynamic binding
// to avoid the overhead of loading AD DLLs when not in enterprise isolation mode, we load
// these DLLs dynamically when needed. For normal product build, *DO NOT* define the constant
// USE_STATIC_FUNCTION_BINDING. Defining the constant allows compiling the source code with
// the system defined function prototypes, to validate no changes have been made to the lib
// functions.
//
// #define USE_STATIC_FUNCTION_BINDING 1
#if defined( USE_STATIC_FUNCTION_BINDING )
#define pfn_DsGetDcName DsGetDcNameA
#define pfn_NetApiBufferFree NetApiBufferFree
#define pfn_ldap_init ldap_init
#define pfn_ldap_set_option ldap_set_option
#define pfn_ldap_bind_s ldap_bind_s
#define pfn_ldap_unbind ldap_unbind
#define pfn_ldap_search ldap_search
#define pfn_ldap_search_s ldap_search_s
#define pfn_ldap_first_entry ldap_first_entry
#define pfn_ldap_get_values ldap_get_values
#define pfn_ldap_value_free ldap_value_free
#define pfn_ldap_msgfree ldap_msgfree
#define pfn_ldap_abandon ldap_abandon
#define pfn_ldap_result ldap_result
#define pfn_ldap_parse_result ldap_parse_result
#define pfn_LdapGetLastError LdapGetLastError
#else // USE_STATIC_FUNCTION_BINDING
#define pfn_DsGetDcName AD_IO::_pfn_DsGetDcName
#define pfn_NetApiBufferFree AD_IO::_pfn_NetApiBufferFree
#define pfn_ldap_init AD_IO::_pfn_ldap_init
#define pfn_ldap_set_option AD_IO::_pfn_ldap_set_option
#define pfn_ldap_bind_s AD_IO::_pfn_ldap_bind_s
#define pfn_ldap_unbind AD_IO::_pfn_ldap_unbind
#define pfn_ldap_search AD_IO::_pfn_ldap_search
#define pfn_ldap_search_s AD_IO::_pfn_ldap_search_s
#define pfn_ldap_first_entry AD_IO::_pfn_ldap_first_entry
#define pfn_ldap_get_values AD_IO::_pfn_ldap_get_values
#define pfn_ldap_value_free AD_IO::_pfn_ldap_value_free
#define pfn_ldap_msgfree AD_IO::_pfn_ldap_msgfree
#define pfn_ldap_abandon AD_IO::_pfn_ldap_abandon
#define pfn_ldap_result AD_IO::_pfn_ldap_result
#define pfn_ldap_parse_result AD_IO::_pfn_ldap_parse_result
#define pfn_LdapGetLastError AD_IO::_pfn_LdapGetLastError
//
// functions in NETAPI32.DLL
// these prototypes must match the corresponding function prototypes in the system header files
//
typedef DWORD (WINAPI *type_DsGetDcName)(
LPCSTR,
LPCSTR,
GUID *,
LPCSTR,
ULONG,
PDOMAIN_CONTROLLER_INFOA *);
typedef NET_API_STATUS (NET_API_FUNCTION *type_NetApiBufferFree)(
LPVOID);
//
// functions in WLDAP32.DLL
//
typedef LDAP * (LDAPAPI *type_ldap_init)(
PCHAR HostName,
ULONG PortNumber);
typedef ULONG (LDAPAPI *type_ldap_set_option)(
LDAP *ld,
int option,
const void *invalue);
typedef ULONG (LDAPAPI *type_ldap_bind_s)(
LDAP *ld,
PCHAR dn,
PCHAR cred,
ULONG method);
typedef ULONG (LDAPAPI *type_ldap_unbind)(
LDAP *ld);
typedef ULONG (LDAPAPI *type_ldap_search)(
LDAP *ld,
PCHAR base,
ULONG scope,
PCHAR filter,
PCHAR attrs[],
ULONG attrsonly);
typedef ULONG (LDAPAPI *type_ldap_search_s)(
LDAP *ld,
PCHAR base,
ULONG scope,
PCHAR filter,
PCHAR attrs[],
ULONG attrsonly,
LDAPMessage **res);
typedef ULONG (LDAPAPI *type_ldap_search_ext)(
LDAP *ld,
PCHAR base,
ULONG scope,
PCHAR filter,
PCHAR attrs[],
ULONG attrsonly,
PLDAPControlA *ServerControls,
PLDAPControlA *ClientControls,
ULONG TimeLimit,
ULONG SizeLimit,
ULONG *MessageNumber);
typedef ULONG (LDAPAPI *type_ldap_search_ext_s)(
LDAP *ld,
PCHAR base,
ULONG scope,
PCHAR filter,
PCHAR attrs[],
ULONG attrsonly,
PLDAPControlA *ServerControls,
PLDAPControlA *ClientControls,
struct l_timeval *timeout,
ULONG SizeLimit,
LDAPMessage **res);
typedef LDAPMessage * (LDAPAPI *type_ldap_first_entry)(
LDAP *ld,
LDAPMessage *res);
typedef PCHAR * (LDAPAPI *type_ldap_get_values)(
LDAP *ld,
LDAPMessage *entry,
const PCHAR attr);
typedef ULONG (LDAPAPI *type_ldap_result)(
LDAP *ld,
ULONG msgid,
ULONG all,
struct l_timeval *timeout,
LDAPMessage **res);
typedef ULONG (LDAPAPI *type_ldap_parse_result)(
LDAP *Connection,
LDAPMessage *ResultMessage,
ULONG *ReturnCode OPTIONAL,
PCHAR *MatchedDNs OPTIONAL,
PCHAR *ErrorMessage OPTIONAL,
PCHAR **Referrals OPTIONAL,
PLDAPControlA **ServerControls OPTIONAL,
BOOLEAN Freeit);
typedef ULONG (LDAPAPI *type_ldap_abandon)(
LDAP *ld,
ULONG msgid);
typedef ULONG (LDAPAPI *type_ldap_value_free)(
PCHAR *vals);
typedef ULONG (LDAPAPI *type_ldap_msgfree)(
LDAPMessage *res);
typedef ULONG (LDAPAPI *type_LdapGetLastError)(
VOID);
#endif // USE_STATIC_FUNCTION_BINDING
class AD_IO
{
public:
#if !defined( USE_STATIC_FUNCTION_BINDING )
static HMODULE hNetApi32;
static type_DsGetDcName _pfn_DsGetDcName;
static type_NetApiBufferFree _pfn_NetApiBufferFree;
static HMODULE hWLdap32;
static type_ldap_init _pfn_ldap_init;
static type_ldap_set_option _pfn_ldap_set_option;
static type_ldap_bind_s _pfn_ldap_bind_s;
static type_ldap_unbind _pfn_ldap_unbind;
static type_ldap_search _pfn_ldap_search;
static type_ldap_search_s _pfn_ldap_search_s;
static type_ldap_first_entry _pfn_ldap_first_entry;
static type_ldap_get_values _pfn_ldap_get_values;
static type_ldap_abandon _pfn_ldap_abandon;
static type_ldap_result _pfn_ldap_result;
static type_ldap_parse_result _pfn_ldap_parse_result;
static type_ldap_value_free _pfn_ldap_value_free;
static type_ldap_msgfree _pfn_ldap_msgfree;
static type_LdapGetLastError _pfn_LdapGetLastError;
#endif
private:
//
// global service refcount to AD_IO. when > 0, libs loaded, and all ldap interfaces
// initialized. when dropped to 0, all ldap interfaces shut down.
//
static DWORD m_dwRefCount;
//
// critical section to control access to the global members
//
static CRITICAL_SECTION m_cs;
//
// indicates when the AD_IO global services have been properly initialized
//
static BOOL m_fLibsInitOK;
//
// credentials for connecting to the Active Directory
//
StatStr<UNLEN+1> m_User;
StatStr<DNLEN+1> m_Domain;
StatStr<PWLEN+1> m_Pass;
//
// LDAP connection cache
//
PLDAP_CONN_CACHE m_pConnCache;
//
// cache of anonymous user properties
//
LPADIO_ANONYM_CACHE m_pAnonymCache;
inline VOID Lock() { ::EnterCriticalSection( &m_cs ); }
inline VOID Unlock() { ::LeaveCriticalSection( &m_cs ); }
public:
static VOID Initialize() {
INITIALIZE_CRITICAL_SECTION( &m_cs );
m_dwRefCount = 0;
}
static VOID Terminate() {
DeleteCriticalSection( &m_cs );
}
AD_IO();
~AD_IO();
DWORD Configure(
const STR & strADAccUser,
const STR & strADAccDomain,
const STR & strADAccPass,
PCSTR pszAnonUser,
PCSTR pszAnonDomain);
DWORD GetUserHomeDir(
const STR & strUser,
const STR & strDomain,
STR * pstrTarget,
ADIO_ASYNC ** ppadioReqCtx,
tpAdioAsyncCallback pfnCallback,
HANDLE hCLientCtx);
DWORD GetAnonymHomeDir(
STR & strTarget) const {
return m_pAnonymCache ?
m_pAnonymCache->GetCachedPath(
strTarget,
m_pConnCache) :
ERROR_BAD_CONFIGURATION;
}
};
typedef AD_IO *LPAD_IO;
#endif // __ADIO_HXX__