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.

545 lines
13 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. rndldap.cpp
  5. Abstract:
  6. This module contains implementation of ldap helper functions.
  7. --*/
  8. #include "stdafx.h"
  9. #include "rndldap.h"
  10. #include "ntldap.h"
  11. HRESULT GetAttributeValue(
  12. IN LDAP * pLdap,
  13. IN LDAPMessage * pEntry,
  14. IN const WCHAR * pName,
  15. OUT BSTR * pValue
  16. )
  17. {
  18. *pValue = NULL;
  19. TCHAR **p = ldap_get_values(pLdap, pEntry, (WCHAR *)pName);
  20. if (p != NULL)
  21. {
  22. if (p[0] != NULL)
  23. {
  24. *pValue = SysAllocString(p[0]);
  25. }
  26. ldap_value_free(p);
  27. }
  28. return (*pValue == NULL) ? E_FAIL : S_OK;
  29. }
  30. HRESULT GetAttributeValueBer(
  31. IN LDAP * pLdap,
  32. IN LDAPMessage * pEntry,
  33. IN const WCHAR * pName,
  34. OUT char ** pValue,
  35. OUT DWORD * pdwSize
  36. )
  37. {
  38. *pValue = NULL;
  39. struct berval **p = ldap_get_values_len(pLdap, pEntry, (WCHAR *)pName);
  40. if (p != NULL)
  41. {
  42. if (p[0] != NULL)
  43. {
  44. *pValue = new CHAR[p[0]->bv_len];
  45. if (*pValue == NULL)
  46. {
  47. return E_OUTOFMEMORY;
  48. }
  49. memcpy(*pValue, p[0]->bv_val, p[0]->bv_len);
  50. *pdwSize = p[0]->bv_len;
  51. }
  52. ldap_value_free_len(p);
  53. }
  54. return (*pValue == NULL) ? E_FAIL : S_OK;
  55. }
  56. HRESULT GetNamingContext(LDAP *hLdap, TCHAR **ppNamingContext)
  57. {
  58. // send a search (base level, base dn = "", filter = "objectclass=*")
  59. // ask only for the defaultNamingContext attribute
  60. PTCHAR Attributes[] = {(WCHAR *)DEFAULT_NAMING_CONTEXT, NULL};
  61. LDAPMessage *SearchResult;
  62. ULONG res = DoLdapSearch(
  63. hLdap, // ldap handle
  64. L"", // empty base dn
  65. LDAP_SCOPE_BASE, // base level search
  66. (WCHAR *)ANY_OBJECT_CLASS, // instance of any object class
  67. Attributes, // array of attribute names
  68. FALSE, // also return the attribute values
  69. &SearchResult // search results
  70. );
  71. BAIL_IF_LDAP_FAIL(res, "Search for oganization");
  72. // associate the ldap handle with the search message holder, so that the
  73. // search message may be released when the instance goes out of scope
  74. CLdapMsgPtr MessageHolder(SearchResult);
  75. TCHAR **NamingContext;
  76. LDAPMessage *EntryMessage = ldap_first_entry(hLdap, SearchResult);
  77. while ( NULL != EntryMessage )
  78. {
  79. // look for the value for the namingContexts attribute
  80. NamingContext = ldap_get_values(
  81. hLdap,
  82. EntryMessage,
  83. (WCHAR *)DEFAULT_NAMING_CONTEXT
  84. );
  85. // the first entry contains the naming context and its a single
  86. // value(null terminated) if a value is found, create memory for
  87. // the directory path, set the dir path length
  88. if ( (NULL != NamingContext) &&
  89. (NULL != NamingContext[0]) &&
  90. (NULL == NamingContext[1]) )
  91. {
  92. // the naming context value is released when the ValueHolder
  93. // instance goes out of scope
  94. CLdapValuePtr ValueHolder(NamingContext);
  95. *ppNamingContext = new TCHAR [lstrlen(NamingContext[0]) + 1];
  96. BAIL_IF_NULL(*ppNamingContext, E_OUTOFMEMORY);
  97. lstrcpy(*ppNamingContext, NamingContext[0]);
  98. // return success
  99. return S_OK;
  100. }
  101. // Get next entry.
  102. EntryMessage = ldap_next_entry(hLdap, EntryMessage);
  103. }
  104. // none found, return error
  105. return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
  106. }
  107. ULONG
  108. DoLdapSearch (
  109. LDAP *ld,
  110. PWCHAR base,
  111. ULONG scope,
  112. PWCHAR filter,
  113. PWCHAR attrs[],
  114. ULONG attrsonly,
  115. LDAPMessage **res,
  116. BOOL bSACL /*=TRUE */
  117. )
  118. {
  119. LDAP_TIMEVAL Timeout;
  120. Timeout.tv_sec = REND_LDAP_TIMELIMIT;
  121. Timeout.tv_usec = 0;
  122. //
  123. // Without SACLs
  124. //
  125. SECURITY_INFORMATION seInfo =
  126. DACL_SECURITY_INFORMATION |
  127. OWNER_SECURITY_INFORMATION |
  128. GROUP_SECURITY_INFORMATION;
  129. //
  130. // Ber val
  131. //
  132. BYTE berValue[2*sizeof(ULONG)];
  133. berValue[0] = 0x30;
  134. berValue[1] = 0x03;
  135. berValue[2] = 0x02;
  136. berValue[3] = 0x01;
  137. berValue[4] = (BYTE)(seInfo & 0xF);
  138. //
  139. // LDAP server control
  140. //
  141. LDAPControlW seInfoControl = {
  142. LDAP_SERVER_SD_FLAGS_OID_W,
  143. {5, (PCHAR)berValue},
  144. TRUE
  145. };
  146. //
  147. // LDAP Server controls list
  148. //
  149. PLDAPControlW serverControls[2] = { &seInfoControl, NULL};
  150. PLDAPControlW* pServerControls = NULL;
  151. if( !bSACL )
  152. {
  153. pServerControls = serverControls;
  154. }
  155. ULONG ulRes = ldap_search_ext_sW(ld,
  156. base,
  157. scope,
  158. filter,
  159. attrs,
  160. attrsonly,
  161. pServerControls, // server controls
  162. NULL, // client controls
  163. &Timeout, // timeout value
  164. 0, // maximum size
  165. res);
  166. //
  167. // The ldap_search* APIs are quirky in that they require you to free the
  168. // result even if the call fails. ldap_msgfree() checks its argument, so
  169. // this also doesn't break if the result *wasn't* left around. This is
  170. // inconsistent with pretty much all other Windows system APIs; to keep
  171. // from obfuscating the callers of DoLdapSearch, we free the result here
  172. // in the failure case. That way, callers can treat DoLdapSearch like any
  173. // other function that cleans up after itself on failure.
  174. //
  175. // Some callers use smart pointers that would free the message on destruction,
  176. // and some do not. Therefore we set *res to NULL after freeing *res, to
  177. // protect ourselves in either case. Any subsequent ldap_msgfree(NULL) will
  178. // do nothing (and will not fault).
  179. //
  180. if ( ulRes != LDAP_SUCCESS )
  181. {
  182. ldap_msgfree( *res );
  183. *res = NULL;
  184. }
  185. return ulRes;
  186. }
  187. //
  188. // Translates the result of an ldap_result call to an ldap error code.
  189. //
  190. ULONG LdapErrorFromLdapResult(ULONG res, LDAPMessage * pResultMessage)
  191. {
  192. ULONG ulCode;
  193. if ( res == 0 )
  194. {
  195. ulCode = LDAP_TIMEOUT;
  196. }
  197. else if ( res == (ULONG) -1 )
  198. {
  199. ulCode = LDAP_LOCAL_ERROR;
  200. }
  201. else
  202. {
  203. // ulCode = LDAP_SUCCESS;
  204. ulCode = pResultMessage->lm_returncode;
  205. }
  206. ldap_msgfree( pResultMessage );
  207. return ulCode;
  208. }
  209. ULONG
  210. DoLdapAdd (
  211. LDAP *ld,
  212. PWCHAR dn,
  213. LDAPModW *attrs[]
  214. )
  215. {
  216. //
  217. // Ask to add an object.We get back an error/success code and a
  218. // message number so that we can refer to this pending message.
  219. //
  220. ULONG ulMessageNumber;
  221. ULONG res1 = ldap_add_extW(ld,
  222. dn,
  223. attrs,
  224. NULL, // server controls
  225. NULL, // client controls
  226. &ulMessageNumber);
  227. BAIL_IF_LDAP_FAIL(res1, "ldap_add_extW");
  228. //
  229. // Wait for the result, specifying a timeout. We get
  230. // back an error/success code and a result message.
  231. //
  232. LDAP_TIMEVAL Timeout;
  233. Timeout.tv_sec = REND_LDAP_TIMELIMIT;
  234. Timeout.tv_usec = 0;
  235. LDAPMessage * pResultMessage;
  236. ULONG res2 = ldap_result(ld,
  237. ulMessageNumber,
  238. LDAP_MSG_ALL,
  239. &Timeout,
  240. &pResultMessage);
  241. //
  242. // Extract return code and free message.
  243. //
  244. return LdapErrorFromLdapResult(res2, pResultMessage);
  245. }
  246. ULONG
  247. DoLdapModify (
  248. BOOL fChase,
  249. LDAP *ld,
  250. PWCHAR dn,
  251. LDAPModW *attrs[],
  252. BOOL bSACL /*=TRUE */
  253. )
  254. {
  255. //
  256. // Chase referrals. These is only used if fChase is set, but we must not
  257. // stick them in an "if" block or they will not have appropriate scope.
  258. //
  259. LDAPControlW control;
  260. LDAPControlW * controls [] = {&control, NULL};
  261. ULONG ulValue = LDAP_CHASE_EXTERNAL_REFERRALS | LDAP_CHASE_SUBORDINATE_REFERRALS;
  262. if ( fChase )
  263. {
  264. control.ldctl_iscritical = 1;
  265. control.ldctl_oid = LDAP_CONTROL_REFERRALS_W;
  266. control.ldctl_value.bv_len = sizeof(ULONG);
  267. control.ldctl_value.bv_val = (char *) &ulValue;
  268. }
  269. //
  270. // Without SACLs
  271. //
  272. SECURITY_INFORMATION seInfo = DACL_SECURITY_INFORMATION ;
  273. //
  274. // Ber val
  275. //
  276. BYTE berValue[2*sizeof(ULONG)];
  277. berValue[0] = 0x30;
  278. berValue[1] = 0x03;
  279. berValue[2] = 0x02;
  280. berValue[3] = 0x01;
  281. berValue[4] = (BYTE)(seInfo & 0xF);
  282. //
  283. // LDAP server control
  284. //
  285. LDAPControlW seInfoControl = {
  286. LDAP_SERVER_SD_FLAGS_OID_W,
  287. {5, (PCHAR)berValue},
  288. TRUE
  289. };
  290. //
  291. // LDAP Server controls list
  292. //
  293. PLDAPControlW serverControls[2] = { &seInfoControl, NULL};
  294. PLDAPControlW* pServerControls = NULL;
  295. if( !bSACL )
  296. {
  297. pServerControls = serverControls;
  298. }
  299. //
  300. // Ask to modify an object.We get back an error/success code and a
  301. // message number so that we can refer to this pending message.
  302. //
  303. ULONG ulMessageNumber;
  304. ULONG res1 = ldap_modify_extW(ld,
  305. dn,
  306. attrs,
  307. pServerControls, // server controls
  308. fChase ? controls : NULL, // client controls
  309. &ulMessageNumber);
  310. BAIL_IF_LDAP_FAIL(res1, "ldap_modify_extW");
  311. //
  312. // Wait for the result, specifying a timeout. We get
  313. // back an error/success code and a result message.
  314. //
  315. LDAP_TIMEVAL Timeout;
  316. Timeout.tv_sec = REND_LDAP_TIMELIMIT;
  317. Timeout.tv_usec = 0;
  318. LDAPMessage * pResultMessage;
  319. ULONG res2 = ldap_result(ld,
  320. ulMessageNumber,
  321. LDAP_MSG_ALL,
  322. &Timeout,
  323. &pResultMessage);
  324. //
  325. // Extract return code and free message.
  326. //
  327. return LdapErrorFromLdapResult(res2, pResultMessage);
  328. }
  329. ULONG
  330. DoLdapDelete (
  331. LDAP *ld,
  332. PWCHAR dn
  333. )
  334. {
  335. //
  336. // Ask to delete an object.We get back an error/success code and a
  337. // message number so that we can refer to this pending message.
  338. //
  339. ULONG ulMessageNumber;
  340. ULONG res1 = ldap_delete_extW(ld,
  341. dn,
  342. NULL, // server controls
  343. NULL, // client controls
  344. &ulMessageNumber);
  345. BAIL_IF_LDAP_FAIL(res1, "ldap_delete_extW");
  346. //
  347. // Wait for the result, specifying a timeout. We get
  348. // back an error/success code and a result message.
  349. //
  350. LDAP_TIMEVAL Timeout;
  351. Timeout.tv_sec = REND_LDAP_TIMELIMIT;
  352. Timeout.tv_usec = 0;
  353. LDAPMessage * pResultMessage;
  354. ULONG res2 = ldap_result(ld,
  355. ulMessageNumber,
  356. LDAP_MSG_ALL,
  357. &Timeout,
  358. &pResultMessage);
  359. //
  360. // Extract return code and free message.
  361. //
  362. return LdapErrorFromLdapResult(res2, pResultMessage);
  363. }
  364. HRESULT SetTTL(
  365. IN LDAP * pLdap,
  366. IN const WCHAR * pDN,
  367. IN DWORD dwTTL
  368. )
  369. /*++
  370. Routine Description:
  371. Set the TTL of a dynamic object for either ILS or NDNC.
  372. Arguments:
  373. pLdap - The Ldap connection.
  374. pDN - The DN of a object on the ILS server.
  375. dwTTL - The time to live value.
  376. Return Value:
  377. HRESULT.
  378. --*/
  379. {
  380. TCHAR strTTL[32]; // The attribute value is a DWORD in string.
  381. wsprintf(strTTL, _T("%d"), dwTTL);
  382. TCHAR * ttl[] = {strTTL, NULL};
  383. LDAPMod mod; // The modify sturctures used by LDAP
  384. mod.mod_values = ttl;
  385. mod.mod_op = LDAP_MOD_REPLACE;
  386. mod.mod_type = (WCHAR *)ENTRYTTL;
  387. LDAPMod* mods[] = {&mod, NULL}; // only one attribute is modified.
  388. LOG((MSP_INFO, "setting TTL for %S", pDN));
  389. BAIL_IF_LDAP_FAIL(DoLdapModify(FALSE, pLdap, (WCHAR *)pDN, mods), "set TTL");
  390. return S_OK;
  391. }
  392. HRESULT UglyIPtoIP(
  393. BSTR pUglyIP,
  394. BSTR * pIP
  395. )
  396. // This function converts NM's IP address format to the right format.
  397. {
  398. #define IPADDRLEN 16
  399. WCHAR buffer[IPADDRLEN + 1];
  400. DWORD dwIP;
  401. dwIP = _wtoi(pUglyIP);
  402. if (dwIP == 0)
  403. {
  404. return E_FAIL;
  405. }
  406. dwIP = ntohl(dwIP);
  407. // format the four bytes in the dword into an ip address string
  408. swprintf(buffer, L"%d.%d.%d.%d",
  409. HIBYTE(HIWORD(dwIP)),
  410. LOBYTE(HIWORD(dwIP)),
  411. HIBYTE(LOWORD(dwIP)),
  412. LOBYTE(LOWORD(dwIP))
  413. );
  414. *pIP = SysAllocString(buffer);
  415. BAIL_IF_NULL(*pIP, E_OUTOFMEMORY);
  416. return S_OK;
  417. }
  418. HRESULT ParseUserName(
  419. BSTR pName,
  420. BSTR * ppAddress
  421. )
  422. {
  423. WCHAR * pCloseBracket = wcschr(pName, CLOSE_BRACKET_CHARACTER);
  424. if ( pCloseBracket == NULL )
  425. {
  426. // this is not the format generated by us.
  427. return S_FALSE;
  428. }
  429. *ppAddress = SysAllocString(pCloseBracket + 1);
  430. BAIL_IF_NULL(*ppAddress, E_OUTOFMEMORY);
  431. *pCloseBracket = NULL_CHARACTER;
  432. return S_OK;
  433. }
  434. // eof