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.

589 lines
14 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 2002
  3. Module Name:
  4. selbinding.hxx
  5. Abstract:
  6. Manipulation of the selective binding registry settings.
  7. Revision History:
  8. MauricF 03-20-02 Consolodate access to selective binding settings across
  9. rpccfg/rpcnsh/rpctrans.lib
  10. --*/
  11. #include <sysinc.h>
  12. #include <selbinding.hxx>
  13. DWORD
  14. GetSelectiveBindingVersion(
  15. IN DWORD dwSize,
  16. IN LPVOID lpBuffer,
  17. OUT SB_VER *pVer
  18. )
  19. /*++
  20. Routine Description:
  21. Determines the version of the selective binding settings in this buffer.
  22. the appropriate
  23. Arguments:
  24. dwSize - Size of the buffer
  25. lpBuffer - The buffer containing the settings
  26. pVer - Pointer to the version we fill in
  27. Return Value:
  28. ERROR_OUTOFMEMORY
  29. ERROR_SUCCESS - if the buffer is corrupt -> *pVer==SB_VER_UNKNOWN, if its default settings *pVer==SB_VER_DEFAULT
  30. --*/
  31. {
  32. SUBNET_REG_ENTRY *pRegEntry;
  33. ASSERT(pVer != NULL);
  34. //Initialize the out params
  35. *pVer = SB_VER_UNKNOWN;
  36. //If NULL, then we treat it as default settings
  37. if ((dwSize == 0) || (lpBuffer == NULL))
  38. {
  39. *pVer = SB_VER_DEFAULT;
  40. return ERROR_SUCCESS;
  41. }
  42. //If its not large enough to hold the flag, then
  43. //it isn't new format, could be the old format
  44. if (dwSize < sizeof(DWORD))
  45. {
  46. *pVer = SB_VER_INDICES;
  47. return ERROR_SUCCESS;
  48. }
  49. //We can now cast the buffer as the structure, but don't
  50. //access anything but the flag just yet
  51. pRegEntry = (SUBNET_REG_ENTRY*) lpBuffer;
  52. //If it doesn't contain our flag at the begining, its
  53. //not new format, could be a differnet format though
  54. if (((ULONG)'4vPI') != pRegEntry->dwFlag)
  55. {
  56. *pVer = SB_VER_INDICES;
  57. return ERROR_SUCCESS;
  58. }
  59. //At this point it is either new format or unknown, it is not old format
  60. //If its not large enough to hold the header, its unknown
  61. if (dwSize < sizeof(SUBNET_REG_ENTRY))
  62. {
  63. return ERROR_SUCCESS;
  64. }
  65. //Now we can access the rest of thee header
  66. //If the size is not consistent with the number of subnets
  67. //it claims to be holding then it is unknown
  68. if (dwSize != (sizeof(SUBNET_REG_ENTRY) + sizeof(DWORD) * pRegEntry->dwCount))
  69. {
  70. return ERROR_SUCCESS;
  71. }
  72. //If it is holding zero subnets, its unknown (this is not valid for SB_VER_SUBNETS)
  73. if (pRegEntry->dwCount == 0)
  74. {
  75. return ERROR_SUCCESS;
  76. }
  77. //Make sure the admit flag is either zero or one
  78. if ((pRegEntry->dwAdmit != 0) && (pRegEntry->dwAdmit != 1))
  79. {
  80. return ERROR_SUCCESS;
  81. }
  82. //Looks legit
  83. *pVer = SB_VER_SUBNETS;
  84. return ERROR_SUCCESS;
  85. }
  86. DWORD
  87. GetSelectiveBindingBuffer(
  88. OUT LPDWORD lpSize,
  89. OUT LPVOID *lppBuffer
  90. )
  91. /*++
  92. Routine Description:
  93. Retrieves the buffer from the registry and allocates space for you.
  94. Arguments:
  95. lpSize - This is filled in with the size of the buffer.
  96. lppBuffer - This will point to a buffer containing the registry entry, can't be NULL
  97. Return Value:
  98. ERROR_OUTOFMEMORY
  99. ERROR_ACCESS_DENIED - The user did not have access to the registry key.
  100. ERROR_SUCCESS - lppBuffer will point to a buffer containing the registry key or NULL if the
  101. key could not be found or is of zero size.
  102. --*/
  103. {
  104. HKEY hKey;
  105. DWORD dwStatus;
  106. DWORD dwDummy;
  107. ASSERT((lpSize != NULL) && (lppBuffer != NULL));
  108. //Init the out params
  109. *lppBuffer = NULL;
  110. *lpSize = 0;
  111. // Open the handle to our registry entry
  112. dwStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, RPC_SELECTIVE_BINDING_KEY_PATH,
  113. 0, KEY_READ, &hKey
  114. );
  115. if (dwStatus != ERROR_SUCCESS)
  116. {
  117. ASSERT((dwStatus == ERROR_FILE_NOT_FOUND) ||
  118. (dwStatus == ERROR_ACCESS_DENIED) ||
  119. (dwStatus == ERROR_OUTOFMEMORY) ||
  120. (dwStatus == ERROR_NOT_ENOUGH_MEMORY));
  121. if (dwStatus == ERROR_FILE_NOT_FOUND)
  122. {
  123. //Default settings
  124. return ERROR_SUCCESS;
  125. }
  126. return dwStatus;
  127. }
  128. // Query for the size of the buffer
  129. dwStatus = RegQueryValueEx(hKey, RPC_SELECTIVE_BINDING_VALUE,
  130. 0, &dwDummy, NULL, lpSize);
  131. if (dwStatus != ERROR_SUCCESS)
  132. {
  133. ASSERT(dwStatus == ERROR_OUTOFMEMORY);
  134. RegCloseKey(hKey);
  135. return dwStatus;
  136. }
  137. // If the size is zero, we will map this to default settings
  138. if (*lpSize == 0)
  139. {
  140. RegCloseKey(hKey);
  141. return ERROR_SUCCESS;
  142. }
  143. // Allocate the buffer
  144. *lppBuffer = new char[*lpSize];
  145. if (*lppBuffer == NULL)
  146. {
  147. RegCloseKey(hKey);
  148. return ERROR_OUTOFMEMORY;
  149. }
  150. // Get the buffer for real this time
  151. dwStatus = RegQueryValueEx(hKey, RPC_SELECTIVE_BINDING_VALUE,
  152. 0, &dwDummy, (LPBYTE)*lppBuffer, lpSize);
  153. if (dwStatus != ERROR_SUCCESS)
  154. {
  155. ASSERT(dwStatus == ERROR_OUTOFMEMORY);
  156. delete [] *lppBuffer;
  157. }
  158. RegCloseKey(hKey);
  159. return dwStatus;
  160. }
  161. DWORD
  162. GetSelectiveBindingSettings(
  163. OUT SB_VER *pVer,
  164. OUT LPDWORD lpSize,
  165. OUT LPVOID *lppSettings
  166. )
  167. /*++
  168. Routine Description:
  169. Retrieves the version and version specific setting information. *lppSettings will point to the settings
  170. if *pVer == SB_VER_INDICES or SB_VER_SUBNETS, other wise *lppSettings will be NULL
  171. Arguments:
  172. Return Value:
  173. ERROR_SUCCESS
  174. ERROR_ACCESS_DENIED
  175. ERROR_OUTOFMEMORY
  176. --*/
  177. {
  178. DWORD dwStatus = ERROR_SUCCESS;
  179. LPVOID lpBuffer = NULL;
  180. DWORD dwSize = 0;
  181. ASSERT((pVer != NULL) && (lpSize != NULL) && (lppSettings != NULL));
  182. *lppSettings = NULL;
  183. // Get the selective binding buffer
  184. dwStatus = GetSelectiveBindingBuffer(&dwSize, &lpBuffer);
  185. if (dwStatus != ERROR_SUCCESS)
  186. {
  187. ASSERT((dwStatus == ERROR_ACCESS_DENIED) ||
  188. (dwStatus == ERROR_OUTOFMEMORY));
  189. return dwStatus;
  190. }
  191. // Get the selective binding version
  192. dwStatus = GetSelectiveBindingVersion(dwSize, lpBuffer, pVer);
  193. if (dwStatus != ERROR_SUCCESS)
  194. {
  195. ASSERT(0);
  196. delete [] lpBuffer;
  197. return dwStatus;
  198. }
  199. // Depending on the version, fill in the appropriate structure
  200. switch (*pVer)
  201. {
  202. case SB_VER_INDICES:
  203. dwStatus = GetSelectiveBindingIndices(dwSize, lpBuffer, lpSize, (VER_INDICES_SETTINGS**) lppSettings);
  204. break;
  205. case SB_VER_SUBNETS:
  206. dwStatus = GetSelectiveBindingSubnets(dwSize, lpBuffer, lpSize, (VER_SUBNETS_SETTINGS**) lppSettings);
  207. break;
  208. case SB_VER_UNKNOWN:
  209. case SB_VER_DEFAULT:
  210. break;
  211. default:
  212. ASSERT(0);
  213. }
  214. ASSERT((dwStatus == ERROR_SUCCESS) ||
  215. (dwStatus == ERROR_OUTOFMEMORY));
  216. return dwStatus;
  217. }
  218. DWORD
  219. GetSelectiveBindingSubnets(
  220. IN DWORD dwSize,
  221. IN LPVOID lpBuffer,
  222. OUT LPDWORD lpSize,
  223. OUT VER_SUBNETS_SETTINGS **lppSettings
  224. )
  225. /*++
  226. Routine Description:
  227. Allocates and fills in a settings structure based off an SB_VER_SUBNETS buffer.
  228. Arguments:
  229. IN dwSize - size of the SB_VER_SUBNETS buffer
  230. IN lpBuffer - pointer to the SB_VER_SUBNETS buffer
  231. OUT lppSettings - filled in with a pointer to te subnet settings
  232. Return Value:
  233. ERROR_SUCCESS
  234. ERROR_OUTOFMEMORY
  235. --*/
  236. {
  237. SUBNET_REG_ENTRY *pEntry;
  238. ASSERT((lpBuffer != NULL) &&
  239. (lppSettings != NULL));
  240. // Cast the buffer as a SUBNET_REG_ENTRY
  241. pEntry = (SUBNET_REG_ENTRY*)lpBuffer;
  242. // Calculate the size to allocate for VER_SUBNETS_SETTINGS
  243. *lpSize = sizeof(VER_SUBNETS_SETTINGS) + pEntry->dwCount*sizeof(DWORD);
  244. *lppSettings = (VER_SUBNETS_SETTINGS*) new char [*lpSize];
  245. if (*lppSettings == NULL)
  246. return ERROR_OUTOFMEMORY;
  247. // Copy in the relevent fields
  248. (*lppSettings)->bAdmit = (BOOL)pEntry->dwAdmit;
  249. (*lppSettings)->dwCount = pEntry->dwCount;
  250. memcpy((*lppSettings)->dwSubnets, pEntry->dwSubnets, pEntry->dwCount*sizeof(DWORD));
  251. return ERROR_SUCCESS;
  252. }
  253. DWORD
  254. GetSelectiveBindingIndices(
  255. IN DWORD dwSize,
  256. IN LPVOID lpBuffer,
  257. OUT LPDWORD lpSize,
  258. OUT VER_INDICES_SETTINGS **lppSettings
  259. )
  260. /*++
  261. Routine Description:
  262. Allocates and fills in a settings structure based off an SB_VER_INDICES buffer.
  263. Arguments:
  264. IN dwSize - size of the SB_VER_INDICES buffer
  265. IN lpBuffer - pointer to the SB_VER_INDICES buffer
  266. OUT lppSettings - filled in with a pointer to the indices settings
  267. Return Value:
  268. ERROR_SUCCESS
  269. ERROR_OUTOFMEMORY
  270. --*/
  271. {
  272. DWORD dwStatus = ERROR_SUCCESS;
  273. DWORD dwCount=0;
  274. LPVOID lpTmp = NULL;
  275. DWORD dwIndex;
  276. DWORD idx;
  277. ASSERT((lpBuffer != NULL) &&
  278. (lppSettings != NULL));
  279. // Count how many indices there are
  280. lpTmp = lpBuffer;
  281. while (NextIndex((char**)&lpTmp) != -1) dwCount++;
  282. // Calculate the size to allocate for VER_INDICES_SETTINGS
  283. *lpSize = sizeof(VER_INDICES_SETTINGS) + dwCount*sizeof(DWORD);
  284. *lppSettings = (VER_INDICES_SETTINGS*) new char [*lpSize];
  285. if (*lppSettings == NULL)
  286. return ERROR_OUTOFMEMORY;
  287. // Step through and get each index
  288. lpTmp = lpBuffer;
  289. idx = 0;
  290. (*lppSettings)->dwCount = dwCount;
  291. for (idx = 0; idx <dwCount; idx++)
  292. (*lppSettings)->dwIndices[idx] = NextIndex((char**)&lpTmp);
  293. return ERROR_SUCCESS;
  294. }
  295. DWORD
  296. DeleteSelectiveBinding()
  297. /*++
  298. Routine Description:
  299. Deletes the linkage key, this indicates we should use the default settings for selective binding
  300. (listen on all interfaces).
  301. Arguments:
  302. Return Value:
  303. ERROR_SUCCESS
  304. ERROR_ACCESS_DENIED
  305. --*/
  306. {
  307. HKEY hKey;
  308. DWORD dwStatus;
  309. // Attempt to open the key
  310. dwStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, RPC_SETTINGS_PATH,
  311. 0, KEY_ALL_ACCESS, &hKey
  312. );
  313. if (dwStatus != ERROR_SUCCESS)
  314. {
  315. ASSERT((dwStatus == ERROR_ACCESS_DENIED) ||
  316. (dwStatus == ERROR_FILE_NOT_FOUND));
  317. return dwStatus;
  318. }
  319. // Delete the selective binding key
  320. dwStatus = RegDeleteKey(hKey, RPC_SELECTIVE_BINDING_KEY);
  321. ASSERT((dwStatus == ERROR_SUCCESS) ||
  322. (dwStatus == ERROR_FILE_NOT_FOUND));
  323. RegCloseKey(hKey);
  324. return ERROR_SUCCESS;
  325. }
  326. DWORD
  327. SetSelectiveBindingSubnets(
  328. IN DWORD dwCount,
  329. IN LPDWORD lpSubnetTable,
  330. IN BOOL bAdmit
  331. )
  332. /*++
  333. Routine Description:
  334. This converts the inputs into a buffer which we write to the registry using SetSelectiveBindingBuffer.
  335. Arguments:
  336. bAdmit - True for Admit (Add) list False for Deny (Delete) list.
  337. dwCount - The number of subnets we are setting. It is illegal to set zero subnets.
  338. lpSubnetTable - This is the array of subnets we wish to create an Admit or Deny list from.
  339. Return Value:
  340. ERROR_ACCESS_DENIED
  341. ERROR_OUTOFMEMORY
  342. ERROR_SUCCESS
  343. --*/
  344. {
  345. SUBNET_REG_ENTRY *pRegEntry;
  346. DWORD dwSize;
  347. DWORD dwStatus;
  348. ASSERT((dwCount !=0) &&
  349. (lpSubnetTable != NULL));
  350. //Calculate the size of the buffer
  351. dwSize = sizeof(SUBNET_REG_ENTRY) + dwCount*sizeof(DWORD);
  352. pRegEntry = (SUBNET_REG_ENTRY*) new char[dwSize];
  353. if (pRegEntry == NULL)
  354. return ERROR_OUTOFMEMORY;
  355. //Fill in the structure
  356. pRegEntry->dwFlag = ((ULONG)'4vPI');
  357. pRegEntry->dwCount = dwCount;
  358. pRegEntry->dwAdmit = (bAdmit ? ((DWORD)0x01) : ((DWORD)0x00));
  359. memcpy(pRegEntry->dwSubnets, lpSubnetTable, dwCount*sizeof(DWORD));
  360. //Write this to the registry
  361. dwStatus = SetSelectiveBindingBuffer(dwSize, (LPVOID)pRegEntry);
  362. delete [] pRegEntry;
  363. pRegEntry = NULL;
  364. return dwStatus;
  365. }
  366. DWORD
  367. SetSelectiveBindingBuffer(
  368. IN DWORD dwSize,
  369. IN LPVOID lpBuffer
  370. )
  371. /*++
  372. Routine Description:
  373. Writes the buffer to the selective binding key in the registry
  374. Arguments:
  375. dwSize - This is the size of the buffer.
  376. lpBuffer - This is the buffer we write to the registry.
  377. Return Value:
  378. ERROR_ACCESS_DENIED - The user did not have permission to write to this key
  379. ERROR_SUCCESS
  380. --*/
  381. {
  382. HKEY hKey;
  383. DWORD dwStatus;
  384. DWORD dwDummy;
  385. ASSERT((dwSize != 0) &&
  386. (lpBuffer != NULL));
  387. // Attempt to create the key, this will succeed even if the key already exists
  388. dwStatus = RegCreateKeyEx(HKEY_LOCAL_MACHINE, RPC_SELECTIVE_BINDING_KEY_PATH,
  389. 0, "", REG_OPTION_NON_VOLATILE,
  390. KEY_WRITE, NULL, &hKey, &dwDummy
  391. );
  392. if (dwStatus != ERROR_SUCCESS)
  393. {
  394. ASSERT(dwStatus == ERROR_ACCESS_DENIED);
  395. return dwStatus;
  396. }
  397. // Write the value
  398. dwStatus = RegSetValueEx(hKey, "Bind",
  399. 0, REG_BINARY, (LPBYTE)lpBuffer,
  400. dwSize
  401. );
  402. ASSERT(dwStatus == ERROR_SUCCESS);
  403. RegCloseKey(hKey);
  404. return dwStatus;
  405. }
  406. DWORD
  407. NextIndex(
  408. IN OUT char **Ptr
  409. )
  410. /*++
  411. Routine Description:
  412. Retrieves the next index from the buffer, and moves the pointer to the start of the
  413. following index.
  414. Arguments:
  415. Ptr - A pointer to the old registry format for storing indices. Each index is stored
  416. as a string, (must be ASCII when its passed to this function). The Ptr gets
  417. updated to point to the following index.
  418. Return Value:
  419. The index retrieved or -1 if the end of the buffer has been reached.
  420. --*/
  421. {
  422. char *Index = (char *)*Ptr ;
  423. if (*Index == 0)
  424. {
  425. return -1;
  426. }
  427. while (*(char *)*Ptr) ((char *)*Ptr)++ ;
  428. ((char *)*Ptr)++ ;
  429. return (DWORD) atol(Index) ;
  430. }