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

  1. /**********************************************************************/
  2. /** Microsoft Windows NT **/
  3. /** Copyright(c) Microsoft Corp., 2001 **/
  4. /**********************************************************************/
  5. #ifndef __ADIO_HXX__
  6. #define __ADIO_HXX__
  7. /*
  8. adio.hxx
  9. Class definition for module to manage access to Active Directory.
  10. FILE HISTORY:
  11. RobSol 17-May-2001 Created.
  12. */
  13. //------------------------------------------------------------------------------------------
  14. //
  15. // this class maintains caching of a LDAP connections. One instance per LDAP connection
  16. //
  17. //------------------------------------------------------------------------------------------
  18. class LdapCacheItem
  19. {
  20. friend class LDAP_CONN_CACHE;
  21. private:
  22. //
  23. // used by the linked list routines
  24. //
  25. LIST_ENTRY m_Link;
  26. //
  27. // name of domain for which LDAP connection established
  28. //
  29. StatStr<DNLEN+1> m_strDomainName;
  30. //
  31. // Distingushed Name of domain - needed for the ldap_search routine
  32. //
  33. StatStr<MAX_PATH+1> m_strForestDN;
  34. //
  35. // cached LDAP connection
  36. //
  37. LDAP *m_ldapConnection;
  38. //
  39. // reference count of users of this instance
  40. //
  41. LONG m_RefCount;
  42. DWORD Forest2DN( PCSTR pszForest);
  43. public:
  44. LdapCacheItem(
  45. const STR & DomainName,
  46. const STR & strUser,
  47. const STR & strDomain,
  48. const STR & strPassword);
  49. ~LdapCacheItem();
  50. VOID AddRef()
  51. { InterlockedIncrement( &m_RefCount ); }
  52. VOID Release() {
  53. if (InterlockedDecrement( &m_RefCount ) > 0) {
  54. return;
  55. }
  56. delete this;
  57. }
  58. BOOL IsDomainNameMatch( const STR & DomainName) const
  59. { return m_strDomainName.Equ( DomainName ); }
  60. LDAP *QueryConnection() const
  61. { return m_ldapConnection; }
  62. PCHAR QueryForestDN() const
  63. { return m_strForestDN.QueryStr(); }
  64. };
  65. typedef LdapCacheItem *PLdapCacheItem;
  66. //------------------------------------------------------------------------------------------
  67. //
  68. // this class interfaces and manages caching of all LDAP connection cache objects for a
  69. // single server instance. it maintains the connection credentials for that server instance.
  70. //
  71. //------------------------------------------------------------------------------------------
  72. class LDAP_CONN_CACHE
  73. {
  74. private:
  75. //
  76. // linked list head for LdapCacheItem instances
  77. //
  78. LIST_ENTRY m_ConnList;
  79. //
  80. // critical section to control access to the list.
  81. //
  82. CRITICAL_SECTION m_cs;
  83. //
  84. // name domain and password for user to authenticate LDAP connections.
  85. //
  86. StatStr<UNLEN+1> m_User;
  87. StatStr<DNLEN+1> m_Domain;
  88. StatStr<PWLEN+1> m_Pass;
  89. inline VOID Lock() { ::EnterCriticalSection( &m_cs ); }
  90. inline VOID Unlock() { ::LeaveCriticalSection( &m_cs ); }
  91. public:
  92. LDAP_CONN_CACHE();
  93. ~LDAP_CONN_CACHE();
  94. DWORD Configure(
  95. const STR & strUser,
  96. const STR & strDomain,
  97. const STR & strPassword);
  98. PLdapCacheItem QueryLdapConnection( const STR & Domain );
  99. };
  100. typedef LDAP_CONN_CACHE *PLDAP_CONN_CACHE;
  101. //------------------------------------------------------------------------------------------
  102. //
  103. // anonymous user AD property cache. one instance per site
  104. // refreshes itself after a global timeout
  105. //
  106. //------------------------------------------------------------------------------------------
  107. class ADIO_ANONYM_CACHE {
  108. private:
  109. //
  110. // indicates whether the instance is valid. Set to TRUE when object initialized
  111. // successfully, set to FALSE when shuting down
  112. //
  113. BOOL m_Valid;
  114. //
  115. // reference count of usage. One count for the AD_IO object that points to this instance,
  116. // and one more for each query while the content is refreshed with data from AD or until
  117. // the ceched data is copied.
  118. //
  119. DWORD m_Reference;
  120. //
  121. // time when object has last been refreshed.
  122. //
  123. ULONGLONG m_TimeStamp;
  124. //
  125. // name and domain of user impersonating the anonymous ftp user
  126. //
  127. StatStr<UNLEN+1> m_User;
  128. StatStr<DNLEN+1> m_Domain;
  129. //
  130. // cached home directory path for the anonymous user
  131. //
  132. StatStr<MAX_PATH+1> m_Path;
  133. //
  134. // critical section to lock the instance when reconfidured or the cached data updated.
  135. //
  136. CRITICAL_SECTION m_cs;
  137. VOID Lock() { ::EnterCriticalSection( &m_cs ); }
  138. VOID Unlock() { ::LeaveCriticalSection( &m_cs ); }
  139. public:
  140. ADIO_ANONYM_CACHE();
  141. ~ADIO_ANONYM_CACHE();
  142. DWORD Configure(
  143. IN PCSTR pszUser,
  144. IN PCSTR pszDomain);
  145. BOOL Reference();
  146. VOID Release(
  147. BOOL Shutdown = FALSE);
  148. DWORD GetCachedPath(
  149. STR & TargetPath,
  150. PLDAP_CONN_CACHE pConnCache);
  151. };
  152. typedef ADIO_ANONYM_CACHE *LPADIO_ANONYM_CACHE;
  153. //------------------------------------------------------------------------------------------
  154. //
  155. // Asynchronous IO to the Active Directory
  156. //
  157. //------------------------------------------------------------------------------------------
  158. //
  159. // states for an asynchronously serviced request.
  160. //
  161. typedef enum _eState {
  162. RequestStateInitial = 0,
  163. RequestStateRetrieve,
  164. RequestStateDone
  165. } eAdioAsyncState;
  166. typedef VOID (*tpAdioAsyncCallback)( HANDLE Ctx, DWORD Result );
  167. class ADIO_ASYNC
  168. {
  169. private:
  170. // STATIC (GLOBAL) DATA
  171. //
  172. // critical section to lock access to the static members of the ADIO_ASYNC service
  173. // (lists, etc)
  174. //
  175. static CRITICAL_SECTION m_cs;
  176. //
  177. // total allocated request objects
  178. //
  179. static volatile LONG m_NumTotalAlloc;
  180. //
  181. // total request objects in the free list cache
  182. //
  183. static volatile LONG m_NumTotalFree;
  184. //
  185. // list head for active (pending) requests
  186. //
  187. static LIST_ENTRY m_WorkListHead;
  188. //
  189. // list head for free request object cache
  190. //
  191. static LIST_ENTRY m_FreeListHead;
  192. //
  193. // number of threads started to service async requests
  194. //
  195. static LONG m_ActiveThreads;
  196. //
  197. // handles to active threads
  198. //
  199. static HANDLE m_Threads[];
  200. //
  201. // array of events the async service threads sleep on
  202. //
  203. static HANDLE m_Events[];
  204. // PER INSTANCE DATA
  205. //
  206. // status of last operation on the instance
  207. //
  208. DWORD m_Status;
  209. //
  210. // next state of processing for this instance
  211. //
  212. eAdioAsyncState m_State;
  213. //
  214. // handle of the ldap connection cache
  215. //
  216. PLDAP_CONN_CACHE m_pConnCache;
  217. //
  218. // pointer to the DLAP cache item with the ldap connection for the current user domain
  219. //
  220. PLdapCacheItem m_pLdapCacheItem;
  221. //
  222. // reference number to the ldap asynchronous request
  223. //
  224. ULONG m_AsyncMsgNum;
  225. //
  226. // account name of current user
  227. //
  228. StatStr<UNLEN+1> m_strUser;
  229. //
  230. // domain name of current user
  231. //
  232. StatStr<DNLEN+1> m_strDomain;
  233. //
  234. // pointer to buffer where path name will be stored
  235. //
  236. STR *m_pstrTarget;
  237. //
  238. // ldap message pointer
  239. //
  240. LDAPMessage *m_pLdapMsg;
  241. //
  242. // ldap message type
  243. //
  244. ULONG m_LdapMsgType;
  245. //
  246. // pointer to callback routine where client is notified when request completed
  247. //
  248. tpAdioAsyncCallback m_pfnClientCallback;
  249. //
  250. // client context user passed back with callback routine
  251. //
  252. HANDLE m_hClientCtx;
  253. //
  254. // link this instance into the global lists
  255. //
  256. LIST_ENTRY m_Link;
  257. static inline VOID Lock() { ::EnterCriticalSection( &m_cs ); }
  258. static inline VOID Unlock() { ::LeaveCriticalSection( &m_cs ); }
  259. static ADIO_ASYNC *Alloc();
  260. static VOID Free( ADIO_ASYNC *pReq);
  261. static BOOL FetchRequest( ADIO_ASYNC **ppRec );
  262. VOID QueueWork( VOID ) {
  263. Lock();
  264. InsertTailList( &m_WorkListHead, &m_Link );
  265. Unlock();
  266. }
  267. static DWORD WorkerThread( LPVOID pParam);
  268. BOOL IsResultReady();
  269. VOID Reset( VOID );
  270. BOOL ProcessSearch(BOOL fSyncSearch = FALSE);
  271. BOOL ProcessRetrieve();
  272. VOID ProcessComplete();
  273. public:
  274. ADIO_ASYNC() {}
  275. ~ADIO_ASYNC() {}
  276. static BOOL Initialize();
  277. static BOOL Terminate();
  278. static DWORD QueryRootDir(
  279. const STR & strUser,
  280. const STR & strDomain,
  281. PLDAP_CONN_CACHE pConnCache,
  282. STR * pstrTarget,
  283. ADIO_ASYNC ** ppadioReqCtx,
  284. tpAdioAsyncCallback pfnCallback,
  285. HANDLE hClientCtx);
  286. static DWORD QueryRootDir_Sync(
  287. const STR & strUser,
  288. const STR & strDomain,
  289. PLDAP_CONN_CACHE pConnCache,
  290. STR & strTarget);
  291. VOID EndRequest();
  292. };
  293. typedef ADIO_ASYNC *PADIO_ASYNC;
  294. //------------------------------------------------------------------------------------------
  295. //
  296. // The AD_IO class is the interface to the active directory. It provides these services
  297. // - dynamically load ldap libraries and binds to the needed functions
  298. // - maintains reference and unloads ldap libs when no longer needed
  299. // - interfaces the LDAP connection cache
  300. // - interfaces the anonymous user property cache
  301. //
  302. //------------------------------------------------------------------------------------------
  303. //
  304. // function pointers for dynamic binding
  305. // to avoid the overhead of loading AD DLLs when not in enterprise isolation mode, we load
  306. // these DLLs dynamically when needed. For normal product build, *DO NOT* define the constant
  307. // USE_STATIC_FUNCTION_BINDING. Defining the constant allows compiling the source code with
  308. // the system defined function prototypes, to validate no changes have been made to the lib
  309. // functions.
  310. //
  311. // #define USE_STATIC_FUNCTION_BINDING 1
  312. #if defined( USE_STATIC_FUNCTION_BINDING )
  313. #define pfn_DsGetDcName DsGetDcNameA
  314. #define pfn_NetApiBufferFree NetApiBufferFree
  315. #define pfn_ldap_init ldap_init
  316. #define pfn_ldap_set_option ldap_set_option
  317. #define pfn_ldap_bind_s ldap_bind_s
  318. #define pfn_ldap_unbind ldap_unbind
  319. #define pfn_ldap_search ldap_search
  320. #define pfn_ldap_search_s ldap_search_s
  321. #define pfn_ldap_first_entry ldap_first_entry
  322. #define pfn_ldap_get_values ldap_get_values
  323. #define pfn_ldap_value_free ldap_value_free
  324. #define pfn_ldap_msgfree ldap_msgfree
  325. #define pfn_ldap_abandon ldap_abandon
  326. #define pfn_ldap_result ldap_result
  327. #define pfn_ldap_parse_result ldap_parse_result
  328. #define pfn_LdapGetLastError LdapGetLastError
  329. #else // USE_STATIC_FUNCTION_BINDING
  330. #define pfn_DsGetDcName AD_IO::_pfn_DsGetDcName
  331. #define pfn_NetApiBufferFree AD_IO::_pfn_NetApiBufferFree
  332. #define pfn_ldap_init AD_IO::_pfn_ldap_init
  333. #define pfn_ldap_set_option AD_IO::_pfn_ldap_set_option
  334. #define pfn_ldap_bind_s AD_IO::_pfn_ldap_bind_s
  335. #define pfn_ldap_unbind AD_IO::_pfn_ldap_unbind
  336. #define pfn_ldap_search AD_IO::_pfn_ldap_search
  337. #define pfn_ldap_search_s AD_IO::_pfn_ldap_search_s
  338. #define pfn_ldap_first_entry AD_IO::_pfn_ldap_first_entry
  339. #define pfn_ldap_get_values AD_IO::_pfn_ldap_get_values
  340. #define pfn_ldap_value_free AD_IO::_pfn_ldap_value_free
  341. #define pfn_ldap_msgfree AD_IO::_pfn_ldap_msgfree
  342. #define pfn_ldap_abandon AD_IO::_pfn_ldap_abandon
  343. #define pfn_ldap_result AD_IO::_pfn_ldap_result
  344. #define pfn_ldap_parse_result AD_IO::_pfn_ldap_parse_result
  345. #define pfn_LdapGetLastError AD_IO::_pfn_LdapGetLastError
  346. //
  347. // functions in NETAPI32.DLL
  348. // these prototypes must match the corresponding function prototypes in the system header files
  349. //
  350. typedef DWORD (WINAPI *type_DsGetDcName)(
  351. LPCSTR,
  352. LPCSTR,
  353. GUID *,
  354. LPCSTR,
  355. ULONG,
  356. PDOMAIN_CONTROLLER_INFOA *);
  357. typedef NET_API_STATUS (NET_API_FUNCTION *type_NetApiBufferFree)(
  358. LPVOID);
  359. //
  360. // functions in WLDAP32.DLL
  361. //
  362. typedef LDAP * (LDAPAPI *type_ldap_init)(
  363. PCHAR HostName,
  364. ULONG PortNumber);
  365. typedef ULONG (LDAPAPI *type_ldap_set_option)(
  366. LDAP *ld,
  367. int option,
  368. const void *invalue);
  369. typedef ULONG (LDAPAPI *type_ldap_bind_s)(
  370. LDAP *ld,
  371. PCHAR dn,
  372. PCHAR cred,
  373. ULONG method);
  374. typedef ULONG (LDAPAPI *type_ldap_unbind)(
  375. LDAP *ld);
  376. typedef ULONG (LDAPAPI *type_ldap_search)(
  377. LDAP *ld,
  378. PCHAR base,
  379. ULONG scope,
  380. PCHAR filter,
  381. PCHAR attrs[],
  382. ULONG attrsonly);
  383. typedef ULONG (LDAPAPI *type_ldap_search_s)(
  384. LDAP *ld,
  385. PCHAR base,
  386. ULONG scope,
  387. PCHAR filter,
  388. PCHAR attrs[],
  389. ULONG attrsonly,
  390. LDAPMessage **res);
  391. typedef ULONG (LDAPAPI *type_ldap_search_ext)(
  392. LDAP *ld,
  393. PCHAR base,
  394. ULONG scope,
  395. PCHAR filter,
  396. PCHAR attrs[],
  397. ULONG attrsonly,
  398. PLDAPControlA *ServerControls,
  399. PLDAPControlA *ClientControls,
  400. ULONG TimeLimit,
  401. ULONG SizeLimit,
  402. ULONG *MessageNumber);
  403. typedef ULONG (LDAPAPI *type_ldap_search_ext_s)(
  404. LDAP *ld,
  405. PCHAR base,
  406. ULONG scope,
  407. PCHAR filter,
  408. PCHAR attrs[],
  409. ULONG attrsonly,
  410. PLDAPControlA *ServerControls,
  411. PLDAPControlA *ClientControls,
  412. struct l_timeval *timeout,
  413. ULONG SizeLimit,
  414. LDAPMessage **res);
  415. typedef LDAPMessage * (LDAPAPI *type_ldap_first_entry)(
  416. LDAP *ld,
  417. LDAPMessage *res);
  418. typedef PCHAR * (LDAPAPI *type_ldap_get_values)(
  419. LDAP *ld,
  420. LDAPMessage *entry,
  421. const PCHAR attr);
  422. typedef ULONG (LDAPAPI *type_ldap_result)(
  423. LDAP *ld,
  424. ULONG msgid,
  425. ULONG all,
  426. struct l_timeval *timeout,
  427. LDAPMessage **res);
  428. typedef ULONG (LDAPAPI *type_ldap_parse_result)(
  429. LDAP *Connection,
  430. LDAPMessage *ResultMessage,
  431. ULONG *ReturnCode OPTIONAL,
  432. PCHAR *MatchedDNs OPTIONAL,
  433. PCHAR *ErrorMessage OPTIONAL,
  434. PCHAR **Referrals OPTIONAL,
  435. PLDAPControlA **ServerControls OPTIONAL,
  436. BOOLEAN Freeit);
  437. typedef ULONG (LDAPAPI *type_ldap_abandon)(
  438. LDAP *ld,
  439. ULONG msgid);
  440. typedef ULONG (LDAPAPI *type_ldap_value_free)(
  441. PCHAR *vals);
  442. typedef ULONG (LDAPAPI *type_ldap_msgfree)(
  443. LDAPMessage *res);
  444. typedef ULONG (LDAPAPI *type_LdapGetLastError)(
  445. VOID);
  446. #endif // USE_STATIC_FUNCTION_BINDING
  447. class AD_IO
  448. {
  449. public:
  450. #if !defined( USE_STATIC_FUNCTION_BINDING )
  451. static HMODULE hNetApi32;
  452. static type_DsGetDcName _pfn_DsGetDcName;
  453. static type_NetApiBufferFree _pfn_NetApiBufferFree;
  454. static HMODULE hWLdap32;
  455. static type_ldap_init _pfn_ldap_init;
  456. static type_ldap_set_option _pfn_ldap_set_option;
  457. static type_ldap_bind_s _pfn_ldap_bind_s;
  458. static type_ldap_unbind _pfn_ldap_unbind;
  459. static type_ldap_search _pfn_ldap_search;
  460. static type_ldap_search_s _pfn_ldap_search_s;
  461. static type_ldap_first_entry _pfn_ldap_first_entry;
  462. static type_ldap_get_values _pfn_ldap_get_values;
  463. static type_ldap_abandon _pfn_ldap_abandon;
  464. static type_ldap_result _pfn_ldap_result;
  465. static type_ldap_parse_result _pfn_ldap_parse_result;
  466. static type_ldap_value_free _pfn_ldap_value_free;
  467. static type_ldap_msgfree _pfn_ldap_msgfree;
  468. static type_LdapGetLastError _pfn_LdapGetLastError;
  469. #endif
  470. private:
  471. //
  472. // global service refcount to AD_IO. when > 0, libs loaded, and all ldap interfaces
  473. // initialized. when dropped to 0, all ldap interfaces shut down.
  474. //
  475. static DWORD m_dwRefCount;
  476. //
  477. // critical section to control access to the global members
  478. //
  479. static CRITICAL_SECTION m_cs;
  480. //
  481. // indicates when the AD_IO global services have been properly initialized
  482. //
  483. static BOOL m_fLibsInitOK;
  484. //
  485. // credentials for connecting to the Active Directory
  486. //
  487. StatStr<UNLEN+1> m_User;
  488. StatStr<DNLEN+1> m_Domain;
  489. StatStr<PWLEN+1> m_Pass;
  490. //
  491. // LDAP connection cache
  492. //
  493. PLDAP_CONN_CACHE m_pConnCache;
  494. //
  495. // cache of anonymous user properties
  496. //
  497. LPADIO_ANONYM_CACHE m_pAnonymCache;
  498. inline VOID Lock() { ::EnterCriticalSection( &m_cs ); }
  499. inline VOID Unlock() { ::LeaveCriticalSection( &m_cs ); }
  500. public:
  501. static VOID Initialize() {
  502. INITIALIZE_CRITICAL_SECTION( &m_cs );
  503. m_dwRefCount = 0;
  504. }
  505. static VOID Terminate() {
  506. DeleteCriticalSection( &m_cs );
  507. }
  508. AD_IO();
  509. ~AD_IO();
  510. DWORD Configure(
  511. const STR & strADAccUser,
  512. const STR & strADAccDomain,
  513. const STR & strADAccPass,
  514. PCSTR pszAnonUser,
  515. PCSTR pszAnonDomain);
  516. DWORD GetUserHomeDir(
  517. const STR & strUser,
  518. const STR & strDomain,
  519. STR * pstrTarget,
  520. ADIO_ASYNC ** ppadioReqCtx,
  521. tpAdioAsyncCallback pfnCallback,
  522. HANDLE hCLientCtx);
  523. DWORD GetAnonymHomeDir(
  524. STR & strTarget) const {
  525. return m_pAnonymCache ?
  526. m_pAnonymCache->GetCachedPath(
  527. strTarget,
  528. m_pConnCache) :
  529. ERROR_BAD_CONFIGURATION;
  530. }
  531. };
  532. typedef AD_IO *LPAD_IO;
  533. #endif // __ADIO_HXX__