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.

585 lines
13 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Copyright (c) 1997-1999 Microsoft Corporation
  4. //
  5. // File: pid.cpp
  6. //
  7. // Contents: Generate/save/retrieve license server ID to LSA
  8. //
  9. // History:
  10. //
  11. //---------------------------------------------------------------------------
  12. #include "pch.cpp"
  13. #include "pid.h"
  14. #include "gencert.h"
  15. #include "certutil.h"
  16. //////////////////////////////////////////////////////////////////
  17. DWORD
  18. ServerIdsToLsaServerId(
  19. IN PBYTE pbServerUniqueId,
  20. IN DWORD cbServerUniqueId,
  21. IN PBYTE pbServerPid,
  22. IN DWORD cbServerPid,
  23. IN PBYTE pbServerSPK,
  24. IN DWORD cbServerSPK,
  25. IN PCERT_EXTENSION pCertExtensions,
  26. IN DWORD dwNumCertExtensions,
  27. OUT PTLSLSASERVERID* ppLsaServerId,
  28. OUT DWORD* pdwLsaServerId
  29. )
  30. /*++
  31. Abstract:
  32. Combine list of License Server ID to TLSLSASERVERID structure
  33. suitable to be saved with LSA.
  34. Parameters:
  35. pbServerUniqueId : License Server Unique ID.
  36. cbServerUniqueId : size of License Server Unique Id in bytes.
  37. pbServerPid : License Server's PID
  38. cbServerPid : size of License Server's PID in bytes
  39. pbServerSPK : License Server's SPK.
  40. cbServerSPK : size of License Server's SPK in bytes.
  41. pdwLsaServerId : Pointer to DWORD to receive size of TLSLSASERVERID.
  42. pLsaServerId : PPointer to TLSLSASERVERID
  43. Returns:
  44. Note:
  45. Internal Routine.
  46. --*/
  47. {
  48. DWORD dwStatus = ERROR_SUCCESS;
  49. DWORD dwOffset = offsetof(TLSLSASERVERID, pbVariableStart);
  50. PBYTE pbEncodedExt = NULL;
  51. DWORD cbEncodedExt = 0;
  52. CERT_EXTENSIONS cert_extensions;
  53. if( pbServerSPK != NULL &&
  54. cbServerSPK != 0 &&
  55. pCertExtensions != NULL &&
  56. dwNumCertExtensions != 0 )
  57. {
  58. cert_extensions.cExtension = dwNumCertExtensions;
  59. cert_extensions.rgExtension = pCertExtensions;
  60. //
  61. // encode cert. extension
  62. //
  63. dwStatus = TLSCryptEncodeObject(
  64. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  65. szOID_CERT_EXTENSIONS,
  66. &cert_extensions,
  67. &pbEncodedExt,
  68. &cbEncodedExt
  69. );
  70. if(dwStatus != ERROR_SUCCESS)
  71. {
  72. return dwStatus;
  73. }
  74. }
  75. *pdwLsaServerId = sizeof(TLSLSASERVERID) +
  76. cbServerUniqueId +
  77. cbServerPid +
  78. cbServerSPK +
  79. cbEncodedExt;
  80. *ppLsaServerId = (PTLSLSASERVERID)AllocateMemory(*pdwLsaServerId);
  81. if(*ppLsaServerId != NULL)
  82. {
  83. (*ppLsaServerId)->dwVersion = TLSERVER_SERVER_ID_VERSION;
  84. (*ppLsaServerId)->dwUniqueId = 0;
  85. (*ppLsaServerId)->dwServerPid = 0;
  86. (*ppLsaServerId)->dwServerSPK = 0;
  87. (*ppLsaServerId)->dwExtensions = 0;
  88. if(pbServerUniqueId && cbServerUniqueId)
  89. {
  90. (*ppLsaServerId)->dwUniqueId = cbServerUniqueId;
  91. memcpy(
  92. (PBYTE)(*ppLsaServerId) + dwOffset,
  93. pbServerUniqueId,
  94. cbServerUniqueId
  95. );
  96. }
  97. if(pbServerPid && cbServerPid)
  98. {
  99. (*ppLsaServerId)->dwServerPid = cbServerPid;
  100. memcpy(
  101. (PBYTE)(*ppLsaServerId) + dwOffset + cbServerUniqueId,
  102. pbServerPid,
  103. cbServerPid
  104. );
  105. }
  106. if(pbServerSPK && cbServerSPK)
  107. {
  108. (*ppLsaServerId)->dwServerSPK = cbServerSPK;
  109. memcpy(
  110. (PBYTE)(*ppLsaServerId) + dwOffset + cbServerUniqueId + cbServerPid,
  111. pbServerSPK,
  112. cbServerSPK
  113. );
  114. }
  115. if(pbEncodedExt && cbEncodedExt)
  116. {
  117. (*ppLsaServerId)->dwExtensions = cbEncodedExt;
  118. memcpy(
  119. (PBYTE)(*ppLsaServerId) + dwOffset + cbServerUniqueId + cbServerPid + cbServerSPK,
  120. pbEncodedExt,
  121. cbEncodedExt
  122. );
  123. }
  124. }
  125. else
  126. {
  127. dwStatus = GetLastError();
  128. }
  129. FreeMemory(pbEncodedExt);
  130. return dwStatus;
  131. }
  132. //////////////////////////////////////////////////////////////////
  133. DWORD
  134. LsaServerIdToServerIds(
  135. IN PTLSLSASERVERID pLsaServerId,
  136. IN DWORD dwLsaServerId,
  137. OUT PBYTE* ppbServerUniqueId,
  138. OUT PDWORD pcbServerUniqueId,
  139. OUT PBYTE* ppbServerPid,
  140. OUT PDWORD pcbServerPid,
  141. OUT PBYTE* ppbServerSPK,
  142. OUT PDWORD pcbServerSPK,
  143. OUT PCERT_EXTENSIONS* pCertExtensions,
  144. OUT PDWORD pcbCertExtensions
  145. )
  146. /*++
  147. Abstract:
  148. Reverse of ServerIdsToLsaServerId()
  149. --*/
  150. {
  151. DWORD dwStatus = ERROR_SUCCESS;
  152. DWORD dwSize = 0;
  153. PBYTE pbUniqueId = NULL;
  154. PBYTE pbPid = NULL;
  155. PBYTE pbSPK = NULL;
  156. DWORD dwOffset = offsetof(TLSLSASERVERID, pbVariableStart);
  157. DWORD cbCertExt = 0;
  158. PCERT_EXTENSIONS pCertExt = NULL;
  159. //
  160. // verify input.
  161. //
  162. if(dwLsaServerId == 0 || pLsaServerId == NULL)
  163. {
  164. dwStatus = ERROR_INVALID_PARAMETER;
  165. goto cleanup;
  166. }
  167. if(pLsaServerId->dwVersion != TLSERVER_SERVER_ID_VERSION)
  168. {
  169. TLSLogErrorEvent(TLS_E_INCOMPATIBLELSAVERSION);
  170. goto cleanup;
  171. }
  172. dwSize = sizeof(TLSLSASERVERID) +
  173. pLsaServerId->dwUniqueId +
  174. pLsaServerId->dwServerPid +
  175. pLsaServerId->dwServerSPK +
  176. pLsaServerId->dwExtensions;
  177. if(dwSize != dwLsaServerId)
  178. {
  179. dwStatus = ERROR_INVALID_PARAMETER;
  180. goto cleanup;
  181. }
  182. if(pLsaServerId->dwVersion != TLSERVER_SERVER_ID_VERSION)
  183. {
  184. dwStatus = ERROR_INVALID_PARAMETER;
  185. goto cleanup;
  186. }
  187. *pcbServerUniqueId = pLsaServerId->dwUniqueId;
  188. *pcbServerPid = pLsaServerId->dwServerPid;
  189. *pcbServerSPK = pLsaServerId->dwServerSPK;
  190. if(pLsaServerId->dwUniqueId != 0)
  191. {
  192. pbUniqueId = (PBYTE)AllocateMemory(pLsaServerId->dwUniqueId);
  193. if(pbUniqueId == NULL)
  194. {
  195. dwStatus = GetLastError();
  196. goto cleanup;
  197. }
  198. }
  199. if(pLsaServerId->dwServerPid != 0)
  200. {
  201. pbPid = (PBYTE)AllocateMemory(pLsaServerId->dwServerPid);
  202. if(pbPid == NULL)
  203. {
  204. dwStatus = GetLastError();
  205. goto cleanup;
  206. }
  207. }
  208. if(pLsaServerId->dwServerSPK != 0)
  209. {
  210. pbSPK = (PBYTE)AllocateMemory(pLsaServerId->dwServerSPK);
  211. if(pbSPK == NULL)
  212. {
  213. dwStatus = GetLastError();
  214. goto cleanup;
  215. }
  216. }
  217. if(pLsaServerId->dwUniqueId)
  218. {
  219. memcpy(
  220. pbUniqueId,
  221. (PBYTE)pLsaServerId + dwOffset,
  222. pLsaServerId->dwUniqueId
  223. );
  224. }
  225. if(pLsaServerId->dwServerPid)
  226. {
  227. memcpy(
  228. pbPid,
  229. (PBYTE)pLsaServerId + dwOffset + pLsaServerId->dwUniqueId,
  230. pLsaServerId->dwServerPid
  231. );
  232. }
  233. if(pLsaServerId->dwServerSPK)
  234. {
  235. memcpy(
  236. pbSPK,
  237. (PBYTE)pLsaServerId + dwOffset + pLsaServerId->dwUniqueId + pLsaServerId->dwServerPid,
  238. pLsaServerId->dwServerSPK
  239. );
  240. }
  241. if(pLsaServerId->dwExtensions)
  242. {
  243. PBYTE pbEncodedCert;
  244. DWORD cbEncodedCert;
  245. pbEncodedCert = (PBYTE)pLsaServerId +
  246. dwOffset +
  247. pLsaServerId->dwUniqueId +
  248. pLsaServerId->dwServerPid +
  249. pLsaServerId->dwServerSPK;
  250. cbEncodedCert = pLsaServerId->dwExtensions;
  251. dwStatus = LSCryptDecodeObject(
  252. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  253. szOID_CERT_EXTENSIONS,
  254. pbEncodedCert,
  255. cbEncodedCert,
  256. 0,
  257. (VOID **)&pCertExt,
  258. &cbCertExt
  259. );
  260. }
  261. cleanup:
  262. if(dwStatus != ERROR_SUCCESS)
  263. {
  264. FreeMemory(pCertExt);
  265. FreeMemory(pbUniqueId);
  266. FreeMemory(pbPid);
  267. FreeMemory(pbSPK);
  268. }
  269. else
  270. {
  271. *pCertExtensions = pCertExt;
  272. *pcbCertExtensions = cbCertExt;
  273. *ppbServerUniqueId = pbUniqueId;
  274. *ppbServerPid = pbPid;
  275. *ppbServerSPK = pbSPK;
  276. }
  277. return dwStatus;
  278. }
  279. //////////////////////////////////////////////////////////////////
  280. DWORD
  281. LoadNtPidFromRegistry(
  282. OUT LPTSTR* ppszNtPid
  283. )
  284. /*++
  285. Abstract:
  286. Load the NT Product ID from registry key.
  287. Parameters:
  288. pdwNtPidSize : Pointer to DWORD to receive size of data return.
  289. ppbNtPid : Pointer to PBYTE to receive return data pointer.
  290. Return:
  291. Note:
  292. use AllocateMemory() macro to allocate memory.
  293. --*/
  294. {
  295. DWORD dwPidSize=0;
  296. HKEY hKey = NULL;
  297. DWORD dwStatus = ERROR_SUCCESS;
  298. if(ppszNtPid == NULL)
  299. {
  300. SetLastError(dwStatus = ERROR_INVALID_PARAMETER);
  301. goto cleanup;
  302. }
  303. *ppszNtPid = NULL;
  304. dwStatus = RegOpenKeyEx(
  305. HKEY_LOCAL_MACHINE,
  306. NTPID_REGISTRY,
  307. 0,
  308. KEY_READ, // read only
  309. &hKey
  310. );
  311. if(dwStatus != ERROR_SUCCESS)
  312. {
  313. //
  314. // If this registry key does not exist,
  315. // invalid NT installation, if we can't access it,
  316. // we are in big trouble.
  317. //
  318. goto cleanup;
  319. }
  320. dwStatus = RegQueryValueEx(
  321. hKey,
  322. NTPID_VALUE,
  323. NULL,
  324. NULL,
  325. NULL,
  326. &dwPidSize
  327. );
  328. if(dwStatus != ERROR_MORE_DATA && dwStatus != ERROR_SUCCESS)
  329. {
  330. // Big trouble.
  331. goto cleanup;
  332. }
  333. *ppszNtPid = (LPTSTR)AllocateMemory(dwPidSize + sizeof(TCHAR));
  334. if(*ppszNtPid == NULL)
  335. {
  336. dwStatus = GetLastError();
  337. goto cleanup;
  338. }
  339. dwStatus = RegQueryValueEx(
  340. hKey,
  341. NTPID_VALUE,
  342. NULL,
  343. NULL,
  344. (PBYTE)*ppszNtPid,
  345. &dwPidSize
  346. );
  347. cleanup:
  348. if(hKey != NULL)
  349. {
  350. RegCloseKey(hKey);
  351. }
  352. if(dwStatus != NULL)
  353. {
  354. FreeMemory(*ppszNtPid);
  355. }
  356. return dwStatus;
  357. }
  358. //////////////////////////////////////////////////////////////////
  359. DWORD
  360. GenerateRandomNumber(
  361. IN DWORD Seed
  362. )
  363. /*++
  364. Routine Description:
  365. Generate a random number.
  366. Arguments:
  367. Seed - Seed for random-number generator.
  368. Return Value:
  369. Returns a random number.
  370. --*/
  371. {
  372. ULONG ulSeed = Seed;
  373. // Randomize the seed some more
  374. ulSeed = RtlRandomEx(&ulSeed);
  375. return RtlRandomEx(&ulSeed);
  376. }
  377. //////////////////////////////////////////////////////////////////
  378. DWORD
  379. TLSGeneratePid(
  380. OUT LPTSTR* pszTlsPid,
  381. OUT PDWORD pcbTlsPid,
  382. OUT LPTSTR* pszTlsUniqueId,
  383. OUT PDWORD pcbTlsUniqueId
  384. )
  385. /*++
  386. Abstract:
  387. Generate a PID for License Server, License Server PID is composed of
  388. NT PID (from registry) with last 5 digit being randomly generated number.
  389. Parameter:
  390. ppbTlsPid : Pointer to PBYTE that receive the License Server PID.
  391. pcbTlsPid : Pointer to DWORD to receive size of License Server PID.
  392. ppbTlsUniqueId : Pointer to PBYTE to receive the License Server Unique Id.
  393. pcbTlsUniqueId : Pointer to DWORD to receive size of License Server's unique ID.
  394. Returns:
  395. Error code if can't access NT system PID.
  396. Note:
  397. refer to PID20 format for detail, License Server treat PID as binary data.
  398. --*/
  399. {
  400. DWORD dwStatus;
  401. DWORD dwRandomNumber;
  402. DWORD dwNtPid;
  403. LPTSTR pszNtPid = NULL;
  404. LPTSTR pszPid20Random = NULL;
  405. int index;
  406. DWORD dwMod = 1;
  407. if( pszTlsPid == NULL || pcbTlsPid == NULL ||
  408. pszTlsUniqueId == NULL || pcbTlsUniqueId == NULL )
  409. {
  410. dwStatus = ERROR_INVALID_PARAMETER;
  411. goto cleanup;
  412. }
  413. //
  414. // Load NT system PID
  415. //
  416. dwStatus = LoadNtPidFromRegistry(
  417. &pszNtPid
  418. );
  419. if(dwStatus != ERROR_SUCCESS)
  420. {
  421. goto cleanup;
  422. }
  423. pszPid20Random = (LPTSTR)AllocateMemory(
  424. (TLSUNIQUEID_SIZE + 1) * sizeof(TCHAR)
  425. );
  426. if(pszPid20Random == NULL)
  427. {
  428. dwStatus = GetLastError();
  429. goto cleanup;
  430. }
  431. for(index = 0; index < TLSUNIQUEID_SIZE; index++)
  432. {
  433. dwMod *= 10;
  434. }
  435. dwRandomNumber = GenerateRandomNumber( GetCurrentThreadId() + GetTickCount() );
  436. swprintf(
  437. pszPid20Random,
  438. _TEXT("%0*u"),
  439. TLSUNIQUEID_SIZE,
  440. dwRandomNumber % dwMod
  441. );
  442. //
  443. // overwrite last 5 digit
  444. //
  445. lstrcpy(
  446. pszNtPid + (lstrlen(pszNtPid) - TLSUNIQUEID_SIZE),
  447. pszPid20Random
  448. );
  449. *pszTlsPid = pszNtPid;
  450. *pcbTlsPid = (lstrlen(pszNtPid) + 1) * sizeof(TCHAR);
  451. *pszTlsUniqueId = pszPid20Random;
  452. *pcbTlsUniqueId = (lstrlen(pszPid20Random) + 1) * sizeof(TCHAR);
  453. cleanup:
  454. if(dwStatus != ERROR_SUCCESS)
  455. {
  456. FreeMemory(pszNtPid);
  457. FreeMemory(pszPid20Random);
  458. }
  459. return dwStatus;
  460. }