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.

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