Source code of Windows XP (NT5)
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.

3933 lines
84 KiB

  1. #include "ldapc.hxx"
  2. #pragma hdrstop
  3. //
  4. // Local helpers
  5. //
  6. extern "C" {
  7. DWORD
  8. GetDefaultLdapServer(
  9. LPWSTR Addresses[],
  10. LPDWORD Count,
  11. BOOL Verify,
  12. DWORD dwPort
  13. ) ;
  14. }
  15. WINLDAPAPI ULONG LDAPAPI ldap_get_optionW(
  16. LDAP *ld,
  17. int option,
  18. void *outvalue
  19. );
  20. DWORD
  21. GetDefaultServer(
  22. DWORD dwPort,
  23. BOOL fVerify,
  24. LPWSTR szDomainDnsName,
  25. LPWSTR szServerName,
  26. BOOL fWriteable
  27. );
  28. int ConvertToAscii( WCHAR *pszUnicode, char **pszAscii );
  29. int ConvertLDAPMod( LDAPModW **mods, LDAPModA ***modsA );
  30. void FreeLDAPMod( LDAPModA **modsA );
  31. BOOLEAN LDAPCodeWarrantsRetry(HRESULT hr);
  32. HRESULT LdapSearchHelper(
  33. LDAP *ld,
  34. WCHAR *base,
  35. int scope,
  36. WCHAR *filter,
  37. WCHAR *attrs[],
  38. int attrsonly,
  39. struct l_timeval *timeout,
  40. LDAPMessage **res
  41. );
  42. HRESULT
  43. GetOneToken(
  44. LPWSTR pszSource,
  45. LPWSTR * ppszToken,
  46. DWORD * pdwTokenLen,
  47. BOOL * pfMore
  48. );
  49. DWORD
  50. MaskKnownFlagsNotChecked(DWORD dwFlags)
  51. {
  52. DWORD dwRetVal = dwFlags;
  53. dwRetVal &= ~(ADS_PROMPT_CREDENTIALS
  54. | ADS_FAST_BIND
  55. | ADS_READONLY_SERVER
  56. | ADS_USE_SIGNING
  57. | ADS_USE_SEALING
  58. | ADS_USE_DELEGATION
  59. | ADS_SERVER_BIND
  60. | ADS_AUTH_RESERVED
  61. );
  62. return dwRetVal;
  63. }
  64. LPWSTR gpszServerName = NULL;
  65. LPWSTR gpszDomainName = NULL;
  66. //
  67. // High level Open/Close object functions
  68. //
  69. HRESULT LdapOpenObject(
  70. LPWSTR szLDAPServer,
  71. LPWSTR szLDAPDn,
  72. ADS_LDP **ld,
  73. CCredentials& Credentials,
  74. DWORD dwPort
  75. )
  76. {
  77. return LdapOpenObject2(
  78. szLDAPServer,
  79. NULL,
  80. szLDAPDn,
  81. ld,
  82. Credentials,
  83. dwPort
  84. );
  85. }
  86. HRESULT LdapOpenObject2(
  87. LPWSTR szDomainName,
  88. LPWSTR szLDAPServer,
  89. LPWSTR szLDAPDn,
  90. ADS_LDP **ld,
  91. CCredentials& Credentials,
  92. DWORD dwPort
  93. )
  94. {
  95. HRESULT hr = S_OK;
  96. int err = NO_ERROR;
  97. LUID Luid, ModifiedId;
  98. PADS_LDP pCacheEntry = NULL ;
  99. BOOL fAddToCache = TRUE ;
  100. LPWSTR aAddresses[5];
  101. BOOL fServerNotSpecified = FALSE;
  102. BOOL fVerify = FALSE;
  103. WCHAR szDomainDnsName[MAX_PATH];
  104. WCHAR szServerName[MAX_PATH];
  105. DWORD dwFlags = Credentials.GetAuthFlags();
  106. BOOL fStickyServerSpecified = (gpszServerName != NULL);
  107. //
  108. // start by nulling out this return value
  109. //
  110. *ld = NULL ;
  111. //
  112. // Now if the server name is Null - Get a serverName
  113. //
  114. if (!szDomainName) {
  115. RetryGetDefaultServer:
  116. err = GetDefaultServer(
  117. dwPort,
  118. fVerify,
  119. szDomainDnsName,
  120. szServerName,
  121. !(dwFlags & ADS_READONLY_SERVER) ? TRUE : FALSE
  122. );
  123. if (err != NOERROR) {
  124. return HRESULT_FROM_WIN32(err);
  125. }
  126. if (fStickyServerSpecified) {
  127. //
  128. // We need to change the name of the domain to be that of
  129. // the server we want to target. The swap is made if
  130. // 1) gpszDomainName == NULL, that implies that just
  131. // a serverName was set and not which domain it applies to.
  132. // 2) If a domainName is specified, then the domainName
  133. // from above should be that set in the global pointer for
  134. // the target server to be changed.
  135. //
  136. if ((gpszDomainName
  137. && (!_wcsicmp(szDomainDnsName, gpszDomainName))
  138. )
  139. || (gpszDomainName == NULL)
  140. ) {
  141. //
  142. // We need to change the target to the server.
  143. //
  144. wcscpy(szDomainDnsName,gpszServerName);
  145. szServerName[0] = L'\0';
  146. //
  147. // Make sure if server is down we go to another
  148. // server on the retryGetDefault server path.
  149. //
  150. fStickyServerSpecified = FALSE;
  151. }
  152. }
  153. szDomainName = szDomainDnsName;
  154. szLDAPServer = szServerName;
  155. fServerNotSpecified = TRUE;
  156. }
  157. #ifndef WIN95
  158. //
  159. // try the cache first. if find entry, just use it (this bumps ref count
  160. // up by one). if we cant get LUID, we dont use the cache.
  161. //
  162. if ((err = BindCacheGetLuid(&Luid, &ModifiedId)) == NO_ERROR) {
  163. //
  164. // Try the cache for the passed in credentials.
  165. //
  166. if (pCacheEntry = BindCacheLookup(szDomainName, Luid, ModifiedId, Credentials, dwPort)) {
  167. *ld = pCacheEntry ;
  168. return S_OK ;
  169. }
  170. }
  171. else {
  172. //
  173. // pick something that would NOT match anything else. and
  174. // never put this in the cache
  175. //
  176. Luid = ReservedLuid ;
  177. ModifiedId = ReservedLuid;
  178. fAddToCache = FALSE ;
  179. }
  180. #else
  181. //
  182. // In the case of win95, however, we always make the Luid to be the reserved
  183. // one and lookup the cache. If found use it, otherwise, add it.
  184. //
  185. Luid = ReservedLuid ;
  186. ModifiedId = ReservedLuid;
  187. if (pCacheEntry = BindCacheLookup(szDomainName, Luid, ModifiedId, Credentials, dwPort)) {
  188. *ld = pCacheEntry ;
  189. return S_OK ;
  190. }
  191. #endif
  192. //
  193. // allocate the pseudo handle (also the cache entry).
  194. //
  195. err = BindCacheAllocEntry(&pCacheEntry) ;
  196. if (err != NO_ERROR) {
  197. return HRESULT_FROM_WIN32(err);
  198. }
  199. if (!Credentials.IsNullCredentials()) {
  200. hr = LdapOpenBindWithCredentials(
  201. szDomainName,
  202. szLDAPServer,
  203. Credentials,
  204. pCacheEntry,
  205. dwPort
  206. );
  207. }else {
  208. //
  209. // We just want to try with NULL and NULL and
  210. // whatever flags were passed in. No longer want
  211. // to try and get credentials from registry.
  212. //
  213. hr = LdapOpenBindWithDefaultCredentials(
  214. szDomainName,
  215. szLDAPServer,
  216. Credentials,
  217. pCacheEntry,
  218. dwPort
  219. );
  220. }
  221. //
  222. // This is the Server-Less case; where we retry with a force
  223. // server to get a valid ServerName.
  224. //
  225. if (((hr == HRESULT_FROM_WIN32(ERROR_BAD_NETPATH)) ||
  226. (hr == HRESULT_FROM_WIN32(ERROR_DS_SERVER_DOWN))) &&
  227. !fVerify && fServerNotSpecified) {
  228. fVerify = TRUE;
  229. LdapUnbind(pCacheEntry);
  230. goto RetryGetDefaultServer ;
  231. }
  232. //
  233. // if success we add to cache. else unbind & cleanup.
  234. //
  235. if (SUCCEEDED(hr)) {
  236. if (!fAddToCache) {
  237. //
  238. // do not insert in cache since we didnt get LUID
  239. //
  240. }
  241. else {
  242. err = BindCacheAdd(szDomainName, Luid, ModifiedId, Credentials, dwPort, pCacheEntry) ;
  243. if (err != NO_ERROR) {
  244. LdapUnbind(pCacheEntry) ;
  245. hr = HRESULT_FROM_WIN32(err);
  246. }
  247. }
  248. }
  249. else {
  250. //
  251. // Bind failed, force err so that we will clean up
  252. // and return correct value
  253. //
  254. LdapUnbind(pCacheEntry) ; // needed to close out connection
  255. //
  256. // Set error value so that we do not return pCacheEntry.
  257. //
  258. err = ERROR_GEN_FAILURE;
  259. }
  260. if (err == NO_ERROR) {
  261. *ld = pCacheEntry ;
  262. }
  263. else {
  264. FreeADsMem(pCacheEntry) ;
  265. }
  266. return hr;
  267. }
  268. void LdapCloseObject(
  269. ADS_LDP *ld
  270. )
  271. {
  272. //
  273. // We will delete only if the count is zero and the keeparound
  274. // flag is not set.
  275. //
  276. if ((BindCacheDeref(ld) == 0) && !ld->fKeepAround) {
  277. //
  278. // ref count has dropped to zero and its gone from cache.
  279. //
  280. LdapUnbind(ld);
  281. FreeADsMem(ld);
  282. }
  283. }
  284. //
  285. // This routine adds a ref to the pointer. Note that to release
  286. // you use the LdapCloseObject routine.
  287. //
  288. void LdapCacheAddRef(
  289. ADS_LDP *ld
  290. )
  291. {
  292. ADsAssert(ld);
  293. BindCacheAddRef(ld);
  294. }
  295. //
  296. // NOTE: Ldap\ibute returns S_OK if attribute [szAttr] has no
  297. // values (*[aValues]=NULL, *[ncount]=0) but all else ok.
  298. //
  299. HRESULT LdapReadAttribute(
  300. WCHAR *szLDAPServer,
  301. LPWSTR szLDAPDn,
  302. WCHAR *szAttr,
  303. WCHAR ***aValues,
  304. int *nCount,
  305. CCredentials& Credentials,
  306. DWORD dwPort
  307. )
  308. {
  309. return LdapReadAttribute2(
  310. szLDAPServer,
  311. NULL,
  312. szLDAPDn,
  313. szAttr,
  314. aValues,
  315. nCount,
  316. Credentials,
  317. dwPort
  318. );
  319. }
  320. //
  321. // NOTE: LdapReadAttribute2 returns S_OK if attribute [szAttr] has no
  322. // values (*[aValues]=NULL, *[ncount]=0) but all else ok.
  323. //
  324. HRESULT LdapReadAttribute2(
  325. WCHAR *szDomainName,
  326. WCHAR *szLDAPServer,
  327. LPWSTR szLDAPDn,
  328. WCHAR *szAttr,
  329. WCHAR ***aValues,
  330. int *nCount,
  331. CCredentials& Credentials,
  332. DWORD dwPort,
  333. LPWSTR szFilter // defaulted to NULL
  334. )
  335. {
  336. HRESULT hr = S_OK;
  337. ADS_LDP *ld = NULL;
  338. LPWSTR aStrings[2];
  339. LDAPMessage *res = NULL;
  340. LDAPMessage *e = NULL;
  341. LPWSTR szFilterString = L"(objectClass=*)";
  342. if (szFilter != NULL) {
  343. szFilterString = szFilter;
  344. }
  345. hr = LdapOpenObject2(
  346. szDomainName,
  347. szLDAPServer,
  348. szLDAPDn,
  349. &ld,
  350. Credentials,
  351. dwPort
  352. );
  353. if (FAILED(hr))
  354. goto CleanExit;
  355. aStrings[0] = szAttr;
  356. aStrings[1] = NULL;
  357. ADsAssert(ld && ld->LdapHandle);
  358. hr = LdapSearchS( ld,
  359. szLDAPDn,
  360. LDAP_SCOPE_BASE,
  361. szFilterString,
  362. aStrings,
  363. 0,
  364. &res );
  365. // Only one entry should be returned
  366. if ( FAILED(hr)
  367. || FAILED(hr = LdapFirstEntry( ld, res, &e ))
  368. || FAILED(hr = LdapGetValues( ld, e, szAttr, aValues, nCount ))
  369. )
  370. {
  371. goto CleanExit;
  372. }
  373. CleanExit:
  374. if ( res )
  375. LdapMsgFree( res );
  376. if ( ld ){
  377. LdapCloseObject( ld );
  378. }
  379. return hr;
  380. }
  381. //
  382. // This is similar to ReadAttribute but uses a handle to avoid
  383. // the lookup in the bindCache
  384. //
  385. HRESULT LdapReadAttributeFast(
  386. ADS_LDP *ld,
  387. LPWSTR szLDAPDn,
  388. WCHAR *szAttr,
  389. WCHAR ***aValues,
  390. int *nCount
  391. )
  392. {
  393. HRESULT hr = S_OK;
  394. LPWSTR aStrings[2];
  395. LDAPMessage *res = NULL;
  396. LDAPMessage *entry = NULL;
  397. aStrings[0] = szAttr;
  398. aStrings[1] = NULL;
  399. hr = LdapSearchS(
  400. ld,
  401. szLDAPDn,
  402. LDAP_SCOPE_BASE,
  403. L"(objectClass=*)",
  404. aStrings,
  405. 0,
  406. &res
  407. );
  408. // Only one entry should be returned
  409. if ( FAILED(hr)
  410. || FAILED(hr = LdapFirstEntry( ld, res, &entry ))
  411. || FAILED(hr = LdapGetValues( ld, entry, szAttr, aValues, nCount ))
  412. )
  413. {
  414. goto CleanExit;
  415. }
  416. CleanExit:
  417. if ( res )
  418. LdapMsgFree( res );
  419. RRETURN(hr);
  420. }
  421. //
  422. // Wrappers around the ldap functions
  423. //
  424. HRESULT LdapOpen( WCHAR *domainName, WCHAR *hostName, int portno, ADS_LDP *ld, DWORD dwFlags )
  425. {
  426. HRESULT hr = 0;
  427. int ldaperr = 0;
  428. PADS_LDP pCacheEntry = ld ;
  429. DWORD dwOptions = 0;
  430. void *ldapOption;
  431. //
  432. // Reset the handle first
  433. //
  434. pCacheEntry->LdapHandle = NULL;
  435. pCacheEntry->LdapHandle = ldap_init( domainName, portno );
  436. if ( (pCacheEntry->LdapHandle) == NULL ) {
  437. hr = HRESULT_FROM_WIN32(ERROR_BAD_NETPATH);
  438. goto error;
  439. }
  440. ldaperr = ldap_get_option(pCacheEntry->LdapHandle, LDAP_OPT_GETDSNAME_FLAGS, &dwOptions);
  441. if (ldaperr != LDAP_SUCCESS) {
  442. CheckAndSetExtendedError(pCacheEntry->LdapHandle, &hr, ldaperr);
  443. goto error;
  444. }
  445. if (portno == GC_PORT || portno == GC_SSL_PORT) {
  446. dwOptions |= DS_GC_SERVER_REQUIRED;
  447. } else if (!(dwFlags & ADS_READONLY_SERVER) ) {
  448. dwOptions |= DS_WRITABLE_REQUIRED;
  449. }
  450. ldaperr = ldap_set_option(pCacheEntry->LdapHandle, LDAP_OPT_GETDSNAME_FLAGS,(void *)&dwOptions);
  451. if (ldaperr != LDAP_SUCCESS) {
  452. CheckAndSetExtendedError(pCacheEntry->LdapHandle, &hr, ldaperr);
  453. goto error;
  454. }
  455. //
  456. // Now process prompt for credentials
  457. //
  458. if (dwFlags & ADS_PROMPT_CREDENTIALS) {
  459. ldapOption = (void *) LDAP_OPT_ON;
  460. }else {
  461. ldapOption = (void *) LDAP_OPT_OFF;
  462. }
  463. ldaperr = ldap_set_option(pCacheEntry->LdapHandle, LDAP_OPT_PROMPT_CREDENTIALS, &(ldapOption));
  464. if (ldaperr != LDAP_SUCCESS) {
  465. CheckAndSetExtendedError(pCacheEntry->LdapHandle, &hr, ldaperr);
  466. goto error;
  467. }
  468. //
  469. // Now init SSL if encryption is required. This is essentially if this option is on and the
  470. // user did not specify an SSL port.
  471. //
  472. if (dwFlags & ADS_USE_ENCRYPTION) {
  473. ldapOption = (void *) LDAP_OPT_ON;
  474. ldaperr = ldap_set_option(pCacheEntry->LdapHandle, LDAP_OPT_SSL, &(ldapOption));
  475. if (ldaperr != LDAP_SUCCESS) {
  476. CheckAndSetExtendedError(pCacheEntry->LdapHandle, &hr, ldaperr);
  477. goto error;
  478. }
  479. }
  480. //
  481. // Process the other options that can be set in the flags.
  482. //
  483. //
  484. if (dwFlags & ADS_USE_SIGNING) {
  485. //
  486. // User has requested that packets be signed
  487. //
  488. ldapOption = (void *) LDAP_OPT_ON;
  489. ldaperr = ldap_set_option(
  490. pCacheEntry->LdapHandle,
  491. LDAP_OPT_SIGN,
  492. &(ldapOption)
  493. );
  494. if (ldaperr != LDAP_SUCCESS) {
  495. CheckAndSetExtendedError(pCacheEntry->LdapHandle, &hr, ldaperr);
  496. goto error;
  497. }
  498. }
  499. if (dwFlags & ADS_USE_SEALING) {
  500. //
  501. // User has requested that packet are sealed
  502. //
  503. ldapOption = (void *) LDAP_OPT_ON;
  504. ldaperr = ldap_set_option(
  505. pCacheEntry->LdapHandle,
  506. LDAP_OPT_ENCRYPT,
  507. &(ldapOption)
  508. );
  509. if (ldaperr != LDAP_SUCCESS) {
  510. CheckAndSetExtendedError(pCacheEntry->LdapHandle, &hr, ldaperr);
  511. goto error;
  512. }
  513. }
  514. //
  515. // Now process versioning
  516. //
  517. ldapOption = (void *) LDAP_VERSION3;
  518. ldaperr = ldap_set_option(
  519. pCacheEntry->LdapHandle,
  520. LDAP_OPT_VERSION,
  521. &(ldapOption)
  522. );
  523. //
  524. // Non critical if the above fails
  525. //
  526. if (hostName) {
  527. ldapOption = (void *) hostName;
  528. ldaperr = ldap_set_optionW(
  529. pCacheEntry->LdapHandle,
  530. LDAP_OPT_HOST_NAME,
  531. &(ldapOption)
  532. );
  533. // Does not matter even if this setoption fails.
  534. }
  535. //
  536. // Process delegation if set
  537. //
  538. if (dwFlags & ADS_USE_DELEGATION) {
  539. #ifndef Win95
  540. //
  541. // Relying on LDAP/server to enforce the requirement for
  542. // secure auth for this to work.
  543. //
  544. DWORD dwSSPIFlags = 0;
  545. //
  546. // Get the current values.
  547. //
  548. ldapOption = (void *)&dwSSPIFlags;
  549. ldaperr = ldap_get_option(
  550. pCacheEntry->LdapHandle,
  551. LDAP_OPT_SSPI_FLAGS,
  552. ldapOption
  553. );
  554. if (ldaperr != LDAP_SUCCESS) {
  555. CheckAndSetExtendedError(pCacheEntry->LdapHandle, &hr, ldaperr);
  556. goto error;
  557. }
  558. //
  559. // Add delegation to the list.
  560. //
  561. dwSSPIFlags |= ISC_REQ_DELEGATE;
  562. ldaperr = ldap_set_option(
  563. pCacheEntry->LdapHandle,
  564. LDAP_OPT_SSPI_FLAGS,
  565. ldapOption
  566. );
  567. if (ldaperr != LDAP_SUCCESS) {
  568. CheckAndSetExtendedError(pCacheEntry->LdapHandle, &hr, ldaperr);
  569. goto error;
  570. }
  571. #else
  572. BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER);
  573. #endif
  574. }
  575. //
  576. // Set the AREC exclusive option if applicable.
  577. //
  578. if (dwFlags & ADS_SERVER_BIND) {
  579. ldapOption = (void *) LDAP_OPT_ON;
  580. ldaperr = ldap_set_option(
  581. pCacheEntry->LdapHandle,
  582. LDAP_OPT_AREC_EXCLUSIVE,
  583. &(ldapOption)
  584. );
  585. //
  586. // Should we ignore this error ?
  587. //
  588. if (ldaperr) {
  589. CheckAndSetExtendedError(pCacheEntry->LdapHandle, &hr, ldaperr);
  590. goto error;
  591. }
  592. }
  593. ldaperr = ldap_connect(pCacheEntry->LdapHandle, NULL);
  594. if (ldaperr) {
  595. CheckAndSetExtendedError( ld->LdapHandle, &hr, ldaperr );
  596. goto error;
  597. }
  598. if (pCacheEntry->LdapHandle) {
  599. //
  600. // Set the option for this connection giving our Callback functions
  601. //
  602. ldaperr = ldap_set_option(
  603. pCacheEntry->LdapHandle,
  604. LDAP_OPT_REFERRAL_CALLBACK,
  605. &g_LdapReferralCallBacks
  606. );
  607. ldapOption = (void *) LDAP_CHASE_EXTERNAL_REFERRALS;
  608. ldaperr = ldap_set_option(
  609. pCacheEntry->LdapHandle,
  610. LDAP_OPT_REFERRALS,
  611. &(ldapOption)
  612. );
  613. }
  614. return hr;
  615. error:
  616. if (pCacheEntry->LdapHandle != NULL) {
  617. LdapUnbind(pCacheEntry);
  618. }
  619. return hr;
  620. }
  621. HRESULT LdapBindS( ADS_LDP *ld, WCHAR *dn, WCHAR *passwd, BOOL fSimple )
  622. {
  623. LPWSTR pszNTLMUser = NULL;
  624. LPWSTR pszNTLMDomain = NULL;
  625. HRESULT hr = 0;
  626. int ldaperr = 0;
  627. DWORD dwLastLdapError = 0;
  628. ADsAssert(ld && ld->LdapHandle);
  629. if (fSimple) {
  630. ldaperr = ldap_simple_bind_s( ld->LdapHandle, dn, passwd ) ;
  631. }
  632. else {
  633. if (dn || passwd) {
  634. //
  635. // If we have a non-null dn and/or a non-null password, we pass in
  636. // a SEC_WINNT_AUTH_IDENTITY blob with the NTLM credentials
  637. //
  638. hr = LdapCrackUserDNtoNTLMUser2(
  639. dn,
  640. &pszNTLMUser,
  641. &pszNTLMDomain
  642. );
  643. if (FAILED(hr)) {
  644. hr = LdapCrackUserDNtoNTLMUser(
  645. dn,
  646. &pszNTLMUser,
  647. &pszNTLMDomain
  648. );
  649. BAIL_ON_FAILURE(hr);
  650. }
  651. SEC_WINNT_AUTH_IDENTITY AuthI;
  652. AuthI.User = (PWCHAR)pszNTLMUser;
  653. AuthI.UserLength = (pszNTLMUser == NULL)? 0: wcslen(pszNTLMUser);
  654. AuthI.Domain = (PWCHAR)pszNTLMDomain;
  655. AuthI.DomainLength = (pszNTLMDomain == NULL)? 0: wcslen(pszNTLMDomain);
  656. AuthI.Password = (PWCHAR)passwd;
  657. AuthI.PasswordLength = (passwd == NULL)? 0: wcslen(passwd);
  658. AuthI.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
  659. ldaperr = ldap_bind_s( ld->LdapHandle, NULL, (WCHAR*)(&AuthI), LDAP_AUTH_SSPI );
  660. }else {
  661. //
  662. // Otherwise we've come in with NULL, NULL - pass in NULL, NULL. The reason we
  663. // do this is that ldap bind code oes not process NULL, NULL, NULL in the
  664. // SEC_WINNT_AUTH_IDENTITY blob !!!
  665. //
  666. ldaperr = ldap_bind_s( ld->LdapHandle, NULL, NULL, LDAP_AUTH_SSPI );
  667. }
  668. }
  669. CheckAndSetExtendedError( ld->LdapHandle, &hr, ldaperr );
  670. //
  671. // If it is a local error for secure bind try and get
  672. // more error info and store in ADsLastError.
  673. //
  674. if (!fSimple && (ldaperr == LDAP_LOCAL_ERROR)) {
  675. dwLastLdapError = LdapGetLastError();
  676. if (dwLastLdapError) {
  677. //
  678. // Set ADSI extended error code.
  679. //
  680. ADsSetLastError(
  681. dwLastLdapError,
  682. L"",
  683. L"LDAP Provider"
  684. );
  685. }
  686. }
  687. error:
  688. if (pszNTLMUser) {
  689. FreeADsStr(pszNTLMUser);
  690. }
  691. if (pszNTLMDomain) {
  692. FreeADsStr(pszNTLMDomain);
  693. }
  694. return hr;
  695. }
  696. HRESULT LdapUnbind( ADS_LDP *ld )
  697. {
  698. HRESULT hr = NO_ERROR;
  699. ADsAssert(ld);
  700. if (ld->LdapHandle) {
  701. int ldaperr = ldap_unbind( ld->LdapHandle );
  702. // Need to set the handle to null as we may call
  703. // unbind twice otherwise
  704. ld->LdapHandle = NULL;
  705. // There is nothing much we can do about err status
  706. // CheckAndSetExtendedError could cause further problems
  707. // if the handle is not valid so we return E_FAIL
  708. // if the unbind failed.
  709. if (ldaperr ) {
  710. hr = E_FAIL;
  711. }
  712. }
  713. return hr;
  714. }
  715. HRESULT LdapSearchHelper(
  716. LDAP *ld,
  717. WCHAR *base,
  718. int scope,
  719. WCHAR *filter,
  720. WCHAR *attrs[],
  721. int attrsonly,
  722. struct l_timeval *timeout,
  723. LDAPMessage **res
  724. )
  725. {
  726. HRESULT hr = 0;
  727. int ldaperr = 0;
  728. if ( timeout == NULL )
  729. {
  730. ldaperr = ldap_search_s( ld,
  731. base,
  732. scope,
  733. filter,
  734. attrs,
  735. attrsonly,
  736. res );
  737. }
  738. else
  739. {
  740. ldaperr = ldap_search_st( ld,
  741. base,
  742. scope,
  743. filter,
  744. attrs,
  745. attrsonly,
  746. timeout,
  747. res );
  748. }
  749. if (ldaperr) {
  750. if (!ldap_count_entries( ld, *res )) {
  751. CheckAndSetExtendedError( ld, &hr, ldaperr, *res );
  752. }
  753. }else {
  754. hr = S_OK;
  755. }
  756. return hr;
  757. }
  758. HRESULT LdapSearchS(
  759. ADS_LDP *ld,
  760. WCHAR *base,
  761. int scope,
  762. WCHAR *filter,
  763. WCHAR *attrs[],
  764. int attrsonly,
  765. LDAPMessage **res
  766. )
  767. {
  768. ADsAssert(ld && ld->LdapHandle);
  769. HRESULT hr = LdapSearchHelper(
  770. ld->LdapHandle,
  771. base,
  772. scope,
  773. filter,
  774. attrs,
  775. attrsonly,
  776. NULL,
  777. res );
  778. if ( LdapConnectionErr(hr, 0, NULL)) {
  779. BindCacheInvalidateEntry(ld) ;
  780. }
  781. return hr;
  782. }
  783. HRESULT LdapSearchST(
  784. ADS_LDP *ld,
  785. WCHAR *base,
  786. int scope,
  787. WCHAR *filter,
  788. WCHAR *attrs[],
  789. int attrsonly,
  790. struct l_timeval *timeout,
  791. LDAPMessage **res
  792. )
  793. {
  794. ADsAssert(ld && ld->LdapHandle);
  795. HRESULT hr = LdapSearchHelper(
  796. ld->LdapHandle,
  797. base,
  798. scope,
  799. filter,
  800. attrs,
  801. attrsonly,
  802. timeout,
  803. res );
  804. if ( LdapConnectionErr(hr, 0, NULL)) {
  805. BindCacheInvalidateEntry(ld) ;
  806. }
  807. return hr;
  808. }
  809. HRESULT LdapSearch(
  810. ADS_LDP *ld,
  811. WCHAR *base,
  812. int scope,
  813. WCHAR *filter,
  814. WCHAR *attrs[],
  815. int attrsonly,
  816. int *msgid
  817. )
  818. {
  819. HRESULT hr = S_OK;
  820. int ldaperr = 0;
  821. ADsAssert(ld && ld->LdapHandle);
  822. *msgid = ldap_search( ld->LdapHandle,
  823. base,
  824. scope,
  825. filter,
  826. attrs,
  827. attrsonly );
  828. if ( *msgid == -1 )
  829. {
  830. ldaperr = LdapGetLastError();
  831. CheckAndSetExtendedError( ld->LdapHandle, &hr, ldaperr);
  832. }
  833. if ( LdapConnectionErr(hr, 0, NULL)) {
  834. BindCacheInvalidateEntry(ld) ;
  835. }
  836. return hr;
  837. }
  838. HRESULT LdapModifyS(
  839. ADS_LDP *ld,
  840. WCHAR *dn,
  841. LDAPModW *mods[]
  842. )
  843. {
  844. HRESULT hr = S_OK;
  845. int ldaperr = 0;
  846. ADsAssert(ld && ld->LdapHandle);
  847. ldaperr = ldap_modify_s( ld->LdapHandle, dn, mods);
  848. CheckAndSetExtendedError( ld->LdapHandle, &hr, ldaperr );
  849. if (LdapConnectionErr(hr, 0, NULL)) {
  850. BindCacheInvalidateEntry(ld) ;
  851. }
  852. return hr;
  853. }
  854. HRESULT LdapModifyExtS(
  855. ADS_LDP *ld,
  856. WCHAR *dn,
  857. LDAPModW *mods[],
  858. PLDAPControlW * ServerControls,
  859. PLDAPControlW * ClientControls
  860. )
  861. {
  862. HRESULT hr = S_OK;
  863. int ldaperr = 0;
  864. ADsAssert(ld && ld->LdapHandle);
  865. ldaperr = ldap_modify_ext_s( ld->LdapHandle, dn, mods, ServerControls, ClientControls);
  866. CheckAndSetExtendedError( ld->LdapHandle, &hr, ldaperr );
  867. if (LdapConnectionErr(hr, 0, NULL)) {
  868. BindCacheInvalidateEntry(ld) ;
  869. }
  870. return hr;
  871. }
  872. HRESULT LdapModRdnS(
  873. ADS_LDP *ld,
  874. WCHAR *dn,
  875. WCHAR *newrdn
  876. )
  877. {
  878. HRESULT hr = S_OK;
  879. int ldaperr = 0;
  880. ADsAssert(ld && ld->LdapHandle);
  881. ldaperr = ldap_modrdn_s( ld->LdapHandle, dn, newrdn );
  882. CheckAndSetExtendedError( ld->LdapHandle, &hr, ldaperr);
  883. if (LdapConnectionErr(hr, 0, NULL)) {
  884. BindCacheInvalidateEntry(ld) ;
  885. }
  886. return hr;
  887. }
  888. //+------------------------------------------------------------------------
  889. //
  890. // Function: LdapRenameExtS
  891. //
  892. // Synopsis: Extended renam/modifyRDN which will move objects across
  893. // namespaces as opposed to modifyRDN which cannot do the same.
  894. //
  895. //
  896. // Arguments: [ld] -- ldap handle.
  897. // [dn] -- dn of object to be moved.
  898. // [newRDN] -- New RDN of the object being moved.
  899. // [newParent] -- New Parent.
  900. // [deleteOldRDN] --
  901. // [ServerControls]-- Server Control to be used.
  902. // [ClientControls]-- Client Control to be used.
  903. //-------------------------------------------------------------------------
  904. HRESULT LdapRenameExtS(
  905. ADS_LDP *ld,
  906. WCHAR *dn,
  907. WCHAR *newRDN,
  908. WCHAR *newParent,
  909. int deleteOldRDN,
  910. PLDAPControlW * ServerControls,
  911. PLDAPControlW * ClientControls
  912. )
  913. {
  914. HRESULT hr = S_OK;
  915. int ldaperr = 0;
  916. ADsAssert(ld && ld->LdapHandle);
  917. ldaperr = ldap_rename_ext_sW(
  918. ld->LdapHandle,
  919. dn,
  920. newRDN,
  921. newParent,
  922. deleteOldRDN,
  923. ServerControls,
  924. ClientControls
  925. );
  926. CheckAndSetExtendedError( ld->LdapHandle, &hr, ldaperr);
  927. if (LdapConnectionErr(hr, 0, NULL)) {
  928. BindCacheInvalidateEntry(ld) ;
  929. }
  930. return hr;
  931. }
  932. HRESULT LdapModDnS(
  933. ADS_LDP *ld,
  934. WCHAR *dn,
  935. WCHAR *newdn,
  936. int deleteoldrdn
  937. )
  938. {
  939. HRESULT hr = S_OK;
  940. int ldaperr = 0;
  941. ADsAssert(ld && ld->LdapHandle);
  942. ldaperr = ldap_modrdn2_s(
  943. ld->LdapHandle,
  944. dn,
  945. newdn,
  946. deleteoldrdn );
  947. CheckAndSetExtendedError( ld->LdapHandle, &hr, ldaperr);
  948. if (LdapConnectionErr(hr, 0, NULL)) {
  949. BindCacheInvalidateEntry(ld) ;
  950. }
  951. return hr;
  952. }
  953. HRESULT LdapAddS(
  954. ADS_LDP *ld,
  955. WCHAR *dn,
  956. LDAPModW *attrs[]
  957. )
  958. {
  959. HRESULT hr = S_OK;
  960. int ldaperr = 0;
  961. ADsAssert(ld && ld->LdapHandle);
  962. ldaperr = ldap_add_s( ld->LdapHandle, dn, attrs );
  963. CheckAndSetExtendedError( ld->LdapHandle , &hr, ldaperr);
  964. if (LdapConnectionErr(hr, 0, NULL)) {
  965. BindCacheInvalidateEntry(ld) ;
  966. }
  967. return hr;
  968. }
  969. //
  970. // Add ext wrapper function
  971. //
  972. HRESULT LdapAddExtS(
  973. ADS_LDP *ld,
  974. WCHAR *dn,
  975. LDAPModW *attrs[],
  976. PLDAPControl * ServerControls,
  977. PLDAPControl * ClientControls
  978. )
  979. {
  980. HRESULT hr = S_OK;
  981. int ldaperr = 0;
  982. ADsAssert(ld && ld->LdapHandle);
  983. ldaperr = ldap_add_ext_s(
  984. ld->LdapHandle,
  985. dn,
  986. attrs,
  987. ServerControls,
  988. ClientControls
  989. );
  990. CheckAndSetExtendedError( ld->LdapHandle , &hr, ldaperr);
  991. if (LdapConnectionErr(hr, 0, NULL)) {
  992. BindCacheInvalidateEntry(ld) ;
  993. }
  994. return hr;
  995. }
  996. HRESULT LdapDeleteS(
  997. ADS_LDP *ld,
  998. WCHAR *dn
  999. )
  1000. {
  1001. HRESULT hr = 0;
  1002. int ldaperr = 0;
  1003. ADsAssert(ld && ld->LdapHandle);
  1004. ldaperr = ldap_delete_s( ld->LdapHandle, dn );
  1005. CheckAndSetExtendedError( ld->LdapHandle, &hr, ldaperr);
  1006. if (LdapConnectionErr(hr, 0, NULL)) {
  1007. BindCacheInvalidateEntry(ld) ;
  1008. }
  1009. return hr;
  1010. }
  1011. HRESULT LdapDeleteExtS(
  1012. ADS_LDP *ld,
  1013. WCHAR *dn,
  1014. PLDAPControlW * ServerControls,
  1015. PLDAPControlW * ClientControls
  1016. )
  1017. {
  1018. HRESULT hr = 0;
  1019. int ldaperr = 0;
  1020. ADsAssert(ld && ld->LdapHandle);
  1021. ldaperr = ldap_delete_ext_s(
  1022. ld->LdapHandle,
  1023. dn,
  1024. ServerControls,
  1025. ClientControls
  1026. );
  1027. CheckAndSetExtendedError( ld->LdapHandle, &hr, ldaperr);
  1028. if (LdapConnectionErr(hr, 0, NULL)) {
  1029. BindCacheInvalidateEntry(ld) ;
  1030. }
  1031. return hr;
  1032. }
  1033. HRESULT
  1034. LdapCompareExt(
  1035. ADS_LDP *ld,
  1036. const LPWSTR pszDn,
  1037. const LPWSTR pszAttribute,
  1038. const LPWSTR pszValue,
  1039. struct berval *berData,
  1040. PLDAPControlW * ServerControls,
  1041. PLDAPControlW * ClientControls
  1042. )
  1043. {
  1044. HRESULT hr = S_OK;
  1045. int ldaperr = 0;
  1046. ADsAssert(ld && ld->LdapHandle);
  1047. ldaperr = ldap_compare_ext_s(
  1048. ld->LdapHandle,
  1049. pszDn,
  1050. pszAttribute,
  1051. pszValue,
  1052. berData,
  1053. ServerControls,
  1054. ClientControls
  1055. );
  1056. CheckAndSetExtendedError( ld->LdapHandle, &hr, ldaperr);
  1057. if (LdapConnectionErr(hr, 0, NULL)) {
  1058. BindCacheInvalidateEntry(ld) ;
  1059. }
  1060. RRETURN(hr);
  1061. }
  1062. HRESULT LdapAbandon(
  1063. ADS_LDP *ld,
  1064. int msgid
  1065. )
  1066. {
  1067. ADsAssert(ld && ld->LdapHandle);
  1068. // No error code, 0 if success, -1 otherwise
  1069. return ldap_abandon( ld->LdapHandle, msgid );
  1070. }
  1071. HRESULT LdapResult(
  1072. ADS_LDP *ld,
  1073. int msgid,
  1074. int all,
  1075. struct l_timeval *timeout,
  1076. LDAPMessage **res,
  1077. int *restype
  1078. )
  1079. {
  1080. HRESULT hr = S_OK;
  1081. int ldaperr = 0;
  1082. ADsAssert(ld && ld->LdapHandle);
  1083. *restype = ldap_result( ld->LdapHandle, msgid, all, timeout, res );
  1084. if ( *restype == -1 ) // error
  1085. ldaperr = LdapGetLastError();
  1086. if (ldaperr) {
  1087. if (!ldap_count_entries( ld->LdapHandle, *res )) {
  1088. CheckAndSetExtendedError( ld->LdapHandle, &hr, ldaperr, *res );
  1089. if ( LdapConnectionErr(hr, 0, NULL)) {
  1090. BindCacheInvalidateEntry(ld) ;
  1091. }
  1092. }
  1093. }else {
  1094. hr = S_OK;
  1095. }
  1096. return hr;
  1097. }
  1098. void LdapMsgFree(
  1099. LDAPMessage *res
  1100. )
  1101. {
  1102. ldap_msgfree( res ); // Returns the type of message freed which
  1103. // is not interesting
  1104. }
  1105. int LdapResult2Error(
  1106. ADS_LDP *ld,
  1107. LDAPMessage *res,
  1108. int freeit
  1109. )
  1110. {
  1111. ADsAssert(ld && ld->LdapHandle);
  1112. return ldap_result2error( ld->LdapHandle, res, freeit );
  1113. }
  1114. HRESULT LdapFirstEntry(
  1115. ADS_LDP *ld,
  1116. LDAPMessage *res,
  1117. LDAPMessage **pfirst
  1118. )
  1119. {
  1120. HRESULT hr = S_OK;
  1121. int ldaperr = 0;
  1122. ADsAssert(ld && ld->LdapHandle);
  1123. *pfirst = ldap_first_entry( ld->LdapHandle, res );
  1124. if ( *pfirst == NULL )
  1125. {
  1126. ldaperr = LdapGetLastError();
  1127. CheckAndSetExtendedError( ld->LdapHandle, &hr, ldaperr, res);
  1128. }
  1129. return hr;
  1130. }
  1131. HRESULT LdapNextEntry(
  1132. ADS_LDP *ld,
  1133. LDAPMessage *entry,
  1134. LDAPMessage **pnext
  1135. )
  1136. {
  1137. HRESULT hr = S_OK;
  1138. int ldaperr = 0;
  1139. ADsAssert(ld && ld->LdapHandle);
  1140. *pnext = ldap_next_entry( ld->LdapHandle, entry );
  1141. if ( *pnext == NULL )
  1142. {
  1143. ldaperr = LdapGetLastError();
  1144. CheckAndSetExtendedError( ld->LdapHandle, &hr, ldaperr, entry);
  1145. }
  1146. return hr;
  1147. }
  1148. int LdapCountEntries(
  1149. ADS_LDP *ld,
  1150. LDAPMessage *res
  1151. )
  1152. {
  1153. ADsAssert(ld && ld->LdapHandle);
  1154. return ldap_count_entries( ld->LdapHandle, res );
  1155. }
  1156. HRESULT LdapFirstAttribute(
  1157. ADS_LDP *ld,
  1158. LDAPMessage *entry,
  1159. void **ptr,
  1160. WCHAR **pattr
  1161. )
  1162. {
  1163. ADsAssert(ld && ld->LdapHandle);
  1164. LPWSTR pAttrTemp = NULL;
  1165. // NOTE: The return value from ldap_first_attribute is static and
  1166. // should not be freed
  1167. pAttrTemp = ldap_first_attribute( ld->LdapHandle, entry,
  1168. (struct berelement **) ptr ); // static data
  1169. if ( pAttrTemp == NULL )
  1170. {
  1171. HRESULT hr = S_OK;
  1172. int ldaperr = 0;
  1173. // Error occurred or end of attributes
  1174. ldaperr = LdapGetLastError();
  1175. CheckAndSetExtendedError( ld->LdapHandle, &hr, ldaperr, entry);
  1176. return hr;
  1177. }
  1178. //
  1179. // Copy over the value as we can loose state if this fn is
  1180. // called again - for example we read the attribute and are
  1181. // now looking for schema information about it and end up
  1182. // fetching the schema from the server.
  1183. //
  1184. *pattr = AllocADsStr(pAttrTemp);
  1185. return NO_ERROR;
  1186. }
  1187. HRESULT LdapNextAttribute(
  1188. ADS_LDP *ld,
  1189. LDAPMessage *entry,
  1190. void *ptr,
  1191. WCHAR **pattr
  1192. )
  1193. {
  1194. ADsAssert(ld && ld->LdapHandle);
  1195. LPWSTR pAttrTemp = NULL;
  1196. // NOTE: The return value from ldap_next_attribute is static and
  1197. // should not be freed
  1198. pAttrTemp = ldap_next_attribute( ld->LdapHandle, entry,
  1199. (struct berelement *) ptr ); // static data
  1200. if (pAttrTemp) {
  1201. *pattr = AllocADsStr(pAttrTemp);
  1202. } else {
  1203. *pattr = NULL;
  1204. }
  1205. #if 0 // Ignore the error code here since at the end of the enumeration,
  1206. // we will probably get an error code here ( both Andy and umich's
  1207. // dll will return errors sometimes. No error returned from NTDS,
  1208. // but errors are returned from Exchange server )
  1209. if ( *pattr == NULL )
  1210. {
  1211. HRESULT hr = NO_ERROR;
  1212. int ldaperr = 0;
  1213. // Error occurred or end of attributes
  1214. ldaperr = LdapGetLastError();
  1215. CheckAndSetExtendedError( ld->LdapHandle, &hr, ldaperr);
  1216. return hr;
  1217. }
  1218. #endif
  1219. return S_OK;
  1220. }
  1221. //
  1222. // NOTE: LdapGetValues return S_OK if attribute [attr] has no values
  1223. // (*[pvalues] =NULL, *[pcount]=0) but all else ok.
  1224. //
  1225. HRESULT LdapGetValues(
  1226. ADS_LDP *ld,
  1227. LDAPMessage *entry,
  1228. WCHAR *attr,
  1229. WCHAR ***pvalues,
  1230. int *pcount
  1231. )
  1232. {
  1233. HRESULT hr = S_OK;
  1234. int ldaperr = 0;
  1235. ADsAssert(ld && ld->LdapHandle);
  1236. *pvalues = ldap_get_values( ld->LdapHandle, entry, attr );
  1237. if ( *pvalues == NULL ) {
  1238. *pcount=0;
  1239. //
  1240. // ldap_get_values succeeds if attribute has no values
  1241. // but all else ok. (confiremed with anoopa)
  1242. //
  1243. ldaperr = LdapGetLastError();
  1244. if (ldaperr) {
  1245. CheckAndSetExtendedError( ld->LdapHandle, &hr, ldaperr, entry);
  1246. }
  1247. return hr;
  1248. }
  1249. *pcount = ldap_count_values( *pvalues );
  1250. return S_OK;
  1251. }
  1252. //
  1253. // NOTE: LdapGetValuesLen return S_OK if attribute [attr] has no values
  1254. // (*[pvalues] =NULL, *[pcount]=0) but all else ok.
  1255. //
  1256. HRESULT LdapGetValuesLen(
  1257. ADS_LDP *ld,
  1258. LDAPMessage *entry,
  1259. WCHAR *attr,
  1260. struct berval ***pvalues,
  1261. int *pcount
  1262. )
  1263. {
  1264. //
  1265. // NOTE: this can contain binary data as well as strings,
  1266. // strings are ascii, no conversion is done here
  1267. //
  1268. HRESULT hr = S_OK;
  1269. int ldaperr = 0;
  1270. ADsAssert(ld && ld->LdapHandle);
  1271. *pvalues = ldap_get_values_len( ld->LdapHandle, entry, attr );
  1272. if ( *pvalues == NULL ){
  1273. *pcount=0;
  1274. //
  1275. // ldap_get_values succeeds if attribute has no values
  1276. // but all else ok. (confiremed with anoopa)
  1277. //
  1278. ldaperr = LdapGetLastError();
  1279. if (ldaperr) {
  1280. CheckAndSetExtendedError( ld->LdapHandle, &hr, ldaperr, entry);
  1281. }
  1282. return hr;
  1283. }
  1284. *pcount = ldap_count_values_len( *pvalues );
  1285. return S_OK;
  1286. }
  1287. void LdapValueFree(
  1288. WCHAR **vals
  1289. )
  1290. {
  1291. ldap_value_free( vals );
  1292. }
  1293. void LdapValueFreeLen(
  1294. struct berval **vals
  1295. )
  1296. {
  1297. ldap_value_free_len( vals );
  1298. }
  1299. void LdapMemFree(
  1300. WCHAR *pszString
  1301. )
  1302. {
  1303. ldap_memfree( pszString );
  1304. }
  1305. void LdapAttributeFree(
  1306. WCHAR *pszString
  1307. )
  1308. {
  1309. //
  1310. // Since we made a copy of the string returned by LDAP, we
  1311. // need to free it here.
  1312. //
  1313. FreeADsStr(pszString);
  1314. }
  1315. HRESULT LdapGetDn(
  1316. ADS_LDP *ld,
  1317. LDAPMessage *entry,
  1318. WCHAR **pdn
  1319. )
  1320. {
  1321. int ldaperr = 0;
  1322. HRESULT hr = S_OK;
  1323. ADsAssert(ld && ld->LdapHandle);
  1324. *pdn = ldap_get_dn( ld->LdapHandle, entry );
  1325. if ( *pdn == NULL )
  1326. {
  1327. // Error occurred
  1328. ldaperr = LdapGetLastError();
  1329. CheckAndSetExtendedError( ld->LdapHandle, &hr, ldaperr, entry);
  1330. return hr;
  1331. }
  1332. return hr;
  1333. }
  1334. int ConvertToAscii( WCHAR *pszUnicode, char **pszAscii )
  1335. {
  1336. int nSize;
  1337. if ( pszUnicode == NULL )
  1338. {
  1339. *pszAscii = NULL;
  1340. return NO_ERROR;
  1341. }
  1342. nSize = WideCharToMultiByte( CP_ACP,
  1343. 0,
  1344. pszUnicode,
  1345. -1,
  1346. NULL,
  1347. 0,
  1348. NULL,
  1349. NULL );
  1350. if ( nSize == 0 )
  1351. return GetLastError();
  1352. *pszAscii = (char * ) AllocADsMem( nSize );
  1353. if ( *pszAscii == NULL )
  1354. return ERROR_NOT_ENOUGH_MEMORY;
  1355. if ( !WideCharToMultiByte( CP_ACP,
  1356. 0,
  1357. pszUnicode,
  1358. -1,
  1359. *pszAscii,
  1360. nSize,
  1361. NULL,
  1362. NULL ))
  1363. {
  1364. FreeADsMem( *pszAscii );
  1365. *pszAscii = NULL;
  1366. return GetLastError();
  1367. }
  1368. return NO_ERROR;
  1369. }
  1370. int ConvertToUnicode( char *pszAscii, WCHAR **pszUnicode )
  1371. {
  1372. int nSize;
  1373. *pszUnicode = NULL;
  1374. if ( pszAscii == NULL )
  1375. {
  1376. return NO_ERROR;
  1377. }
  1378. nSize = MultiByteToWideChar( CP_ACP,
  1379. 0,
  1380. pszAscii,
  1381. -1,
  1382. NULL,
  1383. 0 );
  1384. if ( nSize == 0 )
  1385. return GetLastError();
  1386. *pszUnicode = (WCHAR * ) AllocADsMem( nSize * sizeof(WCHAR));
  1387. if ( *pszUnicode == NULL )
  1388. return ERROR_NOT_ENOUGH_MEMORY;
  1389. if ( !MultiByteToWideChar( CP_ACP,
  1390. 0,
  1391. pszAscii,
  1392. -1,
  1393. *pszUnicode,
  1394. nSize ))
  1395. {
  1396. FreeADsMem( *pszUnicode );
  1397. *pszUnicode = NULL;
  1398. return GetLastError();
  1399. }
  1400. return NO_ERROR;
  1401. }
  1402. // Dead function?
  1403. int ConvertLDAPMod( LDAPModW **mods, LDAPModA ***modsA )
  1404. {
  1405. int nCount = 0;
  1406. LDAPModA *aMods = NULL;
  1407. int err = NO_ERROR;
  1408. if ( mods == NULL )
  1409. {
  1410. *modsA = NULL;
  1411. return NO_ERROR;
  1412. }
  1413. while ( mods[nCount] )
  1414. nCount++;
  1415. *modsA = (LDAPModA **) AllocADsMem((nCount+1) * sizeof(LDAPModA *));
  1416. if ( *modsA == NULL )
  1417. return ERROR_NOT_ENOUGH_MEMORY;
  1418. aMods = (LDAPModA *) AllocADsMem(nCount * sizeof(LDAPModA));
  1419. if ( aMods == NULL )
  1420. {
  1421. FreeADsMem( *modsA );
  1422. *modsA = NULL;
  1423. return ERROR_NOT_ENOUGH_MEMORY;
  1424. }
  1425. for ( int i = 0; i < nCount; i++ )
  1426. {
  1427. aMods[i].mod_op = mods[i]->mod_op;
  1428. if ( err = ConvertToAscii( mods[i]->mod_type, &(aMods[i].mod_type)))
  1429. break;
  1430. if ( aMods[i].mod_op & LDAP_MOD_BVALUES )
  1431. {
  1432. aMods[i].mod_bvalues = mods[i]->mod_bvalues;
  1433. }
  1434. else
  1435. {
  1436. int nStrCount = 0;
  1437. WCHAR **aStrings = mods[i]->mod_values;
  1438. while ( aStrings[nStrCount] )
  1439. nStrCount++;
  1440. aMods[i].mod_values = (char **) AllocADsMem(
  1441. (nStrCount+1) * sizeof(char *));
  1442. if ( aMods[i].mod_values != NULL )
  1443. {
  1444. for ( int j = 0; j < nStrCount; j++ )
  1445. {
  1446. err = ConvertToAscii( mods[i]->mod_values[j],
  1447. &(aMods[i].mod_values[j]));
  1448. if ( err )
  1449. {
  1450. for ( int k = 0; k < j; k++ )
  1451. FreeADsMem( aMods[i].mod_values[k] );
  1452. FreeADsMem( aMods[i].mod_values );
  1453. break;
  1454. }
  1455. }
  1456. }
  1457. else
  1458. {
  1459. err = ERROR_NOT_ENOUGH_MEMORY;
  1460. }
  1461. if ( err )
  1462. break;
  1463. }
  1464. (*modsA)[i] = &aMods[i];
  1465. }
  1466. if ( err )
  1467. {
  1468. for ( int k = 0; k < i; k++ )
  1469. {
  1470. FreeADsMem( aMods[k].mod_type );
  1471. if ( !(aMods[k].mod_op & LDAP_MOD_BVALUES ))
  1472. {
  1473. int j = 0;
  1474. while ( aMods[k].mod_values[j] )
  1475. FreeADsMem( aMods[k].mod_values[j++] );
  1476. if ( aMods[k].mod_values )
  1477. FreeADsMem( aMods[k].mod_values );
  1478. }
  1479. }
  1480. FreeADsMem( aMods );
  1481. FreeADsMem( *modsA );
  1482. *modsA = NULL;
  1483. }
  1484. return err;
  1485. }
  1486. // Dead function?
  1487. void FreeLDAPMod( LDAPModA **modsA )
  1488. {
  1489. int i = 0;
  1490. while ( modsA[i] )
  1491. {
  1492. FreeADsMem( modsA[i]->mod_type );
  1493. if ( !(modsA[i]->mod_op & LDAP_MOD_BVALUES ))
  1494. {
  1495. int j = 0;
  1496. while ( modsA[i]->mod_values[j] )
  1497. FreeADsMem( modsA[i]->mod_values[j++] );
  1498. if ( modsA[i]->mod_values )
  1499. FreeADsMem( modsA[i]->mod_values );
  1500. }
  1501. i++;
  1502. }
  1503. if ( modsA[0] )
  1504. FreeADsMem( modsA[0] );
  1505. FreeADsMem( modsA );
  1506. }
  1507. void
  1508. LdapGetCredentialsFromRegistry(
  1509. CCredentials& Credentials
  1510. )
  1511. {
  1512. HKEY hKey ;
  1513. WCHAR UserName[128], Password[128] ;
  1514. LPWSTR pUserName = NULL;
  1515. LPWSTR pPassword = NULL;
  1516. DWORD dwType, cbUserName = sizeof(UserName),
  1517. cbPassword = sizeof(Password);
  1518. int err = NO_ERROR;
  1519. UserName[0] = Password[0] = 0 ;
  1520. //
  1521. // Open the registry Key
  1522. //
  1523. err = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  1524. L"System\\CurrentControlSet\\Services\\TcpIp\\Parameters",
  1525. 0L,
  1526. KEY_READ,
  1527. &hKey) ;
  1528. if (err == NO_ERROR) {
  1529. err = RegQueryValueEx (hKey,
  1530. L"LdapUserName",
  1531. NULL,
  1532. &dwType,
  1533. (LPBYTE) UserName,
  1534. &cbUserName) ;
  1535. if (err == NO_ERROR) {
  1536. pUserName = UserName;
  1537. }
  1538. err = RegQueryValueEx (hKey,
  1539. L"LdapPassword",
  1540. NULL,
  1541. &dwType,
  1542. (LPBYTE) Password,
  1543. &cbPassword) ;
  1544. if (err == NO_ERROR) {
  1545. pPassword = Password;
  1546. }
  1547. Credentials.SetUserName(pUserName);
  1548. Credentials.SetPassword(pPassword);
  1549. RegCloseKey(hKey) ;
  1550. }
  1551. }
  1552. HRESULT
  1553. LdapOpenBindWithCredentials(
  1554. WCHAR *szDomainName,
  1555. WCHAR *szServerName,
  1556. CCredentials& Credentials,
  1557. PADS_LDP pCacheEntry,
  1558. DWORD dwPort
  1559. )
  1560. {
  1561. HRESULT hr = S_OK;
  1562. LPWSTR UserName = NULL;
  1563. LPWSTR Password = NULL;
  1564. DWORD dwFlagsChecked = 0;
  1565. DWORD dwAuthFlags = 0;
  1566. ULONG ulSSLPort, ulPort;
  1567. hr = Credentials.GetUserName(&UserName);
  1568. BAIL_ON_FAILURE(hr);
  1569. hr = Credentials.GetPassword(&Password);
  1570. BAIL_ON_FAILURE(hr);
  1571. //
  1572. // dwAuthFlags are the acutal flags set by the user
  1573. //
  1574. dwAuthFlags = Credentials.GetAuthFlags();
  1575. //
  1576. // dwFlagsChecked are the flags that we handle in this fn.
  1577. //
  1578. dwFlagsChecked = MaskKnownFlagsNotChecked(dwAuthFlags);
  1579. if (dwPort == USE_DEFAULT_LDAP_PORT) {
  1580. //
  1581. // We can choose the appropriate LDAP port no.
  1582. //
  1583. ulSSLPort = LDAP_SSL_PORT;
  1584. ulPort = LDAP_PORT;
  1585. }
  1586. else if ( dwPort == USE_DEFAULT_GC_PORT ) {
  1587. //
  1588. // We can choose the appropriate GC port no.
  1589. //
  1590. ulSSLPort = GC_SSL_PORT;
  1591. ulPort = GC_PORT;
  1592. }
  1593. else {
  1594. //
  1595. // Port number explicitly specified; go with that
  1596. //
  1597. ulSSLPort = dwPort;
  1598. ulPort = dwPort;
  1599. }
  1600. switch (dwFlagsChecked) {
  1601. case (ADS_USE_ENCRYPTION | ADS_SECURE_AUTHENTICATION):
  1602. //
  1603. // Case 1 - ADS_USE_ENCRYPTION AND ADS_SECURE_AUTHENTICATION
  1604. // We do a simple bind over SSL. We get secure authentication
  1605. // for free over SSL. If opening the SSL port fails, we will
  1606. // error out
  1607. //
  1608. hr = LdapOpen( szDomainName, szServerName, ulSSLPort, pCacheEntry, dwAuthFlags );
  1609. if (FAILED(hr)) {
  1610. goto error;
  1611. }
  1612. hr = LdapBindS( pCacheEntry, UserName, Password, TRUE );
  1613. if (FAILED(hr) && LDAPCodeWarrantsRetry(hr)) {
  1614. //
  1615. // Try setting the version number to V2.
  1616. void *ldapOption = (void *) LDAP_VERSION2;
  1617. ldap_set_option(
  1618. pCacheEntry->LdapHandle,
  1619. LDAP_OPT_VERSION,
  1620. &(ldapOption)
  1621. );
  1622. hr = LdapBindS( pCacheEntry, UserName, Password, TRUE );
  1623. BAIL_ON_FAILURE(hr);
  1624. }
  1625. break;
  1626. case (ADS_SECURE_AUTHENTICATION):
  1627. //
  1628. // Case 2 - ADS_SECURE_AUTHENTICATION
  1629. // we will try opening the LDAP port and authenticate with
  1630. // SSPI.
  1631. //
  1632. hr = LdapOpen( szDomainName, szServerName, ulPort, pCacheEntry, dwAuthFlags);
  1633. if (FAILED(hr)) {
  1634. goto error;
  1635. }
  1636. hr = LdapBindS( pCacheEntry, UserName, Password, FALSE );
  1637. BAIL_ON_FAILURE(hr);
  1638. break;
  1639. case (ADS_USE_ENCRYPTION):
  1640. //
  1641. // Case 3 - ADS_USE_ENCRYPTION
  1642. // We will first try open the SSL port. If this succeeds, we
  1643. // will try a simple bind. If the open to the SSL port fails,
  1644. // we will error out - (we can't provide encryption)
  1645. //
  1646. hr = LdapOpen( szDomainName, szServerName, ulSSLPort, pCacheEntry, dwAuthFlags );
  1647. if (FAILED(hr)) {
  1648. goto error;
  1649. }
  1650. hr = LdapBindS( pCacheEntry, UserName, Password, TRUE );
  1651. if (FAILED(hr) && LDAPCodeWarrantsRetry(hr)) {
  1652. //
  1653. // Try setting the version number to V2.
  1654. void *ldapOption = (void *) LDAP_VERSION2;
  1655. ldap_set_option(
  1656. pCacheEntry->LdapHandle,
  1657. LDAP_OPT_VERSION,
  1658. &(ldapOption)
  1659. );
  1660. hr = LdapBindS( pCacheEntry, UserName, Password, TRUE );
  1661. BAIL_ON_FAILURE(hr);
  1662. }
  1663. break;
  1664. case 0:
  1665. //
  1666. // Case 4 - NOT ADS_SECURE_AUTHENTICATION AND NOT ADS_USE_ENCRYPTION
  1667. // We will first try opening the LDAP port. Then we will do
  1668. // a simple bind and "clear-text" authenticate.
  1669. //
  1670. hr = LdapOpen( szDomainName, szServerName, ulPort, pCacheEntry, dwAuthFlags );
  1671. if (FAILED(hr)) {
  1672. goto error;
  1673. }
  1674. //
  1675. // Note there is no need to try an SSPI bind, as the user came with
  1676. // explicit credentials and requested no authentication / no encryption
  1677. // We just need to do a simple bind.
  1678. // err = LdapBindS( pCacheEntry, UserName, Password, FALSE );
  1679. hr = HRESULT_FROM_WIN32(ERROR_OPEN_FAILED);
  1680. if (FAILED(hr)) {
  1681. //
  1682. // SSPI bind failed - try a simple bind.
  1683. //
  1684. hr = LdapBindS( pCacheEntry, UserName, Password, TRUE );
  1685. if (FAILED(hr) && LDAPCodeWarrantsRetry(hr)) {
  1686. //
  1687. // Try setting the version number to V2.
  1688. void *ldapOption = (void *) LDAP_VERSION2;
  1689. ldap_set_option(
  1690. pCacheEntry->LdapHandle,
  1691. LDAP_OPT_VERSION,
  1692. &(ldapOption)
  1693. );
  1694. hr = LdapBindS( pCacheEntry, UserName, Password, TRUE );
  1695. if (FAILED(hr)) {
  1696. goto error;
  1697. }
  1698. }
  1699. }
  1700. break;
  1701. case ADS_NO_AUTHENTICATION:
  1702. //
  1703. // Case 10 - ADS_NO_AUTHENTICATION
  1704. //
  1705. hr = LdapOpen( szDomainName, szServerName, ulPort, pCacheEntry, dwAuthFlags);
  1706. if (FAILED(hr)) {
  1707. goto error;
  1708. }
  1709. break;
  1710. default:
  1711. //
  1712. // Case 5 - Bogus values - if we come in with any bogus flags, we
  1713. // will fail with ERROR_INVALID_PARAMETER.
  1714. //
  1715. hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  1716. break;
  1717. }
  1718. error:
  1719. if (UserName) {
  1720. FreeADsStr(UserName);
  1721. }
  1722. if (Password) {
  1723. FreeADsStr(Password);
  1724. }
  1725. return(hr);
  1726. }
  1727. HRESULT
  1728. LdapOpenBindWithDefaultCredentials(
  1729. WCHAR *szDomainName,
  1730. WCHAR *szServerName,
  1731. CCredentials& Credentials,
  1732. PADS_LDP pCacheEntry,
  1733. DWORD dwPort
  1734. )
  1735. {
  1736. HRESULT hr = S_OK;
  1737. LPWSTR UserName = NULL;
  1738. LPWSTR Password = NULL;
  1739. DWORD dwFlagsChecked = 0;
  1740. DWORD dwAuthFlags = 0;
  1741. ULONG ulSSLPort, ulPort;
  1742. hr = Credentials.GetUserName(&UserName);
  1743. BAIL_ON_FAILURE(hr);
  1744. hr = Credentials.GetPassword(&Password);
  1745. BAIL_ON_FAILURE(hr);
  1746. //
  1747. // These are the flags actually passed in.
  1748. //
  1749. dwAuthFlags = Credentials.GetAuthFlags();
  1750. //
  1751. // dwFlagsChecked contains only those flags we check for here.
  1752. //
  1753. dwFlagsChecked = MaskKnownFlagsNotChecked(dwAuthFlags);
  1754. if (dwPort == USE_DEFAULT_LDAP_PORT) {
  1755. //
  1756. // We can choose the LDAP port number
  1757. //
  1758. ulSSLPort = LDAP_SSL_PORT;
  1759. ulPort = LDAP_PORT;
  1760. }
  1761. else if ( dwPort == USE_DEFAULT_GC_PORT ) {
  1762. //
  1763. // We can choose the appropriate GC port number
  1764. //
  1765. ulSSLPort = GC_SSL_PORT;
  1766. ulPort = GC_PORT;
  1767. }
  1768. else {
  1769. //
  1770. // Port number explicitly specified; go with that
  1771. //
  1772. ulSSLPort = dwPort;
  1773. ulPort = dwPort;
  1774. }
  1775. switch (dwFlagsChecked) {
  1776. case (ADS_USE_ENCRYPTION | ADS_SECURE_AUTHENTICATION):
  1777. //
  1778. // Case 1 - ADS_USE_ENCRYPTION AND ADS_SECURE_AUTHENTICATION
  1779. // We do a simple bind over SSL. We get secure authentication
  1780. // for free over SSL. If opening the SSL port fails, we will
  1781. // error out
  1782. //
  1783. hr = LdapOpen( szDomainName, szServerName, ulSSLPort, pCacheEntry, dwAuthFlags );
  1784. BAIL_ON_FAILURE(hr);
  1785. hr = LdapBindS( pCacheEntry, UserName, Password, TRUE );
  1786. if (FAILED(hr)) {
  1787. //
  1788. // Try setting the version number to V2.
  1789. void *ldapOption = (void *) LDAP_VERSION2;
  1790. ldap_set_option(
  1791. pCacheEntry->LdapHandle,
  1792. LDAP_OPT_VERSION,
  1793. &(ldapOption)
  1794. );
  1795. hr = LdapBindS( pCacheEntry, UserName, Password, TRUE );
  1796. BAIL_ON_FAILURE(hr);
  1797. }
  1798. break;
  1799. case (ADS_SECURE_AUTHENTICATION):
  1800. //
  1801. // Case 2 - ADS_SECURE_AUTHENTICATION
  1802. // we will try opening the LDAP port and authenticate with
  1803. // SSPI.
  1804. //
  1805. hr = LdapOpen( szDomainName, szServerName, ulPort, pCacheEntry, dwAuthFlags);
  1806. if (FAILED(hr)) {
  1807. goto error;
  1808. }
  1809. hr = LdapBindS( pCacheEntry, UserName, Password, FALSE );
  1810. BAIL_ON_FAILURE(hr);
  1811. break;
  1812. case (ADS_USE_ENCRYPTION):
  1813. //
  1814. // Case 3 - ADS_USE_ENCRYPTION
  1815. // We will first try open the SSL port. If this succeeds, we
  1816. // will try a simple bind. If the open to the SSL port fails,
  1817. // we will error out - (we can't provide encryption)
  1818. //
  1819. hr = LdapOpen( szDomainName, szServerName, ulSSLPort, pCacheEntry, dwAuthFlags );
  1820. if (FAILED(hr)) {
  1821. goto error;
  1822. }
  1823. hr = LdapBindS( pCacheEntry, UserName, Password, TRUE );
  1824. if (FAILED(hr)) {
  1825. //
  1826. // Try setting the version number to V2.
  1827. void *ldapOption = (void *) LDAP_VERSION2;
  1828. ldap_set_option(
  1829. pCacheEntry->LdapHandle,
  1830. LDAP_OPT_VERSION,
  1831. &(ldapOption)
  1832. );
  1833. hr = LdapBindS( pCacheEntry, UserName, Password, TRUE );
  1834. BAIL_ON_FAILURE(hr);
  1835. }
  1836. break;
  1837. case 0:
  1838. //
  1839. // Case 4 - NOT ADS_SECURE_AUTHENTICATION AND NOT ADS_USE_ENCRYPTION
  1840. // We will first try opening the LDAP port. If this succeeds, we
  1841. // will try an SSPI bind. We still want to try and provide the user
  1842. // with a secure authentication even though he/she is crazy enough
  1843. // to unsecurely authenticate. If the SSPI bind fails, we will do
  1844. // a simple bind and "clear-text" authenticate.
  1845. //
  1846. hr = LdapOpen( szDomainName, szServerName, ulPort, pCacheEntry, dwAuthFlags );
  1847. if (FAILED(hr)) {
  1848. goto error;
  1849. }
  1850. hr = LdapBindS( pCacheEntry, UserName, Password, FALSE );
  1851. if (FAILED(hr) && hr != ERROR_LOGON_FAILURE) {
  1852. hr = LdapBindS( pCacheEntry, UserName, Password, TRUE );
  1853. if (FAILED(hr)) {
  1854. //
  1855. // Try setting the version number to V2.
  1856. //
  1857. void *ldapOption = (void *) LDAP_VERSION2;
  1858. ldap_set_option(
  1859. pCacheEntry->LdapHandle,
  1860. LDAP_OPT_VERSION,
  1861. &(ldapOption)
  1862. );
  1863. hr = LdapBindS( pCacheEntry, UserName, Password, TRUE );
  1864. if (FAILED(hr)) {
  1865. goto error;
  1866. }
  1867. }
  1868. }
  1869. break;
  1870. default:
  1871. //
  1872. // Case 5 - Bogus values - if we come in with any bogus flags, we
  1873. // will fail with ERROR_INVALID_PARAMETER.
  1874. //
  1875. hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  1876. break;
  1877. }
  1878. error:
  1879. if (UserName) {
  1880. FreeADsStr(UserName);
  1881. }
  1882. if (Password) {
  1883. FreeADsStr(Password);
  1884. }
  1885. return(hr);
  1886. }
  1887. //+---------------------------------------------------------------------------
  1888. // Function: LdapCrackUserDNToNTLMUser
  1889. //
  1890. // Synopsis: This call attempts to translate an LDAP-style DN into an NTLM
  1891. // domain password form. The algorithm is to assume that the first
  1892. // component will be of the form "CN=krishnaG" . This first component
  1893. // will be taken as the user name. The subsequent components are
  1894. // scanned till we find the first DC= component.
  1895. //
  1896. // Arguments: [LPTSTR szBuffer]
  1897. // [LPVOID *ppObject]
  1898. //
  1899. // Returns: HRESULT
  1900. //
  1901. // Modifies: -
  1902. //
  1903. // History: 11-3-95 krishnag Created.
  1904. //
  1905. //----------------------------------------------------------------------------
  1906. HRESULT
  1907. LdapCrackUserDNtoNTLMUser(
  1908. LPWSTR pszDN,
  1909. LPWSTR * ppszNTLMUser,
  1910. LPWSTR * ppszNTLMDomain
  1911. )
  1912. {
  1913. OBJECTINFO ObjectInfo;
  1914. POBJECTINFO pObjectInfo = &ObjectInfo;
  1915. WCHAR szUserName[MAX_PATH];
  1916. WCHAR szDomainName[MAX_PATH];
  1917. LPWSTR szToken = NULL;
  1918. LPWSTR pszSrcComp = NULL;
  1919. LPWSTR pszSrcValue = NULL;
  1920. DWORD i = 0;
  1921. DWORD dwNumComponents = 0;
  1922. HRESULT hr = S_OK;
  1923. CLexer Lexer(pszDN);
  1924. CLexer * pTokenizer = &Lexer;
  1925. DWORD dwToken = 0;
  1926. LPWSTR pszUserName = NULL;
  1927. LPWSTR pszDomainName = NULL;
  1928. *ppszNTLMUser = NULL;
  1929. *ppszNTLMDomain = NULL;
  1930. if (pszDN && !*pszDN) {
  1931. //
  1932. // Empty string.
  1933. //
  1934. *ppszNTLMUser = AllocADsStr(L"");
  1935. if (!*ppszNTLMUser) {
  1936. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  1937. }
  1938. *ppszNTLMDomain = AllocADsStr(L"");
  1939. if (!*ppszNTLMDomain) {
  1940. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  1941. }
  1942. RRETURN(hr);
  1943. }
  1944. hr = InitObjectInfo(pszDN, pObjectInfo);
  1945. BAIL_ON_FAILURE(hr);
  1946. szUserName[0] = szDomainName[0] = L'\0';
  1947. //
  1948. // We don't want to treat ! as a special character
  1949. //
  1950. pTokenizer->SetExclaimnationDisabler(TRUE);
  1951. while (1) {
  1952. hr = Component(pTokenizer, pObjectInfo);
  1953. BAIL_ON_FAILURE(hr);
  1954. hr = GetNextToken(pTokenizer, pObjectInfo, &szToken, &dwToken);
  1955. BAIL_ON_FAILURE(hr);
  1956. if (dwToken == TOKEN_COMMA || dwToken == TOKEN_SEMICOLON) {
  1957. continue;
  1958. }
  1959. if (dwToken == TOKEN_ATSIGN) {
  1960. //
  1961. // Need to return entire dn as username and no domain
  1962. //
  1963. *ppszNTLMUser = AllocADsStr(pszDN);
  1964. if (!*ppszNTLMUser) {
  1965. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  1966. }
  1967. *ppszNTLMDomain = AllocADsStr(L"");
  1968. if (!*ppszNTLMDomain) {
  1969. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  1970. }
  1971. goto exit;
  1972. }
  1973. if (dwToken == TOKEN_END) {
  1974. break;
  1975. }
  1976. }
  1977. dwNumComponents = pObjectInfo->NumComponents;
  1978. if (dwNumComponents) {
  1979. pszSrcComp = pObjectInfo->ComponentArray[0].szComponent;
  1980. pszSrcValue = pObjectInfo->ComponentArray[0].szValue;
  1981. if (pszSrcComp) {
  1982. // if there was a LHS as in CN=krishnag
  1983. if (!_wcsicmp(pszSrcComp, L"CN")) {
  1984. wcscpy(szUserName, pszSrcValue);
  1985. }else if (!pszSrcValue){
  1986. wcscpy(szUserName, pszSrcComp);
  1987. }
  1988. }
  1989. for (i = 1; i < dwNumComponents; i++) {
  1990. pszSrcComp = pObjectInfo->ComponentArray[i].szComponent;
  1991. pszSrcValue = pObjectInfo->ComponentArray[i].szValue;
  1992. if (pszSrcComp) {
  1993. // if there was a LHS as in DC=NTWKSTA
  1994. if (!_wcsicmp(pszSrcComp, L"DC")) {
  1995. wcscpy(szDomainName, pszSrcValue);
  1996. break;
  1997. }else if (!pszSrcValue){
  1998. wcscpy(szDomainName, pszSrcComp);
  1999. break;
  2000. }
  2001. }
  2002. }
  2003. }
  2004. if (szUserName[0]) {
  2005. pszUserName = AllocADsStr(szUserName);
  2006. if (!pszUserName) {
  2007. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  2008. }
  2009. if (szDomainName[0]) {
  2010. pszDomainName = AllocADsStr(szDomainName);
  2011. if (!pszDomainName) {
  2012. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  2013. }
  2014. }
  2015. }else {
  2016. hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  2017. BAIL_ON_FAILURE(hr);
  2018. }
  2019. *ppszNTLMUser = pszUserName;
  2020. *ppszNTLMDomain = pszDomainName;
  2021. exit:
  2022. //
  2023. // Clean up the parser object
  2024. //
  2025. FreeObjectInfo(pObjectInfo);
  2026. return(hr);
  2027. error:
  2028. //
  2029. // Clean up the parser object
  2030. //
  2031. FreeObjectInfo(pObjectInfo);
  2032. if (pszUserName) {
  2033. FreeADsStr(pszUserName);
  2034. }
  2035. if (pszDomainName) {
  2036. FreeADsStr(pszDomainName);
  2037. }
  2038. if (*ppszNTLMUser) {
  2039. FreeADsStr(*ppszNTLMUser);
  2040. }
  2041. if (*ppszNTLMDomain) {
  2042. FreeADsStr(*ppszNTLMDomain);
  2043. }
  2044. //
  2045. // Now we just return whatever is returned from the parser.
  2046. //
  2047. return(hr);
  2048. }
  2049. //
  2050. // would like to use WinNT codes path cracking codes - but doesn't
  2051. // work. Too messy, need to clean up - move all path mgmt codes to common.
  2052. //
  2053. // use my own codes for quick fix for now
  2054. //
  2055. // Crack pszDN in "domain\user" format into *ppszNTLMUser="user" and
  2056. // *ppszNTLMDomain="domain".
  2057. //
  2058. HRESULT
  2059. LdapCrackUserDNtoNTLMUser2(
  2060. IN LPWSTR pszDN,
  2061. OUT LPWSTR * ppszNTLMUser,
  2062. OUT LPWSTR * ppszNTLMDomain
  2063. )
  2064. {
  2065. HRESULT hr = E_ADS_BAD_PATHNAME;
  2066. DWORD dwTokenLen=0;
  2067. BOOL fMore = FALSE;
  2068. ASSERT(ppszNTLMUser);
  2069. ASSERT(ppszNTLMDomain);
  2070. *ppszNTLMUser=NULL;
  2071. *ppszNTLMDomain=NULL;
  2072. if (!pszDN) {
  2073. RRETURN(S_OK);
  2074. }
  2075. hr = GetOneToken(
  2076. pszDN,
  2077. ppszNTLMDomain,
  2078. &dwTokenLen,
  2079. &fMore
  2080. );
  2081. BAIL_ON_FAILURE(hr);
  2082. if (fMore && *(pszDN+dwTokenLen+1)!=L'\\') {
  2083. hr = GetOneToken(
  2084. pszDN+dwTokenLen+1,
  2085. ppszNTLMUser,
  2086. &dwTokenLen,
  2087. &fMore
  2088. );
  2089. } else {
  2090. hr = E_ADS_BAD_PATHNAME;
  2091. }
  2092. BAIL_ON_FAILURE(hr);
  2093. RRETURN (hr);
  2094. error:
  2095. if (*ppszNTLMUser) {
  2096. FreeADsStr(*ppszNTLMUser);
  2097. *ppszNTLMUser=NULL;
  2098. }
  2099. if (*ppszNTLMDomain) {
  2100. FreeADsStr(*ppszNTLMDomain);
  2101. *ppszNTLMDomain=NULL;
  2102. }
  2103. RRETURN (hr);
  2104. }
  2105. HRESULT
  2106. GetOneToken(
  2107. LPWSTR pszSource,
  2108. LPWSTR * ppszToken,
  2109. DWORD * pdwTokenLen,
  2110. BOOL * pfMore
  2111. )
  2112. {
  2113. LPWSTR pszToken = NULL;
  2114. DWORD dwTokenLen= 0;
  2115. LPWSTR pszCurrChar = pszSource;
  2116. ASSERT(pszSource);
  2117. ASSERT(ppszToken);
  2118. ASSERT(pdwTokenLen);
  2119. ASSERT(pfMore);
  2120. *ppszToken=NULL;
  2121. *pdwTokenLen = 0;
  2122. *pfMore = FALSE;
  2123. //
  2124. // do we use exception handling code here ? what if caller passed
  2125. // in a bad string -> not terminated?
  2126. //
  2127. while (*pszCurrChar!=L'\0' && *pszCurrChar!=L'\\') {
  2128. dwTokenLen++;
  2129. pszCurrChar++;
  2130. }
  2131. pszToken = (LPWSTR) AllocADsMem( (dwTokenLen+1) * sizeof(WCHAR) );
  2132. if (!pszToken) {
  2133. RRETURN(E_OUTOFMEMORY);
  2134. }
  2135. memcpy( pszToken, pszSource, dwTokenLen * sizeof(WCHAR) );
  2136. (pszToken)[dwTokenLen]=L'\0';
  2137. *pdwTokenLen = dwTokenLen;
  2138. *ppszToken = pszToken;
  2139. *pfMore = (*pszCurrChar==L'\0') ? FALSE : TRUE;
  2140. RRETURN(S_OK);
  2141. }
  2142. VOID
  2143. CheckAndSetExtendedError(
  2144. LDAP *ld,
  2145. HRESULT *perr,
  2146. int ldaperr,
  2147. LDAPMessage *ldapResMsg
  2148. )
  2149. {
  2150. WCHAR pszProviderName[MAX_PATH];
  2151. INT numChars;
  2152. void *option;
  2153. DWORD dwStatus = NO_ERROR;
  2154. DWORD dwErr = NO_ERROR;
  2155. DWORD dwLdapErrParse = NO_ERROR;
  2156. PWCHAR ppszLdapMessage = NULL;
  2157. LPWSTR pszStopChar = NULL;
  2158. // first set the dwErr, then we can see if we can get
  2159. // more information from ldap_parse_resultW
  2160. switch (ldaperr) {
  2161. case LDAP_SUCCESS :
  2162. dwErr = NO_ERROR;
  2163. break;
  2164. case LDAP_OPERATIONS_ERROR :
  2165. dwErr = ERROR_DS_OPERATIONS_ERROR;
  2166. break;
  2167. case LDAP_PROTOCOL_ERROR :
  2168. dwErr = ERROR_DS_PROTOCOL_ERROR;
  2169. break;
  2170. case LDAP_TIMELIMIT_EXCEEDED :
  2171. dwErr = ERROR_DS_TIMELIMIT_EXCEEDED;
  2172. break;
  2173. case LDAP_SIZELIMIT_EXCEEDED :
  2174. dwErr = ERROR_DS_SIZELIMIT_EXCEEDED;
  2175. break;
  2176. case LDAP_COMPARE_FALSE :
  2177. dwErr = ERROR_DS_COMPARE_FALSE;
  2178. break;
  2179. case LDAP_COMPARE_TRUE :
  2180. dwErr = ERROR_DS_COMPARE_TRUE;
  2181. break;
  2182. case LDAP_AUTH_METHOD_NOT_SUPPORTED :
  2183. dwErr = ERROR_DS_AUTH_METHOD_NOT_SUPPORTED;
  2184. break;
  2185. case LDAP_STRONG_AUTH_REQUIRED :
  2186. dwErr = ERROR_DS_STRONG_AUTH_REQUIRED;
  2187. break;
  2188. // LDAP_REFERRAL_V2 has same value as LDAP_PARTIAL_RESULTS
  2189. case LDAP_PARTIAL_RESULTS :
  2190. //
  2191. // If the referral chasing is off for the handle
  2192. // we really don't worry about this error
  2193. //
  2194. dwStatus = ldap_get_option(
  2195. ld,
  2196. LDAP_OPT_REFERRALS,
  2197. &(option)
  2198. );
  2199. if (dwStatus == NO_ERROR && option == LDAP_OPT_OFF) {
  2200. dwErr = NO_ERROR;
  2201. }
  2202. else {
  2203. dwErr = ERROR_MORE_DATA;
  2204. }
  2205. break ;
  2206. case LDAP_REFERRAL :
  2207. dwErr = ERROR_DS_REFERRAL;
  2208. break;
  2209. case LDAP_ADMIN_LIMIT_EXCEEDED :
  2210. dwErr = ERROR_DS_ADMIN_LIMIT_EXCEEDED;
  2211. break;
  2212. case LDAP_UNAVAILABLE_CRIT_EXTENSION :
  2213. dwErr = ERROR_DS_UNAVAILABLE_CRIT_EXTENSION;
  2214. break;
  2215. case LDAP_CONFIDENTIALITY_REQUIRED :
  2216. dwErr = ERROR_DS_CONFIDENTIALITY_REQUIRED;
  2217. break;
  2218. case LDAP_NO_SUCH_ATTRIBUTE :
  2219. dwErr = ERROR_DS_NO_ATTRIBUTE_OR_VALUE;
  2220. break;
  2221. case LDAP_UNDEFINED_TYPE :
  2222. dwErr = ERROR_DS_ATTRIBUTE_TYPE_UNDEFINED;
  2223. break;
  2224. case LDAP_INAPPROPRIATE_MATCHING :
  2225. dwErr = ERROR_DS_INAPPROPRIATE_MATCHING;
  2226. break;
  2227. case LDAP_CONSTRAINT_VIOLATION :
  2228. dwErr = ERROR_DS_CONSTRAINT_VIOLATION;
  2229. break;
  2230. case LDAP_ATTRIBUTE_OR_VALUE_EXISTS :
  2231. dwErr = ERROR_DS_ATTRIBUTE_OR_VALUE_EXISTS;
  2232. break;
  2233. case LDAP_INVALID_SYNTAX :
  2234. dwErr = ERROR_DS_INVALID_ATTRIBUTE_SYNTAX;
  2235. break;
  2236. case LDAP_NO_SUCH_OBJECT :
  2237. dwErr = ERROR_DS_NO_SUCH_OBJECT;
  2238. break;
  2239. case LDAP_ALIAS_PROBLEM :
  2240. dwErr = ERROR_DS_ALIAS_PROBLEM;
  2241. break;
  2242. case LDAP_INVALID_DN_SYNTAX :
  2243. dwErr = ERROR_DS_INVALID_DN_SYNTAX;
  2244. break;
  2245. case LDAP_IS_LEAF :
  2246. dwErr = ERROR_DS_IS_LEAF;
  2247. break;
  2248. case LDAP_ALIAS_DEREF_PROBLEM :
  2249. dwErr = ERROR_DS_ALIAS_DEREF_PROBLEM;
  2250. break;
  2251. case LDAP_INAPPROPRIATE_AUTH :
  2252. dwErr = ERROR_DS_INAPPROPRIATE_AUTH;
  2253. break;
  2254. case LDAP_INVALID_CREDENTIALS :
  2255. dwErr = ERROR_LOGON_FAILURE;
  2256. break;
  2257. case LDAP_INSUFFICIENT_RIGHTS :
  2258. dwErr = ERROR_ACCESS_DENIED;
  2259. break;
  2260. case LDAP_BUSY :
  2261. dwErr = ERROR_DS_BUSY;
  2262. break;
  2263. case LDAP_UNAVAILABLE :
  2264. dwErr = ERROR_DS_UNAVAILABLE;
  2265. break;
  2266. case LDAP_UNWILLING_TO_PERFORM :
  2267. dwErr = ERROR_DS_UNWILLING_TO_PERFORM;
  2268. break;
  2269. case LDAP_LOOP_DETECT :
  2270. dwErr = ERROR_DS_LOOP_DETECT;
  2271. break;
  2272. case LDAP_NAMING_VIOLATION :
  2273. dwErr = ERROR_DS_NAMING_VIOLATION;
  2274. break;
  2275. case LDAP_OBJECT_CLASS_VIOLATION :
  2276. dwErr = ERROR_DS_OBJ_CLASS_VIOLATION;
  2277. break;
  2278. case LDAP_NOT_ALLOWED_ON_NONLEAF :
  2279. dwErr = ERROR_DS_CANT_ON_NON_LEAF;
  2280. break;
  2281. case LDAP_NOT_ALLOWED_ON_RDN :
  2282. dwErr = ERROR_DS_CANT_ON_RDN;
  2283. break;
  2284. case LDAP_ALREADY_EXISTS :
  2285. dwErr = ERROR_OBJECT_ALREADY_EXISTS;
  2286. break;
  2287. case LDAP_NO_OBJECT_CLASS_MODS :
  2288. dwErr = ERROR_DS_CANT_MOD_OBJ_CLASS;
  2289. break;
  2290. case LDAP_RESULTS_TOO_LARGE :
  2291. dwErr = ERROR_DS_OBJECT_RESULTS_TOO_LARGE;
  2292. break;
  2293. case LDAP_AFFECTS_MULTIPLE_DSAS :
  2294. dwErr = ERROR_DS_AFFECTS_MULTIPLE_DSAS;
  2295. break;
  2296. case LDAP_OTHER :
  2297. dwErr = ERROR_GEN_FAILURE;
  2298. break;
  2299. case LDAP_SERVER_DOWN :
  2300. dwErr = ERROR_DS_SERVER_DOWN;
  2301. break;
  2302. case LDAP_LOCAL_ERROR :
  2303. dwErr = ERROR_DS_LOCAL_ERROR;
  2304. break;
  2305. case LDAP_ENCODING_ERROR :
  2306. dwErr = ERROR_DS_ENCODING_ERROR;
  2307. break;
  2308. case LDAP_DECODING_ERROR :
  2309. dwErr = ERROR_DS_DECODING_ERROR;
  2310. break;
  2311. case LDAP_TIMEOUT :
  2312. dwErr = ERROR_TIMEOUT;
  2313. break;
  2314. case LDAP_AUTH_UNKNOWN :
  2315. dwErr = ERROR_DS_AUTH_UNKNOWN;
  2316. break;
  2317. case LDAP_FILTER_ERROR :
  2318. dwErr = ERROR_DS_FILTER_UNKNOWN;
  2319. break;
  2320. case LDAP_USER_CANCELLED :
  2321. dwErr = ERROR_CANCELLED;
  2322. break;
  2323. case LDAP_PARAM_ERROR :
  2324. dwErr = ERROR_DS_PARAM_ERROR;
  2325. break;
  2326. case LDAP_NO_MEMORY :
  2327. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  2328. break;
  2329. case LDAP_CONNECT_ERROR :
  2330. dwErr = ERROR_CONNECTION_REFUSED;
  2331. break;
  2332. case LDAP_NOT_SUPPORTED :
  2333. dwErr = ERROR_DS_NOT_SUPPORTED;
  2334. break;
  2335. case LDAP_NO_RESULTS_RETURNED :
  2336. dwErr = ERROR_DS_NO_RESULTS_RETURNED;
  2337. break;
  2338. case LDAP_CONTROL_NOT_FOUND :
  2339. dwErr = ERROR_DS_CONTROL_NOT_FOUND;
  2340. break;
  2341. case LDAP_MORE_RESULTS_TO_RETURN :
  2342. dwErr = ERROR_MORE_DATA;
  2343. break;
  2344. case LDAP_CLIENT_LOOP :
  2345. dwErr = ERROR_DS_CLIENT_LOOP;
  2346. break;
  2347. case LDAP_REFERRAL_LIMIT_EXCEEDED :
  2348. dwErr = ERROR_DS_REFERRAL_LIMIT_EXCEEDED;
  2349. break;
  2350. default:
  2351. //
  2352. // It may not be a bad idea to add range checking here
  2353. //
  2354. dwErr = (DWORD) LdapMapErrorToWin32(ldaperr);
  2355. }
  2356. //
  2357. // Set extended error only if it was not success and the
  2358. // handle was not NULL
  2359. //
  2360. if ((ldaperr != LDAP_SUCCESS) && (ld !=NULL)) {
  2361. dwStatus = ldap_get_optionW(
  2362. ld,
  2363. LDAP_OPT_SERVER_ERROR,
  2364. (void *)&ppszLdapMessage
  2365. );
  2366. if (ppszLdapMessage != NULL && dwStatus == NO_ERROR) {
  2367. dwLdapErrParse = wcstoul(ppszLdapMessage, &pszStopChar, 16);
  2368. //
  2369. // If the error code is zero and the message and stopChar
  2370. // point to the same location, we must have invalid data.
  2371. // We also have invalid data if the return value from the
  2372. // call is ULONG_MAX.
  2373. //
  2374. if ((!dwLdapErrParse && (ppszLdapMessage == pszStopChar))
  2375. || (dwLdapErrParse == (DWORD) -1)
  2376. ) {
  2377. dwLdapErrParse = ERROR_INVALID_DATA;
  2378. }
  2379. }
  2380. ADsSetLastError(
  2381. dwLdapErrParse,
  2382. ppszLdapMessage,
  2383. L"LDAP Provider"
  2384. );
  2385. if (ppszLdapMessage) {
  2386. LdapMemFree(ppszLdapMessage);
  2387. ppszLdapMessage = NULL;
  2388. }
  2389. } else {
  2390. // We need to reset the last error with a well known value
  2391. ADsSetLastError(
  2392. NO_ERROR,
  2393. NULL,
  2394. L"LDAP Provider"
  2395. );
  2396. }
  2397. *perr = HRESULT_FROM_WIN32(dwErr);
  2398. }
  2399. //
  2400. // Return TRUE if the error is a connection error. Ie. this bind handle is
  2401. // no longer valid and should not be reused.
  2402. //
  2403. BOOL LdapConnectionErr(
  2404. int err,
  2405. int ldaperr,
  2406. BOOL *fTryRebind
  2407. )
  2408. {
  2409. (void) fTryRebind ; // currently not used
  2410. switch (err) {
  2411. case ERROR_DS_UNAVAILABLE :
  2412. case ERROR_GEN_FAILURE :
  2413. case ERROR_DS_LOCAL_ERROR :
  2414. case ERROR_DS_SERVER_DOWN :
  2415. return TRUE ;
  2416. default:
  2417. return FALSE ;
  2418. }
  2419. }
  2420. HRESULT LdapSearchExtSHelper(
  2421. LDAP *ld,
  2422. WCHAR *base,
  2423. int scope,
  2424. WCHAR *filter,
  2425. WCHAR *attrs[],
  2426. int attrsonly,
  2427. PLDAPControlW * ServerControls,
  2428. PLDAPControlW *ClientControls,
  2429. struct l_timeval *Timeout,
  2430. ULONG SizeLimit,
  2431. LDAPMessage **res
  2432. )
  2433. {
  2434. HRESULT hr = S_OK;
  2435. int ldaperr = 0;
  2436. ldaperr = ldap_search_ext_s( ld,
  2437. base,
  2438. scope,
  2439. filter,
  2440. attrs,
  2441. attrsonly,
  2442. ServerControls,
  2443. ClientControls,
  2444. Timeout,
  2445. SizeLimit,
  2446. res );
  2447. if (ldaperr) {
  2448. CheckAndSetExtendedError( ld, &hr, ldaperr, *res );
  2449. }
  2450. return hr;
  2451. }
  2452. HRESULT LdapSearchExtS(
  2453. ADS_LDP *ld,
  2454. WCHAR *base,
  2455. int scope,
  2456. WCHAR *filter,
  2457. WCHAR *attrs[],
  2458. int attrsonly,
  2459. PLDAPControlW * ServerControls,
  2460. PLDAPControlW *ClientControls,
  2461. struct l_timeval *Timeout,
  2462. ULONG SizeLimit,
  2463. LDAPMessage **res
  2464. )
  2465. {
  2466. HRESULT hr = LdapSearchExtSHelper(
  2467. ld->LdapHandle,
  2468. base,
  2469. scope,
  2470. filter,
  2471. attrs,
  2472. attrsonly,
  2473. ServerControls,
  2474. ClientControls,
  2475. Timeout,
  2476. SizeLimit,
  2477. res );
  2478. if ( LdapConnectionErr(hr, 0, NULL)) {
  2479. BindCacheInvalidateEntry(ld) ;
  2480. }
  2481. return hr;
  2482. }
  2483. HRESULT LdapSearchExt(
  2484. ADS_LDP *ld,
  2485. WCHAR *base,
  2486. int scope,
  2487. WCHAR *filter,
  2488. WCHAR *attrs[],
  2489. int attrsonly,
  2490. PLDAPControlW *ServerControls,
  2491. PLDAPControlW *ClientControls,
  2492. ULONG TimeLimit,
  2493. ULONG SizeLimit,
  2494. ULONG *MessageNumber
  2495. )
  2496. {
  2497. char *pszBaseA = NULL;
  2498. int ldaperr = 0;
  2499. HRESULT hr = 0;
  2500. ldaperr = ldap_search_ext(
  2501. ld->LdapHandle,
  2502. base,
  2503. scope,
  2504. filter,
  2505. attrs,
  2506. attrsonly,
  2507. ServerControls,
  2508. ClientControls,
  2509. TimeLimit,
  2510. SizeLimit,
  2511. MessageNumber
  2512. );
  2513. CheckAndSetExtendedError( ld->LdapHandle, &hr, ldaperr);
  2514. if (LdapConnectionErr(hr, 0, NULL)) {
  2515. BindCacheInvalidateEntry(ld) ;
  2516. }
  2517. return hr;
  2518. }
  2519. ULONG _cdecl QueryForConnection(
  2520. PLDAP PrimaryConnection,
  2521. PLDAP ReferralFromConnection,
  2522. PWCHAR NewDN,
  2523. PCHAR HostName,
  2524. ULONG PortNumber,
  2525. PVOID SecAuthIdentity, // if null, use CurrentUser below
  2526. PVOID CurrentUserToken, // pointer to current user's LUID
  2527. PLDAP *ConnectionToUse
  2528. )
  2529. {
  2530. HRESULT hr = S_OK;
  2531. PADS_LDP pCacheEntry = NULL;
  2532. LPWSTR pszServer = NULL;
  2533. PSEC_WINNT_AUTH_IDENTITY pSecAuthIdentity = (PSEC_WINNT_AUTH_IDENTITY) SecAuthIdentity;
  2534. PLUID pLuid = (PLUID) CurrentUserToken;
  2535. CCredentials Credentials;
  2536. if (ConnectionToUse) {
  2537. *ConnectionToUse = NULL;
  2538. }
  2539. if (!pLuid) {
  2540. goto error;
  2541. }
  2542. if (pSecAuthIdentity) {
  2543. hr = Credentials.SetUserName(pSecAuthIdentity->User);
  2544. BAIL_ON_FAILURE(hr);
  2545. hr = Credentials.SetPassword(pSecAuthIdentity->Password);
  2546. BAIL_ON_FAILURE(hr);
  2547. Credentials.SetAuthFlags(ADS_SECURE_AUTHENTICATION);
  2548. }
  2549. if (ConvertToUnicode(HostName, &pszServer ))
  2550. goto error;
  2551. if (!pszServer) {
  2552. //
  2553. // Cannot do a lookup without server name.
  2554. //
  2555. goto error;
  2556. }
  2557. if (pCacheEntry = BindCacheLookup(pszServer, *pLuid, ReservedLuid, Credentials, PortNumber)) {
  2558. *ConnectionToUse = pCacheEntry->LdapHandle ;
  2559. }
  2560. error:
  2561. if (pszServer) {
  2562. FreeADsMem(pszServer);
  2563. }
  2564. return 0;
  2565. }
  2566. BOOLEAN _cdecl NotifyNewConnection(
  2567. PLDAP PrimaryConnection,
  2568. PLDAP ReferralFromConnection,
  2569. PWCHAR NewDN,
  2570. PCHAR HostName,
  2571. PLDAP NewConnection,
  2572. ULONG PortNumber,
  2573. PVOID SecAuthIdentity, // if null, use CurrentUser below
  2574. PVOID CurrentUser, // pointer to current user's LUID
  2575. ULONG ErrorCodeFromBind
  2576. )
  2577. {
  2578. PADS_LDP pCacheEntry = NULL;
  2579. PADS_LDP pPrimaryEntry = NULL;
  2580. HRESULT hr = S_OK;
  2581. LPWSTR pszServer = NULL;
  2582. DWORD err;
  2583. BOOLEAN ret = FALSE;
  2584. PSEC_WINNT_AUTH_IDENTITY pSecAuthIdentity = (PSEC_WINNT_AUTH_IDENTITY) SecAuthIdentity;
  2585. PLUID pLuid = (PLUID) CurrentUser;
  2586. CCredentials Credentials;
  2587. if (!pLuid || !NewConnection) {
  2588. goto error;
  2589. }
  2590. //
  2591. // Get the cache entry corresponding to the Primary Connection
  2592. // This is necessary so that we can link the new connection to the primary
  2593. // connection so that we can decrease the reference
  2594. //
  2595. if ((pPrimaryEntry = GetCacheEntry(PrimaryConnection)) == NULL) {
  2596. goto error;
  2597. }
  2598. err = BindCacheAllocEntry(&pCacheEntry) ;
  2599. if (err != NO_ERROR) {
  2600. goto error;
  2601. }
  2602. if ( ConvertToUnicode(HostName, &pszServer))
  2603. goto error;
  2604. if (pSecAuthIdentity) {
  2605. hr = Credentials.SetUserName(pSecAuthIdentity->User);
  2606. BAIL_ON_FAILURE(hr);
  2607. hr = Credentials.SetPassword(pSecAuthIdentity->Password);
  2608. BAIL_ON_FAILURE(hr);
  2609. Credentials.SetAuthFlags(ADS_SECURE_AUTHENTICATION);
  2610. }
  2611. pCacheEntry->LdapHandle = NewConnection;
  2612. err = BindCacheAdd(pszServer, *pLuid, ReservedLuid, Credentials, PortNumber, pCacheEntry) ;
  2613. if (err == NO_ERROR) {
  2614. if (!AddReferralLink(pPrimaryEntry, pCacheEntry)) {
  2615. //
  2616. // If the referral link could not be succesfully added, we don't
  2617. // want to keep this connection.
  2618. //
  2619. BindCacheDeref(pCacheEntry);
  2620. goto error;
  2621. }
  2622. //
  2623. // return TRUE to indicate that we have succesfully cached the handle
  2624. //
  2625. ret = TRUE;
  2626. }
  2627. error:
  2628. if (pszServer) {
  2629. FreeADsMem(pszServer);
  2630. }
  2631. if (!ret && pCacheEntry) {
  2632. FreeADsMem(pCacheEntry);
  2633. }
  2634. return ret;
  2635. }
  2636. ULONG _cdecl DereferenceConnection(
  2637. PLDAP PrimaryConnection,
  2638. PLDAP ConnectionToDereference
  2639. )
  2640. {
  2641. PADS_LDP pCacheEntry;
  2642. if (ConnectionToDereference) {
  2643. if (pCacheEntry = GetCacheEntry(ConnectionToDereference)) {
  2644. LdapCloseObject(pCacheEntry);
  2645. }
  2646. }
  2647. return S_OK;
  2648. }
  2649. HRESULT LdapSearchInitPage(
  2650. ADS_LDP *ld,
  2651. PWCHAR base,
  2652. ULONG scope,
  2653. PWCHAR filter,
  2654. PWCHAR attrs[],
  2655. ULONG attrsonly,
  2656. PLDAPControlW *serverControls,
  2657. PLDAPControlW *clientControls,
  2658. ULONG pageTimeLimit,
  2659. ULONG totalSizeLimit,
  2660. PLDAPSortKeyW *sortKeys,
  2661. PLDAPSearch *ppSearch
  2662. )
  2663. {
  2664. HRESULT hr = S_OK;
  2665. int ldaperr = 0;
  2666. ADsAssert(ppSearch);
  2667. *ppSearch = ldap_search_init_page(
  2668. ld->LdapHandle,
  2669. base,
  2670. scope,
  2671. filter,
  2672. attrs,
  2673. attrsonly,
  2674. serverControls,
  2675. clientControls,
  2676. pageTimeLimit,
  2677. totalSizeLimit,
  2678. sortKeys
  2679. );
  2680. if (*ppSearch == NULL) {
  2681. ldaperr = LdapGetLastError();
  2682. }
  2683. CheckAndSetExtendedError( ld->LdapHandle, &hr, ldaperr );
  2684. if ( LdapConnectionErr(hr, 0, NULL)) {
  2685. BindCacheInvalidateEntry(ld) ;
  2686. }
  2687. return hr;
  2688. }
  2689. HRESULT LdapGetNextPage(
  2690. ADS_LDP *ld,
  2691. PLDAPSearch searchHandle,
  2692. ULONG pageSize,
  2693. ULONG *pMessageNumber
  2694. )
  2695. {
  2696. HRESULT hr = S_OK;
  2697. int ldaperr = ldap_get_next_page(
  2698. ld->LdapHandle,
  2699. searchHandle,
  2700. pageSize,
  2701. pMessageNumber
  2702. );
  2703. CheckAndSetExtendedError( ld->LdapHandle, &hr, ldaperr );
  2704. if ( LdapConnectionErr(hr, 0, NULL)) {
  2705. BindCacheInvalidateEntry(ld) ;
  2706. }
  2707. return hr;
  2708. }
  2709. HRESULT LdapGetNextPageS(
  2710. ADS_LDP *ld,
  2711. PLDAPSearch searchHandle,
  2712. struct l_timeval *timeOut,
  2713. ULONG pageSize,
  2714. ULONG *totalCount,
  2715. LDAPMessage **results
  2716. )
  2717. {
  2718. HRESULT hr = S_OK;
  2719. int ldaperr = ldap_get_next_page_s(
  2720. ld->LdapHandle,
  2721. searchHandle,
  2722. timeOut,
  2723. pageSize,
  2724. totalCount,
  2725. results
  2726. );
  2727. CheckAndSetExtendedError( ld->LdapHandle, &hr, ldaperr );
  2728. if ( LdapConnectionErr(hr, 0, NULL)) {
  2729. BindCacheInvalidateEntry(ld) ;
  2730. }
  2731. return hr;
  2732. }
  2733. HRESULT LdapGetPagedCount(
  2734. ADS_LDP *ld,
  2735. PLDAPSearch searchBlock,
  2736. ULONG *totalCount,
  2737. PLDAPMessage results
  2738. )
  2739. {
  2740. HRESULT hr = S_OK;
  2741. int ldaperr = ldap_get_paged_count(
  2742. ld->LdapHandle,
  2743. searchBlock,
  2744. totalCount,
  2745. results
  2746. );
  2747. CheckAndSetExtendedError( ld->LdapHandle, &hr, ldaperr, results );
  2748. if ( LdapConnectionErr(hr, 0, NULL)) {
  2749. BindCacheInvalidateEntry(ld) ;
  2750. }
  2751. return hr;
  2752. }
  2753. HRESULT LdapSearchAbandonPage(
  2754. ADS_LDP *ld,
  2755. PLDAPSearch searchBlock
  2756. )
  2757. {
  2758. HRESULT hr = S_OK;
  2759. int ldaperr = ldap_search_abandon_page(
  2760. ld->LdapHandle,
  2761. searchBlock
  2762. );
  2763. CheckAndSetExtendedError( ld->LdapHandle, &hr, ldaperr );
  2764. if ( LdapConnectionErr(hr, 0, NULL)) {
  2765. BindCacheInvalidateEntry(ld) ;
  2766. }
  2767. return hr;
  2768. }
  2769. HRESULT LdapEncodeSortControl(
  2770. ADS_LDP *ld,
  2771. PLDAPSortKeyW *SortKeys,
  2772. PLDAPControlW Control,
  2773. BOOLEAN Criticality
  2774. )
  2775. {
  2776. HRESULT hr = S_OK;
  2777. int ldaperr = ldap_encode_sort_controlW (
  2778. ld->LdapHandle,
  2779. SortKeys,
  2780. Control,
  2781. Criticality
  2782. );
  2783. CheckAndSetExtendedError( ld->LdapHandle, &hr, ldaperr );
  2784. return hr;
  2785. }
  2786. BOOL IsGCNamespace(
  2787. LPWSTR szADsPath
  2788. )
  2789. {
  2790. WCHAR szNamespace[MAX_PATH];
  2791. HRESULT hr = S_OK;
  2792. hr = GetNamespaceFromADsPath(
  2793. szADsPath,
  2794. szNamespace
  2795. );
  2796. if (FAILED(hr))
  2797. return FALSE;
  2798. return (_wcsicmp(szNamespace, szGCNamespaceName) == 0);
  2799. }
  2800. HRESULT LdapCreatePageControl(
  2801. ADS_LDP *ld,
  2802. ULONG dwPageSize,
  2803. struct berval *Cookie,
  2804. BOOL fIsCritical,
  2805. PLDAPControl *Control // Use LdapControlFree to free
  2806. )
  2807. {
  2808. HRESULT hr = S_OK;
  2809. int ldaperr = ldap_create_page_control(
  2810. ld->LdapHandle,
  2811. dwPageSize,
  2812. Cookie,
  2813. (UCHAR) fIsCritical,
  2814. Control
  2815. );
  2816. CheckAndSetExtendedError( ld->LdapHandle, &hr, ldaperr );
  2817. return hr;
  2818. }
  2819. HRESULT LdapParsePageControl(
  2820. ADS_LDP *ld,
  2821. PLDAPControl *ServerControls,
  2822. ULONG *TotalCount,
  2823. struct berval **Cookie // Use BerBvFree to free
  2824. )
  2825. {
  2826. HRESULT hr = S_OK;
  2827. int ldaperr = ldap_parse_page_control(
  2828. ld->LdapHandle,
  2829. ServerControls,
  2830. TotalCount,
  2831. Cookie
  2832. );
  2833. CheckAndSetExtendedError( ld->LdapHandle, &hr, ldaperr );
  2834. return hr;
  2835. }
  2836. HRESULT LdapCreateVLVControl(
  2837. ADS_LDP *pld,
  2838. PLDAPVLVInfo pVLVInfo,
  2839. UCHAR fCritical,
  2840. PLDAPControl *ppControl // Use LdapControlFree to free
  2841. )
  2842. {
  2843. HRESULT hr = S_OK;
  2844. int ldaperr = ldap_create_vlv_control(
  2845. pld->LdapHandle,
  2846. pVLVInfo,
  2847. fCritical,
  2848. ppControl
  2849. );
  2850. CheckAndSetExtendedError( pld->LdapHandle, &hr, ldaperr );
  2851. return hr;
  2852. }
  2853. HRESULT LdapParseVLVControl(
  2854. ADS_LDP *pld,
  2855. PLDAPControl *ppServerControls,
  2856. ULONG *pTargetPos,
  2857. ULONG *pListCount,
  2858. struct berval **ppCookie // Use BerBvFree to free
  2859. )
  2860. {
  2861. HRESULT hr = S_OK;
  2862. int ldaperr = ldap_parse_vlv_control(
  2863. pld->LdapHandle,
  2864. ppServerControls,
  2865. pTargetPos,
  2866. pListCount,
  2867. ppCookie,
  2868. NULL
  2869. );
  2870. CheckAndSetExtendedError( pld->LdapHandle, &hr, ldaperr );
  2871. return hr;
  2872. }
  2873. HRESULT LdapParseResult(
  2874. ADS_LDP *ld,
  2875. LDAPMessage *ResultMessage,
  2876. ULONG *ReturnCode OPTIONAL, // returned by server
  2877. PWCHAR *MatchedDNs OPTIONAL, // free with LdapMemFree
  2878. PWCHAR *ErrorMessage OPTIONAL, // free with LdapMemFree
  2879. PWCHAR **Referrals OPTIONAL, // free with LdapValueFree
  2880. PLDAPControlW **ServerControls OPTIONAL, // free with LdapFreeControls
  2881. BOOL Freeit
  2882. )
  2883. {
  2884. HRESULT hr = S_OK;
  2885. int ldaperr = ldap_parse_result(
  2886. ld->LdapHandle,
  2887. ResultMessage,
  2888. ReturnCode,
  2889. MatchedDNs,
  2890. ErrorMessage,
  2891. Referrals,
  2892. ServerControls,
  2893. (BOOLEAN) Freeit
  2894. );
  2895. CheckAndSetExtendedError( ld->LdapHandle, &hr, ldaperr, ResultMessage );
  2896. return hr;
  2897. }
  2898. void
  2899. LdapControlsFree(
  2900. PLDAPControl *ppControl
  2901. )
  2902. {
  2903. ldap_controls_free( ppControl );
  2904. }
  2905. void
  2906. LdapControlFree(
  2907. PLDAPControl pControl
  2908. )
  2909. {
  2910. ldap_control_free( pControl );
  2911. }
  2912. void
  2913. BerBvFree(
  2914. struct berval *bv
  2915. )
  2916. {
  2917. ber_bvfree( bv );
  2918. }
  2919. //
  2920. // This function looks at the LDAP error code to see if we
  2921. // should try and bind again using a lower version level or
  2922. // alternate mechanism
  2923. //
  2924. BOOLEAN
  2925. LDAPCodeWarrantsRetry(
  2926. HRESULT hr
  2927. )
  2928. {
  2929. BOOLEAN fretVal = FALSE;
  2930. switch (hr) {
  2931. case HRESULT_FROM_WIN32(ERROR_DS_OPERATIONS_ERROR) :
  2932. fretVal = TRUE;
  2933. break;
  2934. case HRESULT_FROM_WIN32(ERROR_DS_PROTOCOL_ERROR) :
  2935. fretVal = TRUE;
  2936. break;
  2937. case HRESULT_FROM_WIN32(ERROR_DS_AUTH_METHOD_NOT_SUPPORTED) :
  2938. fretVal = TRUE;
  2939. break;
  2940. case HRESULT_FROM_WIN32(ERROR_DS_AUTH_UNKNOWN) :
  2941. fretVal = TRUE;
  2942. break;
  2943. case HRESULT_FROM_WIN32(ERROR_DS_NOT_SUPPORTED) :
  2944. fretVal = TRUE;
  2945. break;
  2946. default:
  2947. fretVal = FALSE;
  2948. break;
  2949. } // end case
  2950. return fretVal;
  2951. }
  2952. HRESULT
  2953. LdapcSetStickyServer(
  2954. LPWSTR pszDomainName,
  2955. LPWSTR pszServerName
  2956. )
  2957. {
  2958. HRESULT hr = S_OK;
  2959. if (gpszServerName) {
  2960. FreeADsStr(gpszServerName);
  2961. gpszServerName = NULL;
  2962. }
  2963. if (pszServerName) {
  2964. gpszServerName = AllocADsStr(pszServerName);
  2965. if (!gpszServerName) {
  2966. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  2967. }
  2968. }
  2969. if (gpszDomainName) {
  2970. FreeADsStr(gpszDomainName);
  2971. gpszDomainName = NULL;
  2972. }
  2973. if (pszDomainName) {
  2974. gpszDomainName = AllocADsStr(pszDomainName);
  2975. if (!gpszDomainName) {
  2976. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  2977. }
  2978. }
  2979. RRETURN(hr);
  2980. error :
  2981. if (gpszServerName) {
  2982. FreeADsStr(gpszServerName);
  2983. gpszServerName = NULL;
  2984. }
  2985. if (gpszDomainName) {
  2986. FreeADsStr(gpszDomainName);
  2987. gpszDomainName = NULL;
  2988. }
  2989. RRETURN(hr);
  2990. }