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.

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