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.

488 lines
15 KiB

  1. #include <precomp.h>
  2. #include "tracing.h"
  3. #include "utils.h"
  4. //------------------------------------
  5. // Allocates storage for RPC transactions. The RPC stubs will either call
  6. // MIDL_user_allocate when it needs to un-marshall data into a buffer
  7. // that the user must free. RPC servers will use MIDL_user_allocate to
  8. // allocate storage that the RPC server stub will free after marshalling
  9. // the data.
  10. PVOID
  11. MIDL_user_allocate(IN size_t NumBytes)
  12. {
  13. PVOID pMem = NULL;
  14. DWORD dwErr = ERROR_SUCCESS;
  15. if (NumBytes == 0)
  16. {
  17. dwErr = ERROR_INVALID_PARAMETER;
  18. }
  19. else
  20. {
  21. pMem = LocalAlloc(LMEM_ZEROINIT,NumBytes);
  22. if (pMem == NULL)
  23. dwErr = GetLastError();
  24. }
  25. DbgPrint((TRC_MEM, "[MIDL_user_allocate(%d)=0x%p;%d]", NumBytes, pMem, dwErr));
  26. SetLastError(dwErr);
  27. return pMem;
  28. }
  29. //------------------------------------
  30. // Frees storage used in RPC transactions. The RPC client can call this
  31. // function to free buffer space that was allocated by the RPC client
  32. // stub when un-marshalling data that is to be returned to the client.
  33. // The Client calls MIDL_user_free when it is finished with the data and
  34. // desires to free up the storage.
  35. // The RPC server stub calls MIDL_user_free when it has completed
  36. // marshalling server data that is to be passed back to the client.
  37. VOID
  38. MIDL_user_free(IN LPVOID MemPointer)
  39. {
  40. DbgPrint((TRC_MEM, "[MIDL_user_free(0x%p)]", MemPointer));
  41. if (MemPointer != NULL)
  42. LocalFree(MemPointer);
  43. }
  44. //------------------------------------
  45. // Allocates general usage memory from the process heap
  46. PVOID
  47. Process_user_allocate(IN size_t NumBytes)
  48. {
  49. PVOID pMem = NULL;
  50. DWORD dwErr = ERROR_SUCCESS;
  51. if (NumBytes == 0)
  52. {
  53. dwErr = ERROR_INVALID_PARAMETER;
  54. }
  55. else
  56. {
  57. pMem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, NumBytes);
  58. if (pMem == NULL)
  59. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  60. }
  61. DbgPrint((TRC_MEM, "[MemAlloc(%d)=0x%p;%d]", NumBytes, pMem, dwErr));
  62. SetLastError(dwErr);
  63. return pMem;
  64. }
  65. //------------------------------------
  66. // Frees general usage memory
  67. VOID
  68. Process_user_free(IN LPVOID pMem)
  69. {
  70. DbgPrint((TRC_MEM, "[MemFree(0x%p)]", pMem));
  71. if (pMem != NULL)
  72. HeapFree(GetProcessHeap(), 0, (pMem));
  73. }
  74. //-----------------------------------------------------------
  75. // Searches pwzcConfig in the list pwzcVList. The entries are
  76. // matched exclusively based on the matching SSIDs and on
  77. // matching Infrastructure Mode.
  78. // [in] pwzcVList: Set of WZC_WLAN_CONFIGs to search in
  79. // [in] pwzcConfig: WZC_WLAN_CONFIG to look for
  80. // [in] nIdx: index in pwzcVList to start searching from
  81. // Returns: Pointer to the entry that matches pwzcConfig or NULL
  82. // if none matches
  83. PWZC_WLAN_CONFIG
  84. WzcFindConfig(
  85. PWZC_802_11_CONFIG_LIST pwzcList,
  86. PWZC_WLAN_CONFIG pwzcConfig,
  87. ULONG nIdx)
  88. {
  89. PWZC_WLAN_CONFIG pMatchingConfig = NULL;
  90. // if there is no config in pwzcList, there is no reason in
  91. // looking further
  92. if (pwzcList != NULL)
  93. {
  94. ULONG i;
  95. // for each of the visible SSIDs, see if it matches the given one
  96. for (i = nIdx; i < pwzcList->NumberOfItems; i++)
  97. {
  98. PWZC_WLAN_CONFIG pCrt;
  99. pCrt = &(pwzcList->Config[i]);
  100. // the SSIDs match if they have the same InfrastructureMode, their
  101. // SSID strings have the same length and are the same
  102. if (pCrt->InfrastructureMode == pwzcConfig->InfrastructureMode &&
  103. pCrt->Ssid.SsidLength == pwzcConfig->Ssid.SsidLength &&
  104. RtlCompareMemory(pCrt->Ssid.Ssid, pwzcConfig->Ssid.Ssid, pCrt->Ssid.SsidLength) == pCrt->Ssid.SsidLength)
  105. {
  106. pMatchingConfig = pCrt;
  107. break;
  108. }
  109. }
  110. }
  111. return pMatchingConfig;
  112. }
  113. //---------------------------------------------------------------------
  114. // Matches the content of the two configurations one against the other.
  115. // [in] pwzcConfigA: | configs to match
  116. // [in] pwzcConfigB: |
  117. // [in/out] pbWepDiffOnly: TRUE if there is a difference and the difference is exclusively
  118. // in the WEP Key index or in WEP Key Material. Otherwise is false.
  119. // Returns: TRUE if the configs match, FALSE otherwise;
  120. BOOL
  121. WzcMatchConfig(
  122. PWZC_WLAN_CONFIG pwzcConfigA,
  123. PWZC_WLAN_CONFIG pwzcConfigB,
  124. PBOOL pbWepDiffOnly)
  125. {
  126. BOOL bDiff;
  127. BOOL bWepDiff;
  128. bDiff = (pwzcConfigA->dwCtlFlags & WZCCTL_WEPK_PRESENT) != (pwzcConfigB->dwCtlFlags & WZCCTL_WEPK_PRESENT);
  129. bDiff = bDiff || (pwzcConfigA->Privacy != pwzcConfigB->Privacy);
  130. bDiff = bDiff || (pwzcConfigA->InfrastructureMode != pwzcConfigB->InfrastructureMode);
  131. bDiff = bDiff || (pwzcConfigA->AuthenticationMode != pwzcConfigB->AuthenticationMode);
  132. bDiff = bDiff || (memcmp(&pwzcConfigA->Ssid, &pwzcConfigB->Ssid, sizeof(NDIS_802_11_SSID)) != 0);
  133. bWepDiff = (pwzcConfigA->KeyIndex != pwzcConfigB->KeyIndex);
  134. bWepDiff = bWepDiff || (pwzcConfigA->KeyLength != pwzcConfigB->KeyLength);
  135. bWepDiff = bWepDiff || (memcmp(&pwzcConfigA->KeyMaterial, &pwzcConfigB->KeyMaterial, WZCCTL_MAX_WEPK_MATERIAL) != 0);
  136. if (pbWepDiffOnly != NULL)
  137. *pbWepDiffOnly = (!bDiff && bWepDiff);
  138. return !bDiff && !bWepDiff;
  139. }
  140. //-----------------------------------------------------------
  141. // Converts an NDIS_802_11_BSSID_LIST object to an equivalent
  142. // (imaged) WZC_802_11_CONFIG_LIST
  143. // [in] pndList: NDIS BSSID list to convert
  144. // Returns: Pointer to the list of copied WZC configurations
  145. PWZC_802_11_CONFIG_LIST
  146. WzcNdisToWzc(
  147. PNDIS_802_11_BSSID_LIST pndList)
  148. {
  149. PWZC_802_11_CONFIG_LIST pwzcList = NULL;
  150. // if there is no NDIS list, don't do anything
  151. if (pndList != NULL)
  152. {
  153. // allocate space for the WZC image
  154. pwzcList = (PWZC_802_11_CONFIG_LIST)
  155. MemCAlloc(FIELD_OFFSET(WZC_802_11_CONFIG_LIST, Config) +
  156. pndList->NumberOfItems * sizeof(WZC_WLAN_CONFIG));
  157. // in case allocation failed, return NULL, the caller will know it
  158. // is an error since he passed down a !NULL pointer.
  159. if (pwzcList != NULL)
  160. {
  161. UINT i;
  162. LPBYTE prawList = (LPBYTE)&(pndList->Bssid[0]);
  163. pwzcList->NumberOfItems = pndList->NumberOfItems;
  164. // for each of the NDIS configs, copy the relevant data into the WZC config
  165. for (i = 0; i < pwzcList->NumberOfItems; i++)
  166. {
  167. PWZC_WLAN_CONFIG pwzcConfig;
  168. PNDIS_WLAN_BSSID pndBssid;
  169. pwzcConfig = &(pwzcList->Config[i]);
  170. pndBssid = (PNDIS_WLAN_BSSID)prawList;
  171. prawList += pndBssid->Length;
  172. pwzcConfig->Length = sizeof(WZC_WLAN_CONFIG);
  173. memcpy(&(pwzcConfig->MacAddress), &(pndBssid->MacAddress), sizeof(NDIS_802_11_MAC_ADDRESS));
  174. memcpy(&(pwzcConfig->Ssid), &(pndBssid->Ssid), sizeof(NDIS_802_11_SSID));
  175. pwzcConfig->Privacy = pndBssid->Privacy;
  176. pwzcConfig->Rssi = pndBssid->Rssi;
  177. pwzcConfig->NetworkTypeInUse = pndBssid->NetworkTypeInUse;
  178. memcpy(&(pwzcConfig->Configuration), &(pndBssid->Configuration), sizeof(NDIS_802_11_CONFIGURATION));
  179. pwzcConfig->InfrastructureMode = pndBssid->InfrastructureMode;
  180. memcpy(&(pwzcConfig->SupportedRates), &(pndBssid->SupportedRates), sizeof(NDIS_802_11_RATES));
  181. }
  182. }
  183. }
  184. return pwzcList;
  185. }
  186. //-----------------------------------------------------------
  187. // WzcCleanupWzcList: Cleanup a list of WZC_WLAN_CONFIG objects
  188. VOID
  189. WzcCleanupWzcList(
  190. PWZC_802_11_CONFIG_LIST pwzcList)
  191. {
  192. if (pwzcList != NULL)
  193. {
  194. UINT i;
  195. for (i=0; i<pwzcList->NumberOfItems; i++)
  196. MemFree(pwzcList->Config[i].rdUserData.pData);
  197. MemFree(pwzcList);
  198. }
  199. }
  200. //-----------------------------------------------------------
  201. // RccsInit: Initializes an RCCS structure
  202. DWORD
  203. RccsInit(PRCCS_SYNC pRccs)
  204. {
  205. DWORD dwErr = ERROR_SUCCESS;
  206. // assume pRccs is not null (it shouldn't be under any
  207. // circumstances)
  208. __try
  209. {
  210. InitializeCriticalSection(&(pRccs->csMutex));
  211. }
  212. __except(EXCEPTION_EXECUTE_HANDLER)
  213. {
  214. dwErr = GetExceptionCode();
  215. }
  216. // access through this structure will be paired as Enter/Leave calls
  217. // Object deletion will bump down the ref counter which will reach 0
  218. // and will trigger the destruction code.
  219. pRccs->nRefCount = 1;
  220. return dwErr;
  221. }
  222. //-----------------------------------------------------------
  223. // RccsInit: Deletes an RCCS structure
  224. DWORD
  225. RccsDestroy(PRCCS_SYNC pRccs)
  226. {
  227. // assume pRccs is not null (it shouldn't be under any
  228. // circumstances)
  229. DeleteCriticalSection(&(pRccs->csMutex));
  230. return ERROR_SUCCESS;
  231. }
  232. //-----------------------------------------------------------
  233. // WzcCryptBuffer: Randomly generates a nBufLen bytes in the range
  234. // [loByte hiByte], all stored in pBuffer (buffer assumed preallocated)
  235. // Returns a win32 error code.
  236. DWORD
  237. WzcRndGenBuffer(LPBYTE pBuffer, UINT nBufLen, BYTE loByte, BYTE hiByte)
  238. {
  239. DWORD dwErr = ERROR_SUCCESS;
  240. HCRYPTPROV hProv = (HCRYPTPROV)NULL;
  241. if (loByte >= hiByte)
  242. dwErr = ERROR_INVALID_PARAMETER;
  243. if (dwErr == ERROR_SUCCESS)
  244. {
  245. // acquire the crypt context
  246. if (!CryptAcquireContext(
  247. &hProv,
  248. NULL,
  249. NULL,
  250. PROV_RSA_FULL,
  251. CRYPT_VERIFYCONTEXT))
  252. dwErr = GetLastError();
  253. DbgAssert((dwErr == ERROR_SUCCESS, "CryptAcquireContext failed with err=%d", dwErr));
  254. }
  255. // randomly generate the buffer of bytes
  256. if (dwErr == ERROR_SUCCESS)
  257. {
  258. if (!CryptGenRandom(
  259. hProv,
  260. nBufLen,
  261. pBuffer))
  262. dwErr = GetLastError();
  263. DbgAssert((dwErr == ERROR_SUCCESS, "CryptGenRandom failed with err=%d", dwErr));
  264. }
  265. // fix each byte from the buffer within the given range
  266. if (dwErr == ERROR_SUCCESS)
  267. {
  268. while (nBufLen > 0)
  269. {
  270. *pBuffer = loByte + *pBuffer % (hiByte - loByte + 1);
  271. pBuffer++;
  272. nBufLen--;
  273. }
  274. }
  275. // release the crypt context
  276. if (hProv != (HCRYPTPROV)NULL)
  277. CryptReleaseContext(hProv,0);
  278. return dwErr;
  279. }
  280. //-----------------------------------------------------------
  281. // WzcIsNullBuffer: Checks whether a buffer of nBufLen characters
  282. // is all filled with null characters.
  283. BOOL
  284. WzcIsNullBuffer(LPBYTE pBuffer, UINT nBufLen)
  285. {
  286. for (;nBufLen > 0 && *pBuffer == 0; pBuffer++, nBufLen--);
  287. return (nBufLen == 0);
  288. }
  289. //-----------------------------------------------------------
  290. // WzcSSKClean: Cleans up the PSEC_SESSION_KEYS object given as parameter
  291. VOID
  292. WzcSSKClean(PSEC_SESSION_KEYS pSSK)
  293. {
  294. if (pSSK->dblobSendKey.pbData != NULL)
  295. {
  296. LocalFree(pSSK->dblobSendKey.pbData);
  297. pSSK->dblobSendKey.cbData = 0;
  298. pSSK->dblobSendKey.pbData = NULL;
  299. }
  300. if (pSSK->dblobReceiveKey.pbData != NULL)
  301. {
  302. LocalFree(pSSK->dblobReceiveKey.pbData);
  303. pSSK->dblobReceiveKey.cbData = 0;
  304. pSSK->dblobReceiveKey.pbData = NULL;
  305. }
  306. }
  307. //-----------------------------------------------------------
  308. // WzcSSKFree: Frees up the memory used by the PSEC_SESSION_KEYS parameter
  309. VOID
  310. WzcSSKFree(PSEC_SESSION_KEYS pSSK)
  311. {
  312. if (pSSK != NULL)
  313. {
  314. WzcSSKClean(pSSK);
  315. MemFree(pSSK);
  316. }
  317. }
  318. //-----------------------------------------------------------
  319. // WzcSSKEncrypt: Creates/Allocates a SEC_SESSION_KEYS object
  320. // by encrypting the SESSION_KEYS object provided as parameter.
  321. DWORD
  322. WzcSSKEncrypt(PSEC_SESSION_KEYS pSSK, PSESSION_KEYS pSK)
  323. {
  324. DWORD dwErr = ERROR_SUCCESS;
  325. DATA_BLOB blobIn;
  326. DATA_BLOB blobSndOut = {0, NULL};
  327. DATA_BLOB blobRcvOut = {0, NULL};
  328. if (pSSK == NULL || pSK == NULL)
  329. {
  330. dwErr = ERROR_INVALID_PARAMETER;
  331. goto exit;
  332. }
  333. blobIn.cbData = pSK->dwKeyLength;
  334. blobIn.pbData = pSK->bSendKey;
  335. if (!CryptProtectData(
  336. &blobIn, // DATA_BLOB *pDataIn,
  337. L"", // LPCWSTR szDataDescr,
  338. NULL, // DATA_BLOB *pOptionalEntropy,
  339. NULL, // PVOID pvReserved,
  340. NULL, // CRYPTPROTECT_PROMPTSTRUCT *pPromptStrct,
  341. 0, // DWORD dwFlags,
  342. &blobSndOut)) // DATA_BLOB *pDataOut
  343. {
  344. dwErr = GetLastError();
  345. goto exit;
  346. }
  347. blobIn.cbData = pSK->dwKeyLength;
  348. blobIn.pbData = pSK->bReceiveKey;
  349. if (!CryptProtectData(
  350. &blobIn, // DATA_BLOB *pDataIn,
  351. L"", // LPCWSTR szDataDescr,
  352. NULL, // DATA_BLOB *pOptionalEntropy,
  353. NULL, // PVOID pvReserved,
  354. NULL, // CRYPTPROTECT_PROMPTSTRUCT *pPromptStrct,
  355. 0, // DWORD dwFlags,
  356. &blobRcvOut)) // DATA_BLOB *pDataOut
  357. {
  358. dwErr = GetLastError();
  359. goto exit;
  360. }
  361. pSSK->dblobSendKey = blobSndOut;
  362. pSSK->dblobReceiveKey = blobRcvOut;
  363. exit:
  364. if (dwErr != ERROR_SUCCESS)
  365. {
  366. if (blobSndOut.pbData != NULL)
  367. LocalFree(blobSndOut.pbData);
  368. if (blobRcvOut.pbData != NULL)
  369. LocalFree(blobRcvOut.pbData);
  370. }
  371. return dwErr;
  372. }
  373. //-----------------------------------------------------------
  374. // WzcSSKDecrypt: Creates/Allocates a SESSION_KEYS object
  375. // by dencrypting the SEC_SESSION_KEYS object provided as parameter.
  376. DWORD
  377. WzcSSKDecrypt(PSEC_SESSION_KEYS pSSK, PSESSION_KEYS pSK)
  378. {
  379. DWORD dwErr = ERROR_SUCCESS;
  380. DATA_BLOB blobSndOut = {0, NULL};
  381. DATA_BLOB blobRcvOut = {0, NULL};
  382. if (pSSK == NULL || pSK == NULL)
  383. {
  384. dwErr = ERROR_INVALID_PARAMETER;
  385. goto exit;
  386. }
  387. if (!CryptUnprotectData(
  388. &(pSSK->dblobSendKey),
  389. NULL,
  390. NULL,
  391. NULL,
  392. NULL,
  393. 0,
  394. &blobSndOut))
  395. {
  396. dwErr = GetLastError();
  397. goto exit;
  398. }
  399. if (blobSndOut.cbData > MAX_SESSION_KEY_LENGTH)
  400. {
  401. dwErr = ERROR_INVALID_DATA;
  402. goto exit;
  403. }
  404. if (!CryptUnprotectData(
  405. &(pSSK->dblobReceiveKey),
  406. NULL,
  407. NULL,
  408. NULL,
  409. NULL,
  410. 0,
  411. &blobRcvOut))
  412. {
  413. dwErr = GetLastError();
  414. goto exit;
  415. }
  416. if (blobRcvOut.cbData != blobSndOut.cbData)
  417. {
  418. dwErr = ERROR_INVALID_DATA;
  419. goto exit;
  420. }
  421. pSK->dwKeyLength = blobSndOut.cbData;
  422. memcpy(pSK->bSendKey, blobSndOut.pbData, blobSndOut.cbData);
  423. memcpy(pSK->bReceiveKey, blobRcvOut.pbData, blobRcvOut.cbData);
  424. exit:
  425. if (blobSndOut.pbData != NULL)
  426. LocalFree(blobSndOut.pbData);
  427. if (blobRcvOut.pbData != NULL)
  428. LocalFree(blobRcvOut.pbData);
  429. return dwErr;
  430. }