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.

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