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.

4196 lines
107 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996-1998
  5. //
  6. // File: licprot.c
  7. //
  8. // Contents: Implementation of Hydra Server License Protocol API
  9. //
  10. // History: 02-08-00 RobLeit Created
  11. //
  12. //-----------------------------------------------------------------------------
  13. #include "precomp.h"
  14. #include <rpcnterr.h>
  15. #include <lmapibuf.h>
  16. #include "licemem.inc"
  17. #include <srvdef.h>
  18. VOID
  19. LogLicensingTimeBombExpirationEvent();
  20. void
  21. ThrottleLicenseLogEvent(
  22. WORD wEventType,
  23. DWORD dwEventId,
  24. WORD cStrings,
  25. PWCHAR * apwszStrings );
  26. LICENSE_STATUS
  27. LsStatusToLicenseStatus(
  28. DWORD LsStatus,
  29. DWORD LsStatusDefault
  30. );
  31. #define LS_DISCOVERY_TIMEOUT (1*1000)
  32. // Copied from tlserver\server\srvdef.h
  33. #define PERMANENT_LICENSE_EXPIRE_DATE INT_MAX
  34. #define SECONDS_IN_A_DAY 86400 // number of seconds in a day
  35. #define TERMINAL_SERVICE_EVENT_LOG L"TermService"
  36. ///////////////////////////////////////////////////////////////////////////////
  37. //
  38. // Global variables
  39. //
  40. HANDLE g_hEventLog = NULL;
  41. BOOL g_fEventLogOpen = FALSE;
  42. CRITICAL_SECTION g_EventLogCritSec;
  43. DWORD g_dwLicenseExpirationLeeway = PERMANENT_LICENSE_LEASE_EXPIRE_LEEWAY;
  44. DWORD g_dwTerminalServerVersion;
  45. ///////////////////////////////////////////////////////////////////////////////
  46. LICENSE_STATUS
  47. InitializeProtocolLib()
  48. {
  49. LICENSE_STATUS lsStatus;
  50. //
  51. // initialize the cert util library
  52. //
  53. if (LSInitCertutilLib( 0 ))
  54. {
  55. __try
  56. {
  57. INITLOCK( &g_EventLogCritSec );
  58. }
  59. __except( EXCEPTION_EXECUTE_HANDLER )
  60. {
  61. return LICENSE_STATUS_OUT_OF_MEMORY;
  62. }
  63. g_hEventLog = RegisterEventSource( NULL, TERMINAL_SERVICE_EVENT_LOG );
  64. if (NULL != g_hEventLog)
  65. {
  66. g_fEventLogOpen = TRUE;
  67. }
  68. }
  69. else
  70. {
  71. return LICENSE_STATUS_SERVER_ABORT;
  72. }
  73. lsStatus = InitializeLicensingTimeBomb();
  74. if (lsStatus == LICENSE_STATUS_OK)
  75. {
  76. DWORD dwStatus;
  77. HKEY hKey;
  78. DWORD dwOSVersion = GetVersion();
  79. g_dwTerminalServerVersion = (DWORD)(HIBYTE(LOWORD(dwOSVersion)));
  80. g_dwTerminalServerVersion |= (DWORD)(LOBYTE(LOWORD(dwOSVersion)) << 16);
  81. dwStatus = RegCreateKeyEx(HKEY_LOCAL_MACHINE, HYDRA_SERVER_PARAM, 0,
  82. NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
  83. NULL);
  84. if (dwStatus == ERROR_SUCCESS)
  85. {
  86. DWORD dwBuffer;
  87. DWORD cbBuffer = sizeof(DWORD);
  88. dwStatus = RegQueryValueEx(hKey, PERSEAT_LEEWAY_VALUE, NULL, NULL,
  89. (LPBYTE)&dwBuffer, &cbBuffer);
  90. if (dwStatus == ERROR_SUCCESS)
  91. {
  92. g_dwLicenseExpirationLeeway = min(dwBuffer,
  93. PERMANENT_LICENSE_LEASE_EXPIRE_LEEWAY);
  94. }
  95. }
  96. }
  97. return lsStatus;
  98. }
  99. ///////////////////////////////////////////////////////////////////////////////
  100. LICENSE_STATUS
  101. ShutdownProtocolLib()
  102. {
  103. //
  104. // shut down cert util library
  105. //
  106. g_fEventLogOpen = FALSE;
  107. DeregisterEventSource( g_hEventLog );
  108. g_hEventLog = NULL;
  109. DELETELOCK(&g_EventLogCritSec);
  110. LSShutdownCertutilLib();
  111. return( LICENSE_STATUS_OK );
  112. }
  113. ///////////////////////////////////////////////////////////////////////////////
  114. LICENSE_STATUS
  115. CreateProtocolContext(
  116. IN LPLICENSE_CAPABILITIES pLicenseCap,
  117. OUT HANDLE * phContext)
  118. {
  119. LICENSE_STATUS Status;
  120. PHS_Protocol_Context pLicenseContext = NULL;
  121. //
  122. // allocate the protocol context
  123. //
  124. Status = LicenseMemoryAllocate( sizeof( HS_Protocol_Context ), &pLicenseContext );
  125. if( LICENSE_STATUS_OK != Status )
  126. {
  127. return( Status );
  128. }
  129. //
  130. // Note: InitializeCriticalSection could throw an exception during
  131. // low memory conditions.
  132. //
  133. __try
  134. {
  135. INITLOCK( &pLicenseContext->CritSec );
  136. }
  137. __except( EXCEPTION_EXECUTE_HANDLER )
  138. {
  139. #if DBG
  140. DbgPrint( "LICPROT: CreateLicenseContext: InitializeCriticalSection exception: 0x%x\n",
  141. GetExceptionCode() );
  142. #endif
  143. Status = LICENSE_STATUS_OUT_OF_MEMORY;
  144. goto error;
  145. }
  146. pLicenseContext->hLSHandle = NULL;
  147. pLicenseContext->State = INIT;
  148. pLicenseContext->dwProtocolVersion = LICENSE_HIGHEST_PROTOCOL_VERSION;
  149. pLicenseContext->fAuthenticateServer = TRUE;
  150. pLicenseContext->CertTypeUsed = CERT_TYPE_INVALID;
  151. pLicenseContext->dwKeyExchangeAlg = KEY_EXCHANGE_ALG_RSA;
  152. pLicenseContext->fLoggedProtocolError = FALSE;
  153. //
  154. // Initialize the crypto context parameters
  155. //
  156. pLicenseContext->CryptoContext.dwCryptState = CRYPT_SYSTEM_STATE_INITIALIZED;
  157. pLicenseContext->CryptoContext.dwSessKeyAlg = BASIC_RC4_128;
  158. pLicenseContext->CryptoContext.dwMACAlg = MAC_MD5_SHA;
  159. if (NULL != pLicenseCap)
  160. {
  161. //
  162. // initialize the license context with the incoming data.
  163. //
  164. pLicenseContext->fAuthenticateServer = pLicenseCap->fAuthenticateServer;
  165. pLicenseContext->dwProtocolVersion = pLicenseCap->ProtocolVer;
  166. //
  167. // If the client is not authenticating the server, this means that
  168. // the client already has our certificate. But we need to know which
  169. // certificate the client has.
  170. //
  171. if( FALSE == pLicenseContext->fAuthenticateServer )
  172. {
  173. pLicenseContext->CertTypeUsed = pLicenseCap->CertType;
  174. }
  175. //
  176. // remember the client's machine name
  177. //
  178. if( pLicenseCap->pbClientName )
  179. {
  180. Status = LicenseMemoryAllocate(
  181. pLicenseCap->cbClientName,
  182. &pLicenseContext->ptszClientMachineName );
  183. if( LICENSE_STATUS_OK == Status )
  184. {
  185. //
  186. // copy the client machine name
  187. //
  188. memcpy( pLicenseContext->ptszClientMachineName,
  189. pLicenseCap->pbClientName,
  190. pLicenseCap->cbClientName );
  191. }
  192. else
  193. {
  194. goto error;
  195. }
  196. }
  197. }
  198. else
  199. {
  200. pLicenseContext->ptszClientMachineName = NULL;
  201. }
  202. *phContext = ( HANDLE )pLicenseContext;
  203. return( Status );
  204. error:
  205. //
  206. // encountered error creating context, free allocated memory before
  207. // returning
  208. //
  209. if( pLicenseContext )
  210. {
  211. if (pLicenseContext->ptszClientMachineName)
  212. {
  213. LicenseMemoryFree(&pLicenseContext->ptszClientMachineName);
  214. }
  215. LicenseMemoryFree( &pLicenseContext );
  216. }
  217. return( Status );
  218. }
  219. ///////////////////////////////////////////////////////////////////////////////
  220. LICENSE_STATUS
  221. DeleteProtocolContext(
  222. HANDLE hContext )
  223. {
  224. PHS_Protocol_Context pLicenseContext = ( PHS_Protocol_Context )hContext;
  225. if( NULL == pLicenseContext )
  226. {
  227. return( LICENSE_STATUS_INVALID_SERVER_CONTEXT );
  228. }
  229. LOCK( &pLicenseContext->CritSec );
  230. if (pLicenseContext->hLSHandle != NULL)
  231. {
  232. TLSDisconnectFromServer(pLicenseContext->hLSHandle);
  233. pLicenseContext->hLSHandle = NULL;
  234. }
  235. if( pLicenseContext->ProductInfo.pbCompanyName )
  236. {
  237. LicenseMemoryFree( &pLicenseContext->ProductInfo.pbCompanyName );
  238. }
  239. if( pLicenseContext->ProductInfo.pbProductID )
  240. {
  241. LicenseMemoryFree( &pLicenseContext->ProductInfo.pbProductID );
  242. }
  243. if( pLicenseContext->ptszClientUserName )
  244. {
  245. LicenseMemoryFree( &pLicenseContext->ptszClientUserName );
  246. }
  247. if( pLicenseContext->ptszClientMachineName )
  248. {
  249. LicenseMemoryFree( &pLicenseContext->ptszClientMachineName );
  250. }
  251. if( pLicenseContext->pbOldLicense )
  252. {
  253. LicenseMemoryFree( &pLicenseContext->pbOldLicense );
  254. }
  255. //
  256. // Free the license info that's being cached
  257. //
  258. if( pLicenseContext->pTsLicenseInfo )
  259. {
  260. LicenseMemoryFree( &pLicenseContext->pTsLicenseInfo );
  261. }
  262. UNLOCK( &pLicenseContext->CritSec );
  263. DELETELOCK( &pLicenseContext->CritSec );
  264. LicenseMemoryFree( &pLicenseContext );
  265. return( LICENSE_STATUS_OK );
  266. }
  267. ///////////////////////////////////////////////////////////////////////////////
  268. void
  269. HandleErrorCondition(
  270. PHS_Protocol_Context pLicenseContext,
  271. PDWORD pcbOutBuf,
  272. PBYTE * ppOutBuf,
  273. LICENSE_STATUS * pStatus )
  274. {
  275. License_Error_Message ErrorMsg;
  276. LICENSE_STATUS licenseStatus;
  277. //
  278. // returns the correct error code based on the error condition
  279. //
  280. switch( *pStatus )
  281. {
  282. case( LICENSE_STATUS_NO_LICENSE_SERVER ):
  283. ErrorMsg.dwErrorCode = GM_HS_ERR_NO_LICENSE_SERVER;
  284. ErrorMsg.dwStateTransition = ST_NO_TRANSITION;
  285. break;
  286. case( LICENSE_STATUS_INVALID_MAC_DATA ):
  287. ErrorMsg.dwErrorCode = GM_HC_ERR_INVALID_MAC;
  288. ErrorMsg.dwStateTransition = ST_TOTAL_ABORT;
  289. break;
  290. //
  291. // Handle all other error conditions as invalid client
  292. //
  293. case( LICENSE_STATUS_INVALID_RESPONSE ):
  294. default:
  295. ErrorMsg.dwErrorCode = GM_HS_ERR_INVALID_CLIENT;
  296. ErrorMsg.dwStateTransition = ST_TOTAL_ABORT;
  297. break;
  298. }
  299. //
  300. // for now, we are not sending any error string
  301. //
  302. ErrorMsg.bbErrorInfo.wBlobLen = 0;
  303. ErrorMsg.bbErrorInfo.pBlob = NULL;
  304. //
  305. // pack the error message
  306. //
  307. licenseStatus = PackHydraServerErrorMessage(
  308. pLicenseContext->dwProtocolVersion,
  309. &ErrorMsg,
  310. ppOutBuf,
  311. pcbOutBuf );
  312. if( LICENSE_STATUS_OK != licenseStatus )
  313. {
  314. #if DBG
  315. DbgPrint( "HandleErrorConditions: cannot pack error message: 0x%x\n", *pStatus );
  316. #endif
  317. *pStatus = LICENSE_STATUS_SERVER_ABORT;
  318. }
  319. return;
  320. }
  321. ///////////////////////////////////////////////////////////////////////////////
  322. LICENSE_STATUS
  323. CreateHydraServerHello(
  324. PHS_Protocol_Context pLicenseContext,
  325. DWORD cbInBuf,
  326. PBYTE pInBuf,
  327. DWORD * pcbOutBuf,
  328. PBYTE * ppOutBuf )
  329. {
  330. Hydra_Server_License_Request LicenseRequest;
  331. LICENSE_STATUS Status;
  332. Binary_Blob ScopeBlob;
  333. CHAR szScope[] = SCOPE_NAME;
  334. DWORD dwCertSize;
  335. //
  336. // generate a server random number
  337. //
  338. GenerateRandomBits( LicenseRequest.ServerRandom, LICENSE_RANDOM );
  339. memcpy( pLicenseContext->CryptoContext.rgbServerRandom,
  340. LicenseRequest.ServerRandom,
  341. LICENSE_RANDOM );
  342. //
  343. // fill in the product info. Allocate memory for and initialize the
  344. // license context copy of the product info and then just copy the
  345. // same product info to the license request.
  346. // NOTE: This info should probably be passed in in the future
  347. //
  348. Status = InitProductInfo(
  349. &( pLicenseContext->ProductInfo ),
  350. PRODUCT_INFO_SKU_PRODUCT_ID );
  351. if( LICENSE_STATUS_OK != Status )
  352. {
  353. #if DBG
  354. DbgPrint( "CreateHydraServerHello: cannot init product info: 0x%x\n", Status );
  355. #endif
  356. goto no_request;
  357. }
  358. memcpy( &LicenseRequest.ProductInfo,
  359. &pLicenseContext->ProductInfo,
  360. sizeof( Product_Info ) );
  361. //
  362. // get the hydra server certificate and fill in the key exchange list
  363. //
  364. LicenseRequest.KeyExchngList.wBlobType = BB_KEY_EXCHG_ALG_BLOB;
  365. LicenseRequest.KeyExchngList.wBlobLen = sizeof( DWORD );
  366. LicenseRequest.KeyExchngList.pBlob = ( PBYTE )&pLicenseContext->dwKeyExchangeAlg;
  367. LicenseRequest.ServerCert.pBlob = NULL;
  368. LicenseRequest.ServerCert.wBlobLen = 0;
  369. //
  370. // We may or may not have to send the client the certificate depending on whether the
  371. // client is authenticating the server.
  372. //
  373. if( TRUE == pLicenseContext->fAuthenticateServer )
  374. {
  375. //
  376. // decide on what kind of certificate to get depending on the client's version.
  377. // Pre-Hydra 5.0 clients only knows how to decode proprietory certificate.
  378. // Use X509 certificate for all other clients.
  379. //
  380. if( CERT_TYPE_INVALID == pLicenseContext->CertTypeUsed )
  381. {
  382. if( PREAMBLE_VERSION_3_0 > GET_PREAMBLE_VERSION( pLicenseContext->dwProtocolVersion ) )
  383. {
  384. pLicenseContext->CertTypeUsed = CERT_TYPE_PROPRIETORY;
  385. }
  386. else
  387. {
  388. pLicenseContext->CertTypeUsed = CERT_TYPE_X509;
  389. }
  390. }
  391. Status = TLSGetTSCertificate(
  392. pLicenseContext->CertTypeUsed,
  393. &LicenseRequest.ServerCert.pBlob,
  394. &dwCertSize);
  395. LicenseRequest.ServerCert.wBlobLen = LOWORD(dwCertSize);
  396. LicenseRequest.ServerCert.wBlobType = BB_CERTIFICATE_BLOB;
  397. if( ( LICENSE_STATUS_OK != Status ) &&
  398. ( CERT_TYPE_X509 == pLicenseContext->CertTypeUsed ) )
  399. {
  400. //
  401. // if we cannot get the X509 certificate chain, use the proprietory
  402. // certificate.
  403. //
  404. pLicenseContext->CertTypeUsed = CERT_TYPE_PROPRIETORY;
  405. Status = TLSGetTSCertificate(
  406. pLicenseContext->CertTypeUsed,
  407. &LicenseRequest.ServerCert.pBlob,
  408. &dwCertSize);
  409. LicenseRequest.ServerCert.wBlobLen = LOWORD(dwCertSize);
  410. LicenseRequest.ServerCert.wBlobType = BB_CERTIFICATE_BLOB;
  411. }
  412. if( LICENSE_STATUS_OK != Status )
  413. {
  414. #if DBG
  415. DbgPrint( "LICPROT: cannot get server certificate: %x\n", Status );
  416. #endif
  417. goto no_request;
  418. }
  419. }
  420. //
  421. // fill in the scope info. This info may be passed in in the future.
  422. //
  423. LicenseRequest.ScopeList.dwScopeCount = 1;
  424. LicenseRequest.ScopeList.Scopes = &ScopeBlob;
  425. ScopeBlob.wBlobType = BB_SCOPE_BLOB;
  426. ScopeBlob.pBlob = szScope;
  427. ScopeBlob.wBlobLen = strlen( ScopeBlob.pBlob ) + 1;
  428. strcpy( pLicenseContext->Scope, ScopeBlob.pBlob );
  429. //
  430. // Pack the server hello message into network format
  431. //
  432. Status = PackHydraServerLicenseRequest(
  433. pLicenseContext->dwProtocolVersion,
  434. &LicenseRequest,
  435. ppOutBuf,
  436. pcbOutBuf );
  437. //
  438. // free the memory containing the server certificate
  439. //
  440. if( LicenseRequest.ServerCert.pBlob )
  441. {
  442. TLSFreeTSCertificate( LicenseRequest.ServerCert.pBlob );
  443. LicenseRequest.ServerCert.pBlob = NULL;
  444. }
  445. if( LICENSE_STATUS_OK != Status )
  446. {
  447. goto no_request;
  448. }
  449. Status = LICENSE_STATUS_CONTINUE;
  450. //
  451. // change the state of the context
  452. //
  453. pLicenseContext->State = SENT_SERVER_HELLO;
  454. return( Status );
  455. //=========================================================================
  456. // Error return
  457. //=========================================================================
  458. no_request:
  459. //
  460. // free memory and handles
  461. //
  462. if( pLicenseContext->ProductInfo.pbCompanyName )
  463. {
  464. LicenseMemoryFree( &pLicenseContext->ProductInfo.pbCompanyName );
  465. }
  466. if( pLicenseContext->ProductInfo.pbProductID )
  467. {
  468. LicenseMemoryFree( &pLicenseContext->ProductInfo.pbProductID );
  469. }
  470. return( Status );
  471. }
  472. ///////////////////////////////////////////////////////////////////////////////
  473. LICENSE_STATUS
  474. HandleHelloResponse(
  475. PHS_Protocol_Context pLicenseContext,
  476. DWORD cbInBuf,
  477. PBYTE pInBuf,
  478. DWORD * pcbOutBuf,
  479. PBYTE * ppOutBuf )
  480. {
  481. PPreamble pPreamble;
  482. ASSERT( NULL != pInBuf );
  483. ASSERT( cbInBuf > sizeof( Preamble ) );
  484. if( ( NULL == pInBuf ) || ( sizeof( Preamble ) > cbInBuf ) )
  485. {
  486. return( LICENSE_STATUS_INVALID_INPUT );
  487. }
  488. //
  489. // check the message preamble to determine how to unpack the message
  490. //
  491. pPreamble = ( PPreamble )pInBuf;
  492. if( HC_LICENSE_INFO == pPreamble->bMsgType )
  493. {
  494. //
  495. // Client has sent us its license
  496. //
  497. return( HandleClientLicense( pLicenseContext, cbInBuf, pInBuf, pcbOutBuf, ppOutBuf ) );
  498. }
  499. else if( HC_NEW_LICENSE_REQUEST == pPreamble->bMsgType )
  500. {
  501. //
  502. // Client has requested for a new license
  503. //
  504. return( HandleNewLicenseRequest( pLicenseContext, cbInBuf, pInBuf, pcbOutBuf, ppOutBuf ) );
  505. }
  506. else if( GM_ERROR_ALERT == pPreamble->bMsgType )
  507. {
  508. //
  509. // Client has encountered an error
  510. //
  511. return( HandleClientError( pLicenseContext, cbInBuf, pInBuf, pcbOutBuf, ppOutBuf ) );
  512. }
  513. //
  514. // The client response is invalid for the current server state
  515. //
  516. return( LICENSE_STATUS_INVALID_RESPONSE );
  517. }
  518. ///////////////////////////////////////////////////////////////////////////////
  519. LICENSE_STATUS
  520. ChooseLicense(
  521. PValidation_Info pValidationInfo,
  522. DWORD dwNumLicenses,
  523. LICENSEDPRODUCT * pLicenseInfo,
  524. LPDWORD pdwLicenseIndex,
  525. BOOL fMatchingVersion )
  526. {
  527. DWORD
  528. dwCurrentLicense,
  529. dwProductVersion;
  530. LICENSEDPRODUCT *
  531. pCurrentLicense = pLicenseInfo;
  532. BOOL
  533. fFoundLicense = FALSE;
  534. if( ( 0 >= dwNumLicenses ) || ( NULL == pLicenseInfo ) || ( NULL == pdwLicenseIndex ) )
  535. {
  536. return( LICENSE_STATUS_INVALID_INPUT );
  537. }
  538. //
  539. // Find a license with the license array that matches the criteria.
  540. // The caller may be looking for a license that matches the current product
  541. // version, or for a license that is later than the current product version.
  542. //
  543. for( dwCurrentLicense = 0; dwCurrentLicense < dwNumLicenses; dwCurrentLicense++ )
  544. {
  545. if( TERMSERV_CERT_VERSION_BETA == pCurrentLicense->dwLicenseVersion )
  546. {
  547. continue;
  548. }
  549. dwProductVersion = pCurrentLicense->pLicensedVersion->wMajorVersion;
  550. dwProductVersion <<= 16;
  551. dwProductVersion |= pCurrentLicense->pLicensedVersion->wMinorVersion;
  552. if( fMatchingVersion )
  553. {
  554. //
  555. // we should be looking for a license with a matching version
  556. //
  557. if( dwProductVersion == pValidationInfo->pProductInfo->dwVersion )
  558. {
  559. fFoundLicense = TRUE;
  560. break;
  561. }
  562. }
  563. else
  564. {
  565. //
  566. // Looking for a license that is later than the current product
  567. // version.
  568. //
  569. if( dwProductVersion > pValidationInfo->pProductInfo->dwVersion )
  570. {
  571. fFoundLicense = TRUE;
  572. break;
  573. }
  574. }
  575. //
  576. // continue looking for the license
  577. //
  578. pCurrentLicense++;
  579. }
  580. if( FALSE == fFoundLicense )
  581. {
  582. return( LICENSE_STATUS_NO_LICENSE_ERROR );
  583. }
  584. *pdwLicenseIndex = dwCurrentLicense;
  585. return( LICENSE_STATUS_OK );
  586. }
  587. ///////////////////////////////////////////////////////////////////////////////
  588. VOID
  589. UpdateVerifyResult(
  590. LICENSE_STATUS * pCurrentStatus,
  591. LICENSE_STATUS NewStatus )
  592. {
  593. //
  594. // Update the current status with the best result so far.
  595. // The ratings of the license verification result are as follows:
  596. //
  597. // (1) LICENSE_STATUS_OK
  598. // (2) LICENSE_STATUS_SHOULD_UPGRADE_LICENSE
  599. // (3) LICENSE_STATUS_MUST_UPGRADE_LICENSE
  600. // (4) Other LICENSE_STATUS_xxx
  601. //
  602. if( LICENSE_STATUS_OK == *pCurrentStatus )
  603. {
  604. return;
  605. }
  606. else if( LICENSE_STATUS_OK == NewStatus )
  607. {
  608. *pCurrentStatus = NewStatus;
  609. return;
  610. }
  611. if( LICENSE_STATUS_SHOULD_UPGRADE_LICENSE == *pCurrentStatus )
  612. {
  613. return;
  614. }
  615. else if( LICENSE_STATUS_SHOULD_UPGRADE_LICENSE == NewStatus )
  616. {
  617. *pCurrentStatus = NewStatus;
  618. return;
  619. }
  620. if( LICENSE_STATUS_MUST_UPGRADE_LICENSE == *pCurrentStatus )
  621. {
  622. return;
  623. }
  624. else if( LICENSE_STATUS_MUST_UPGRADE_LICENSE == NewStatus )
  625. {
  626. *pCurrentStatus = NewStatus;
  627. return;
  628. }
  629. *pCurrentStatus = NewStatus;
  630. return;
  631. }
  632. /*++
  633. Function:
  634. FreeTsLicenseInfo
  635. Description:
  636. Release all the memory used in the given TS_LICENSE_INFO structure
  637. Parameter:
  638. pTsLicenseInfo - Pointer to a TS_LICENSE_INFO structure
  639. Return:
  640. Nothing.
  641. --*/
  642. VOID
  643. FreeTsLicenseInfo(
  644. PTS_LICENSE_INFO pTsLicenseInfo )
  645. {
  646. if( NULL == pTsLicenseInfo )
  647. {
  648. return;
  649. }
  650. if( pTsLicenseInfo->pbRawLicense )
  651. {
  652. LicenseMemoryFree( &pTsLicenseInfo->pbRawLicense );
  653. }
  654. //
  655. // release all memory within the structure
  656. //
  657. memset( pTsLicenseInfo, 0, sizeof( TS_LICENSE_INFO ) );
  658. return;
  659. }
  660. /*++
  661. Function:
  662. CacheLicenseInfo
  663. Description:
  664. Cache the client licensing info
  665. Parameters:
  666. pLicenseContext - Pointer to license protocol context
  667. pCurrentLicense - Pointer to the license info to cache
  668. Returns:
  669. nothing.
  670. --*/
  671. VOID
  672. CacheLicenseInfo(
  673. PHS_Protocol_Context pLicenseContext,
  674. PLICENSEDPRODUCT pCurrentLicense )
  675. {
  676. LICENSE_STATUS
  677. Status;
  678. //
  679. // free the old information in the cache
  680. //
  681. if( pLicenseContext->pTsLicenseInfo )
  682. {
  683. FreeTsLicenseInfo( pLicenseContext->pTsLicenseInfo );
  684. }
  685. else
  686. {
  687. Status = LicenseMemoryAllocate( sizeof( TS_LICENSE_INFO ), &pLicenseContext->pTsLicenseInfo );
  688. if( LICENSE_STATUS_OK != Status )
  689. {
  690. #if DBG
  691. DbgPrint( "LICEMGR: CacheLicenseInfo: cannot allocate memory for license info cache\n" );
  692. #endif
  693. return;
  694. }
  695. }
  696. //
  697. // decide if the license is temporary
  698. //
  699. if( pCurrentLicense->pLicensedVersion->dwFlags & 0x80000000 )
  700. {
  701. pLicenseContext->pTsLicenseInfo->fTempLicense = TRUE;
  702. }
  703. else
  704. {
  705. pLicenseContext->pTsLicenseInfo->fTempLicense = FALSE;
  706. }
  707. //
  708. // cache license validity dates
  709. //
  710. pLicenseContext->pTsLicenseInfo->NotAfter = pCurrentLicense->NotAfter;
  711. return;
  712. }
  713. ///////////////////////////////////////////////////////////////////////////////
  714. LICENSE_STATUS
  715. ValidateHydraLicense(
  716. PHS_Protocol_Context pLicenseContext,
  717. PValidation_Info pValidationInfo,
  718. DWORD dwNumLicenses,
  719. PLICENSEDPRODUCT pLicenseInfo,
  720. PDWORD pdwLicenseState )
  721. {
  722. LICENSE_STATUS
  723. Status = LICENSE_STATUS_INVALID_LICENSE,
  724. CurrentStatus;
  725. DWORD
  726. dwLicenseIndex = 0,
  727. dwCurrentLicense = 0;
  728. PLICENSEDPRODUCT
  729. pCurrentLicense;
  730. BOOL
  731. fFoundMatchingVersion = FALSE;
  732. //
  733. // The client could have given us multiple licenses. Pick the right
  734. // license from the array of licenses to validate. Always try to pick
  735. // the license that matches the current product version before looking
  736. // for a license that is for a later version.
  737. //
  738. CurrentStatus = ChooseLicense(
  739. pValidationInfo,
  740. dwNumLicenses,
  741. pLicenseInfo,
  742. &dwLicenseIndex,
  743. TRUE );
  744. if( LICENSE_STATUS_OK == CurrentStatus )
  745. {
  746. //
  747. // Verify the license that is the same version as the current product
  748. // version
  749. // initialize the license state
  750. //
  751. LicenseInitState( *pdwLicenseState );
  752. pCurrentLicense = pLicenseInfo + dwLicenseIndex;
  753. fFoundMatchingVersion = TRUE;
  754. //
  755. // verify HWID
  756. //
  757. CurrentStatus = VerifyClientHwid( pLicenseContext, pValidationInfo, pCurrentLicense );
  758. if( LICENSE_STATUS_OK != CurrentStatus )
  759. {
  760. UpdateVerifyResult( &Status, CurrentStatus );
  761. goto verify_later_license;
  762. }
  763. //
  764. // verify product info. Also verifies the product version.
  765. // The product version determines if the license needs to be
  766. // upgraded or not.
  767. //
  768. CurrentStatus = VerifyLicenseProductInfo(
  769. pLicenseContext,
  770. pValidationInfo,
  771. pCurrentLicense,
  772. pdwLicenseState );
  773. if( LICENSE_STATUS_OK != CurrentStatus )
  774. {
  775. UpdateVerifyResult( &Status, CurrentStatus );
  776. goto verify_later_license;
  777. }
  778. //
  779. // verify license valid date and time. This validation is only
  780. // needed if it is a temporary license
  781. //
  782. CurrentStatus = VerifyLicenseDateAndTime( pCurrentLicense, pdwLicenseState );
  783. if( LICENSE_STATUS_OK != CurrentStatus )
  784. {
  785. UpdateVerifyResult( &Status, CurrentStatus );
  786. goto verify_later_license;
  787. }
  788. CurrentStatus = GetVerifyResult( *pdwLicenseState );
  789. UpdateVerifyResult( &Status, CurrentStatus );
  790. //
  791. // cache the license we tried to validate
  792. //
  793. CacheLicenseInfo( pLicenseContext, pCurrentLicense );
  794. //
  795. // If the current license is OK, then we're done verifying
  796. //
  797. if( LICENSE_STATUS_OK == Status )
  798. {
  799. return( Status );
  800. }
  801. }
  802. verify_later_license:
  803. //
  804. // Cannot find or did not sucessfully verify a license that matches the current
  805. // product version. The following code finds and verifies licenses that
  806. // are later than the current product version.
  807. //
  808. CurrentStatus = ChooseLicense(
  809. pValidationInfo,
  810. dwNumLicenses,
  811. pLicenseInfo,
  812. &dwLicenseIndex,
  813. FALSE );
  814. if( LICENSE_STATUS_OK != CurrentStatus )
  815. {
  816. if( FALSE == fFoundMatchingVersion )
  817. {
  818. //
  819. // cannot find a license that is the same or later than the current
  820. // product version ==> this license must be upgraded.
  821. //
  822. LicenseSetState( *pdwLicenseState, LICENSE_STATE_OLD_VERSION );
  823. return( GetVerifyResult( *pdwLicenseState ) );
  824. }
  825. else
  826. {
  827. return( Status );
  828. }
  829. }
  830. pCurrentLicense = pLicenseInfo + dwLicenseIndex;
  831. dwCurrentLicense = dwLicenseIndex;
  832. while( dwCurrentLicense < dwNumLicenses )
  833. {
  834. //
  835. // initialize the license state
  836. //
  837. LicenseInitState( *pdwLicenseState );
  838. //
  839. // verify HWID
  840. //
  841. CurrentStatus = VerifyClientHwid( pLicenseContext, pValidationInfo, pCurrentLicense );
  842. if( LICENSE_STATUS_OK != CurrentStatus )
  843. {
  844. UpdateVerifyResult( &Status, CurrentStatus );
  845. goto next_license;
  846. }
  847. //
  848. // verify product info. Also verifies the product version.
  849. // The product version determines if the license needs to be
  850. // upgraded or not.
  851. //
  852. CurrentStatus = VerifyLicenseProductInfo(
  853. pLicenseContext,
  854. pValidationInfo,
  855. pCurrentLicense,
  856. pdwLicenseState );
  857. if( LICENSE_STATUS_OK != CurrentStatus )
  858. {
  859. UpdateVerifyResult( &Status, CurrentStatus );
  860. goto next_license;
  861. }
  862. //
  863. // verify license valid date and time. This validation is only
  864. // needed if it is a temporary license
  865. //
  866. CurrentStatus = VerifyLicenseDateAndTime( pCurrentLicense, pdwLicenseState );
  867. if( LICENSE_STATUS_OK != CurrentStatus )
  868. {
  869. UpdateVerifyResult( &Status, CurrentStatus );
  870. goto next_license;
  871. }
  872. CurrentStatus = GetVerifyResult( *pdwLicenseState );
  873. UpdateVerifyResult( &Status, CurrentStatus );
  874. //
  875. // cache the info of the license we had just try to validate
  876. //
  877. CacheLicenseInfo( pLicenseContext, pCurrentLicense );
  878. if( LICENSE_STATUS_OK == Status )
  879. {
  880. //
  881. // if the license is OK, then we can stop the verification process
  882. //
  883. break;
  884. }
  885. next_license:
  886. //
  887. // Get the next license that is later than the current product version.
  888. //
  889. if( dwNumLicenses <= ++dwCurrentLicense )
  890. {
  891. break;
  892. }
  893. pCurrentLicense++;
  894. CurrentStatus = ChooseLicense(
  895. pValidationInfo,
  896. dwNumLicenses - dwCurrentLicense,
  897. pCurrentLicense,
  898. &dwLicenseIndex,
  899. FALSE );
  900. if( LICENSE_STATUS_OK != CurrentStatus )
  901. {
  902. break;
  903. }
  904. pCurrentLicense += dwLicenseIndex;
  905. dwCurrentLicense += dwLicenseIndex;
  906. }
  907. return( Status );
  908. }
  909. ///////////////////////////////////////////////////////////////////////////////
  910. LICENSE_STATUS
  911. ValidateLicense(
  912. PHS_Protocol_Context pLicenseContext,
  913. PValidation_Info pValidationInfo,
  914. PDWORD pdwLicenseState,
  915. BOOL fCheckForPermanent )
  916. {
  917. LICENSE_STATUS Status;
  918. DWORD dwNumLicenseInfo = 0;
  919. LICENSEDPRODUCT * pLicenseInfo = NULL;
  920. static DWORD cchComputerName;
  921. static TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
  922. DWORD cbSecretKey = 0;
  923. PBYTE pbSecretKey = NULL;
  924. if( NULL == pLicenseContext )
  925. {
  926. return( LICENSE_STATUS_INVALID_INPUT );
  927. }
  928. //
  929. // Get the secret key that is used to encrypt the HWID
  930. //
  931. LicenseGetSecretKey( &cbSecretKey, NULL );
  932. Status = LicenseMemoryAllocate( cbSecretKey, &pbSecretKey );
  933. if( LICENSE_STATUS_OK != Status )
  934. {
  935. goto done;
  936. }
  937. Status = LicenseGetSecretKey( &cbSecretKey, pbSecretKey );
  938. if( LICENSE_STATUS_OK != Status )
  939. {
  940. goto done;
  941. }
  942. //
  943. // decode license issued by hydra license server certificate engine.
  944. // Decoding the license will also get us back the decrypted HWID.
  945. //
  946. __try
  947. {
  948. Status = LSVerifyDecodeClientLicense(
  949. pValidationInfo->pLicense,
  950. pValidationInfo->cbLicense,
  951. pbSecretKey,
  952. cbSecretKey,
  953. &dwNumLicenseInfo,
  954. NULL );
  955. if( LICENSE_STATUS_OK != Status )
  956. {
  957. goto done;
  958. }
  959. Status = LicenseMemoryAllocate(
  960. sizeof( LICENSEDPRODUCT ) * dwNumLicenseInfo,
  961. &pLicenseInfo );
  962. if( LICENSE_STATUS_OK != Status )
  963. {
  964. goto done;
  965. }
  966. Status = LSVerifyDecodeClientLicense(
  967. pValidationInfo->pLicense,
  968. pValidationInfo->cbLicense,
  969. pbSecretKey,
  970. cbSecretKey,
  971. &dwNumLicenseInfo,
  972. pLicenseInfo );
  973. }
  974. __except( EXCEPTION_EXECUTE_HANDLER )
  975. {
  976. DWORD dwExceptionCode = GetExceptionCode();
  977. Status = LICENSE_STATUS_CANNOT_DECODE_LICENSE;
  978. }
  979. if( LICENSE_STATUS_OK != Status )
  980. {
  981. #if DBG
  982. DbgPrint( "LICEMGR: cannot decode license: 0x%x\n", Status );
  983. #endif
  984. goto done;
  985. }
  986. //
  987. // now validate the license
  988. //
  989. Status = ValidateHydraLicense(
  990. pLicenseContext,
  991. pValidationInfo,
  992. dwNumLicenseInfo,
  993. pLicenseInfo,
  994. pdwLicenseState );
  995. if (fCheckForPermanent
  996. && LICENSE_STATUS_OK == Status
  997. && !pLicenseContext->pTsLicenseInfo->fTempLicense
  998. && pLicenseContext->ProductInfo.cbProductID >= sizeof(TERMSERV_FREE_TYPE))
  999. {
  1000. int i;
  1001. TCHAR *pszT;
  1002. for (i = 0, pszT = (TCHAR *)(pLicenseContext->ProductInfo.pbProductID + pLicenseContext->ProductInfo.cbProductID - sizeof(TERMSERV_FREE_TYPE)); i < sizeof(TERMSERV_FREE_TYPE); i++)
  1003. {
  1004. if (TERMSERV_FREE_TYPE[i] != pszT[i])
  1005. goto done;
  1006. }
  1007. ReceivedPermanentLicense();
  1008. }
  1009. done:
  1010. if( pbSecretKey )
  1011. {
  1012. LicenseMemoryFree( &pbSecretKey );
  1013. }
  1014. //
  1015. // Free the array of licensed product info
  1016. //
  1017. if( pLicenseInfo )
  1018. {
  1019. while( dwNumLicenseInfo-- )
  1020. {
  1021. LSFreeLicensedProduct( pLicenseInfo + dwNumLicenseInfo );
  1022. }
  1023. LicenseMemoryFree( &pLicenseInfo );
  1024. }
  1025. return( Status );
  1026. }
  1027. ///////////////////////////////////////////////////////////////////////////////
  1028. LICENSE_STATUS
  1029. HandleClientLicense(
  1030. PHS_Protocol_Context pLicenseContext,
  1031. DWORD cbInBuf,
  1032. PBYTE pInBuf,
  1033. DWORD * pcbOutBuf,
  1034. PBYTE * ppOutBuf )
  1035. {
  1036. LICENSE_STATUS Status, UpgradeStatus;
  1037. Hydra_Client_License_Info LicenseInfo;
  1038. PBYTE pPreMasterSecret = NULL;
  1039. DWORD dwPreMasterSecretLen = 0;
  1040. HWID Hwid;
  1041. Validation_Info ValidationInfo;
  1042. License_Error_Message ErrorMsg;
  1043. DWORD dwLicenseState = 0;
  1044. BYTE MacData[LICENSE_MAC_DATA];
  1045. DWORD CertType;
  1046. ASSERT( NULL != pInBuf );
  1047. ASSERT( cbInBuf > 0 );
  1048. if( ( NULL == pInBuf ) || ( 0 >= cbInBuf ) )
  1049. {
  1050. return( LICENSE_STATUS_INVALID_INPUT );
  1051. }
  1052. //
  1053. // Unpack the client license info message
  1054. //
  1055. InitBinaryBlob( &LicenseInfo.EncryptedPreMasterSecret );
  1056. InitBinaryBlob( &LicenseInfo.LicenseInfo );
  1057. InitBinaryBlob( &LicenseInfo.EncryptedHWID );
  1058. Status = UnPackHydraClientLicenseInfo( pInBuf, cbInBuf, &LicenseInfo );
  1059. if( LICENSE_STATUS_OK != Status )
  1060. {
  1061. goto construct_return_msg;
  1062. }
  1063. //
  1064. // Initialize the crypto context with the key exchange info and build the pre-master
  1065. // secret. We need the server and client random numbers and the pre-master secret
  1066. // to build the pre-master secret.
  1067. //
  1068. memcpy( pLicenseContext->CryptoContext.rgbClientRandom,
  1069. LicenseInfo.ClientRandom,
  1070. LICENSE_RANDOM );
  1071. pLicenseContext->CryptoContext.dwKeyExchAlg = LicenseInfo.dwPrefKeyExchangeAlg;
  1072. dwPreMasterSecretLen = LICENSE_PRE_MASTER_SECRET;
  1073. Status = GetEnvelopedData( pLicenseContext->CertTypeUsed,
  1074. LicenseInfo.EncryptedPreMasterSecret.pBlob,
  1075. ( DWORD )LicenseInfo.EncryptedPreMasterSecret.wBlobLen,
  1076. &pPreMasterSecret,
  1077. &dwPreMasterSecretLen );
  1078. if( LICENSE_STATUS_OK != Status )
  1079. {
  1080. if (Status == LICENSE_STATUS_INVALID_INPUT)
  1081. {
  1082. Status = LICENSE_STATUS_INVALID_RESPONSE;
  1083. }
  1084. goto construct_return_msg;
  1085. }
  1086. //
  1087. // Set the pre-master secret and generate the master secret
  1088. //
  1089. Status = LicenseSetPreMasterSecret( &pLicenseContext->CryptoContext, pPreMasterSecret );
  1090. if( LICENSE_STATUS_OK != Status )
  1091. {
  1092. goto construct_return_msg;
  1093. }
  1094. Status = LicenseBuildMasterSecret( &pLicenseContext->CryptoContext );
  1095. if( LICENSE_STATUS_OK != Status )
  1096. {
  1097. goto construct_return_msg;
  1098. }
  1099. //
  1100. // Derive the session key from the key exchange info
  1101. //
  1102. Status = LicenseMakeSessionKeys( &pLicenseContext->CryptoContext, 0 );
  1103. if( LICENSE_STATUS_OK != Status )
  1104. {
  1105. goto construct_return_msg;
  1106. }
  1107. //
  1108. // Use the session key to decrypt the HWID
  1109. //
  1110. if( LicenseInfo.EncryptedHWID.wBlobLen > sizeof(Hwid) )
  1111. {
  1112. Status = LICENSE_STATUS_INVALID_MAC_DATA;
  1113. goto construct_return_msg;
  1114. }
  1115. memcpy( &Hwid,
  1116. LicenseInfo.EncryptedHWID.pBlob,
  1117. LicenseInfo.EncryptedHWID.wBlobLen );
  1118. Status = LicenseDecryptSessionData( &pLicenseContext->CryptoContext,
  1119. ( PBYTE )&Hwid,
  1120. ( DWORD )LicenseInfo.EncryptedHWID.wBlobLen );
  1121. if( LICENSE_STATUS_OK != Status )
  1122. {
  1123. goto construct_return_msg;
  1124. }
  1125. //
  1126. // Calculate the MAC on the HWID.
  1127. //
  1128. Status = LicenseGenerateMAC( &pLicenseContext->CryptoContext,
  1129. ( PBYTE )&Hwid,
  1130. sizeof( HWID ),
  1131. MacData);
  1132. if( LICENSE_STATUS_OK != Status )
  1133. {
  1134. Status = LICENSE_STATUS_INVALID_MAC_DATA;
  1135. goto construct_return_msg;
  1136. }
  1137. //
  1138. // now verify the MAC data
  1139. //
  1140. if( 0 != memcmp( MacData, LicenseInfo.MACData, LICENSE_MAC_DATA ) )
  1141. {
  1142. Status = LICENSE_STATUS_INVALID_MAC_DATA;
  1143. goto construct_return_msg;
  1144. }
  1145. //
  1146. // keep track of the client platform ID
  1147. //
  1148. pLicenseContext->dwClientPlatformID = LicenseInfo.dwPlatformID;
  1149. //
  1150. // call the license manager to validate the license.
  1151. // For now, we don't have to fill in the product info fields
  1152. //
  1153. ValidationInfo.pValidationData = ( PBYTE )&Hwid;
  1154. ValidationInfo.cbValidationData = LICENSE_HWID_LENGTH;
  1155. ValidationInfo.pProductInfo = &pLicenseContext->ProductInfo;
  1156. ValidationInfo.pLicense = LicenseInfo.LicenseInfo.pBlob;
  1157. ValidationInfo.cbLicense = ( DWORD )LicenseInfo.LicenseInfo.wBlobLen;
  1158. Status = ValidateLicense( pLicenseContext,
  1159. &ValidationInfo,
  1160. &dwLicenseState,
  1161. FALSE // fCheckForPermanent
  1162. );
  1163. //
  1164. // If the license cannot be decoded, then it is time to issue a new license
  1165. // for the client.
  1166. //
  1167. if( LICENSE_STATUS_CANNOT_DECODE_LICENSE == Status ||
  1168. LICENSE_STATUS_INVALID_LICENSE == Status )
  1169. {
  1170. LICENSE_STATUS StatusT = IssuePlatformChallenge( pLicenseContext, pcbOutBuf, ppOutBuf );
  1171. if( LICENSE_STATUS_OK != StatusT )
  1172. {
  1173. //
  1174. // cannot obtain a platform challenge for the client
  1175. //
  1176. #if DBG
  1177. DbgPrint( "LICPROT: cannot issue platform challenge: 0x%x\n", Status );
  1178. #endif
  1179. goto construct_return_msg;
  1180. }
  1181. pLicenseContext->State = ISSUED_PLATFORM_CHALLENGE;
  1182. Status = LICENSE_STATUS_CONTINUE;
  1183. goto done;
  1184. }
  1185. #ifdef UPGRADE_LICENSE
  1186. //
  1187. // check if the license needs to be upgraded.
  1188. //
  1189. if( ( LICENSE_STATUS_MUST_UPGRADE_LICENSE == Status ) ||
  1190. ( LICENSE_STATUS_SHOULD_UPGRADE_LICENSE == Status ) )
  1191. {
  1192. //
  1193. // issue the platform challenge for upgrading a license
  1194. //
  1195. UpgradeStatus = IssuePlatformChallenge(
  1196. pLicenseContext,
  1197. pcbOutBuf,
  1198. ppOutBuf );
  1199. if( LICENSE_STATUS_OK == UpgradeStatus )
  1200. {
  1201. //
  1202. // keep track of the old license and continue with the licensing
  1203. // protocol. We will upgrade the old license when the client
  1204. // returns with the platform challenge.
  1205. //
  1206. if( pLicenseContext->pbOldLicense )
  1207. {
  1208. LicenseMemoryFree( &pLicenseContext->pbOldLicense );
  1209. }
  1210. pLicenseContext->pbOldLicense = LicenseInfo.LicenseInfo.pBlob;
  1211. pLicenseContext->cbOldLicense = LicenseInfo.LicenseInfo.wBlobLen;
  1212. pLicenseContext->State = ISSUED_PLATFORM_CHALLENGE;
  1213. Status = LICENSE_STATUS_CONTINUE;
  1214. goto done;
  1215. }
  1216. else if( LICENSE_STATUS_SHOULD_UPGRADE_LICENSE == Status )
  1217. {
  1218. //
  1219. // Let the client go through if we cannot issue a platform challenge to
  1220. // upgrade a valid license now.
  1221. //
  1222. Status = LICENSE_STATUS_OK;
  1223. goto construct_return_msg;
  1224. }
  1225. else
  1226. {
  1227. // LICENSE_STATUS_MUST_UPGRADE_LICENSE: send back the real error
  1228. Status = UpgradeStatus;
  1229. }
  1230. //
  1231. // cannot issue platform challenge to upgrade a license that is not good
  1232. // any more.
  1233. //
  1234. #if DBG
  1235. DbgPrint( "LICPROT: cannot issue platform challenge to upgrade license: 0x%x\n", Status );
  1236. #endif
  1237. }
  1238. #else
  1239. //
  1240. // we are ignoring license upgrade
  1241. //
  1242. if( LICENSE_STATUS_SHOULD_UPGRADE_LICENSE == Status )
  1243. {
  1244. //
  1245. // change the status to OK
  1246. //
  1247. Status = LICENSE_STATUS_OK;
  1248. }
  1249. #endif
  1250. //
  1251. // now construct the message to return to the client, based on the current
  1252. // status code
  1253. //
  1254. construct_return_msg:
  1255. if( LICENSE_STATUS_OK != Status )
  1256. {
  1257. //
  1258. // The current status states that the client could not be validated
  1259. // due to some error
  1260. //
  1261. #if DBG
  1262. DbgPrint( "HandleClientLicense: constructing error message: 0x%x\n", Status );
  1263. #endif
  1264. //
  1265. // handle the error condition and update our state
  1266. //
  1267. HandleErrorCondition( pLicenseContext, pcbOutBuf, ppOutBuf, &Status );
  1268. pLicenseContext->State = VALIDATION_ERROR;
  1269. if( (LICENSE_STATUS_INVALID_RESPONSE == Status)
  1270. || (LICENSE_STATUS_INVALID_MAC_DATA == Status)
  1271. || (LICENSE_STATUS_CANNOT_DECODE_LICENSE == Status)
  1272. || (LICENSE_STATUS_INVALID_LICENSE == Status) )
  1273. {
  1274. WORD wLogString = 0;
  1275. LPTSTR ptszLogString[1] = { NULL };
  1276. //
  1277. // Log the failure
  1278. //
  1279. if( pLicenseContext->ptszClientMachineName )
  1280. {
  1281. wLogString = 1;
  1282. ptszLogString[0] = pLicenseContext->ptszClientMachineName;
  1283. }
  1284. LicenseLogEvent( EVENTLOG_INFORMATION_TYPE,
  1285. EVENT_INVALID_LICENSE,
  1286. wLogString, ptszLogString );
  1287. pLicenseContext->fLoggedProtocolError = TRUE;
  1288. }
  1289. else if ((NULL != pLicenseContext->pTsLicenseInfo)
  1290. && (!pLicenseContext->fLoggedProtocolError))
  1291. {
  1292. LPTSTR ptszLogString[1] = { NULL };
  1293. if( pLicenseContext->ptszClientMachineName )
  1294. {
  1295. ptszLogString[0] = pLicenseContext->ptszClientMachineName;
  1296. }
  1297. // Couldn't renew/upgrade license
  1298. pLicenseContext->fLoggedProtocolError = TRUE;
  1299. if (pLicenseContext->pTsLicenseInfo->fTempLicense)
  1300. {
  1301. // The expired temporary license could not be upgraded
  1302. LicenseLogEvent(
  1303. EVENTLOG_INFORMATION_TYPE,
  1304. EVENT_EXPIRED_TEMPORARY_LICENSE,
  1305. 1,
  1306. ptszLogString
  1307. );
  1308. }
  1309. else
  1310. {
  1311. // The expired permanent license could not be renewed
  1312. LicenseLogEvent(
  1313. EVENTLOG_INFORMATION_TYPE,
  1314. EVENT_EXPIRED_PERMANENT_LICENSE,
  1315. 1,
  1316. ptszLogString
  1317. );
  1318. }
  1319. }
  1320. goto done;
  1321. }
  1322. //
  1323. // The license has been validated successfully, generate the message to
  1324. // return to the client
  1325. //
  1326. Status = ConstructServerResponse( pLicenseContext->dwProtocolVersion,
  1327. LICENSE_RESPONSE_VALID_CLIENT,
  1328. pcbOutBuf,
  1329. ppOutBuf );
  1330. if( LICENSE_STATUS_OK != Status )
  1331. {
  1332. #if DBG
  1333. DbgPrint( "HandleClientLicense: cannot pack error message: 0x%x\n", Status );
  1334. #endif
  1335. pLicenseContext->State = ABORTED;
  1336. Status = LICENSE_STATUS_SERVER_ABORT;
  1337. }
  1338. else
  1339. {
  1340. pLicenseContext->State = VALIDATED_LICENSE_COMPLETE;
  1341. }
  1342. done:
  1343. //
  1344. // free the memory used in the license info structure
  1345. //
  1346. FreeBinaryBlob( &LicenseInfo.EncryptedPreMasterSecret );
  1347. FreeBinaryBlob( &LicenseInfo.EncryptedHWID );
  1348. if( pLicenseContext->pbOldLicense != LicenseInfo.LicenseInfo.pBlob )
  1349. {
  1350. FreeBinaryBlob( &LicenseInfo.LicenseInfo );
  1351. }
  1352. if( pPreMasterSecret )
  1353. {
  1354. LicenseMemoryFree( &pPreMasterSecret );
  1355. }
  1356. return( Status);
  1357. }
  1358. ///////////////////////////////////////////////////////////////////////////////
  1359. LICENSE_STATUS
  1360. HandleNewLicenseRequest(
  1361. PHS_Protocol_Context pLicenseContext,
  1362. DWORD cbInBuf,
  1363. PBYTE pInBuf,
  1364. DWORD * pcbOutBuf,
  1365. PBYTE * ppOutBuf )
  1366. {
  1367. LICENSE_STATUS Status;
  1368. Hydra_Client_New_License_Request NewLicenseRequest;
  1369. PBYTE pPreMasterSecret = NULL;
  1370. DWORD dwPreMasterSecretLen = 0;
  1371. DWORD dwChallengeLen = 0;
  1372. DWORD CertType;
  1373. ASSERT( NULL != pInBuf );
  1374. ASSERT( cbInBuf > 0 );
  1375. if( ( NULL == pInBuf ) || ( 0 >= cbInBuf ) )
  1376. {
  1377. return( LICENSE_STATUS_INVALID_INPUT );
  1378. }
  1379. InitBinaryBlob( &NewLicenseRequest.EncryptedPreMasterSecret );
  1380. //
  1381. // Unpack the new license request
  1382. //
  1383. Status = UnPackHydraClientNewLicenseRequest( pInBuf, cbInBuf, &NewLicenseRequest );
  1384. if( LICENSE_STATUS_OK != Status )
  1385. {
  1386. #if DBG
  1387. DbgPrint( "LICPROT: HandleNewLicenseRequest: cannot unpack client request: 0x%x\n", Status );
  1388. #endif
  1389. return( Status );
  1390. }
  1391. //
  1392. // save the client user and machine name
  1393. //
  1394. #ifdef UNICODE
  1395. //
  1396. // convert the client's user and machine name to unicode
  1397. //
  1398. if( ( NewLicenseRequest.ClientUserName.pBlob ) &&
  1399. ( NULL == pLicenseContext->ptszClientUserName ) )
  1400. {
  1401. Status = Ascii2Wchar( NewLicenseRequest.ClientUserName.pBlob,
  1402. &pLicenseContext->ptszClientUserName );
  1403. if( LICENSE_STATUS_OK != Status )
  1404. {
  1405. #if DBG
  1406. DbgPrint( "LICPROT: HandleNewLicenseRequest: cannot convert client user name: %s to wide char: 0x%x\n",
  1407. NewLicenseRequest.ClientUserName.pBlob, Status );
  1408. #endif
  1409. }
  1410. }
  1411. if( ( NewLicenseRequest.ClientMachineName.pBlob ) &&
  1412. ( NULL == pLicenseContext->ptszClientMachineName ) )
  1413. {
  1414. Status = Ascii2Wchar( NewLicenseRequest.ClientMachineName.pBlob,
  1415. &pLicenseContext->ptszClientMachineName );
  1416. if( LICENSE_STATUS_OK != Status )
  1417. {
  1418. #if DBG
  1419. DbgPrint( "LICPROT: HandleNewLicenseRequest: cannot convert client machine name %s to wide char: 0x%x\n",
  1420. NewLicenseRequest.ClientMachineName.pBlob, Status );
  1421. #endif
  1422. }
  1423. }
  1424. #else // non-UNICODE
  1425. //
  1426. // save the client's user and machine name
  1427. //
  1428. if( ( NewLicenseRequest.ClientUserName.pBlob ) &&
  1429. ( NULL == pLicenseContext->ptszClientUserName ) )
  1430. {
  1431. Status = LicenseMemoryAllocate(
  1432. NewLicenseRequest.ClientUserName.wBlobLen,
  1433. &pLicenseContext->ptszClientUserName );
  1434. if( LICENSE_STATUS_OK != Status )
  1435. {
  1436. #if DBG
  1437. DbgPrint( "LICPROT: HandleNewLicenseRequest: cannot allocate memory for client's user name: 0x%x\n",
  1438. Status );
  1439. #endif
  1440. }
  1441. else
  1442. {
  1443. memcpy( pLicenseContext->ptszClientUserName,
  1444. NewLicenseRequest.ClientUserName.pBlob,
  1445. NewLicenseRequest.ClientUserName.wBlobLen );
  1446. }
  1447. }
  1448. if( ( NewLicenseRequest.ClientMachineName.pBlob ) &&
  1449. ( NULL == pLicenseContext->ptszClientMachineName ) )
  1450. {
  1451. Status = LicenseMemoryAllocate(
  1452. NewLicenseRequest.ClientMachineName.wBlobLen,
  1453. &pLicenseContext->ptszClientMachineName );
  1454. if( LICENSE_STATUS_OK != Status )
  1455. {
  1456. #if DBG
  1457. DbgPrint( "LICPROT: HandleNewLicenseRequest: cannot allocate memory for client's machine name: 0x%x\n",
  1458. Status );
  1459. #endif
  1460. }
  1461. else
  1462. {
  1463. memcpy( pLicenseContext->ptszClientMachineName,
  1464. NewLicenseRequest.ClientMachineName.pBlob,
  1465. NewLicenseRequest.ClientMachineName.wBlobLen );
  1466. }
  1467. }
  1468. #endif // UNICODE
  1469. //
  1470. // Initialize the crypto context with the key exchange info and build the pre-master
  1471. // secret. We need the server and client random numbers and the pre-master secret
  1472. // to build the pre-master secret.
  1473. //
  1474. memcpy( pLicenseContext->CryptoContext.rgbClientRandom,
  1475. NewLicenseRequest.ClientRandom,
  1476. LICENSE_RANDOM );
  1477. pLicenseContext->CryptoContext.dwKeyExchAlg = NewLicenseRequest.dwPrefKeyExchangeAlg;
  1478. //
  1479. // Get the pre-master secret from the enveloped data
  1480. //
  1481. Status = GetEnvelopedData( pLicenseContext->CertTypeUsed,
  1482. NewLicenseRequest.EncryptedPreMasterSecret.pBlob,
  1483. ( DWORD )NewLicenseRequest.EncryptedPreMasterSecret.wBlobLen,
  1484. &pPreMasterSecret,
  1485. &dwPreMasterSecretLen );
  1486. if( LICENSE_STATUS_OK != Status )
  1487. {
  1488. #if DBG
  1489. DbgPrint( "LICPROT: HandleNewLicenseRequest: cannot get enveloped data: 0x%x", Status );
  1490. #endif
  1491. goto done;
  1492. }
  1493. //
  1494. // set the premaster secret and generate the master secret
  1495. //
  1496. Status = LicenseSetPreMasterSecret( &pLicenseContext->CryptoContext, pPreMasterSecret );
  1497. if( LICENSE_STATUS_OK != Status )
  1498. {
  1499. goto done;
  1500. }
  1501. Status = LicenseBuildMasterSecret( &pLicenseContext->CryptoContext );
  1502. if( LICENSE_STATUS_OK != Status )
  1503. {
  1504. goto done;
  1505. }
  1506. //
  1507. // Derive the session key from the key exchange info
  1508. //
  1509. Status = LicenseMakeSessionKeys( &pLicenseContext->CryptoContext, 0 );
  1510. if( LICENSE_STATUS_OK != Status )
  1511. {
  1512. goto done;
  1513. }
  1514. //
  1515. // record the client platform ID and issue the platform challenge
  1516. //
  1517. pLicenseContext->dwClientPlatformID = NewLicenseRequest.dwPlatformID;
  1518. Status = IssuePlatformChallenge( pLicenseContext, pcbOutBuf, ppOutBuf );
  1519. if( LICENSE_STATUS_OK != Status )
  1520. {
  1521. goto done;
  1522. }
  1523. //
  1524. // update our state
  1525. //
  1526. pLicenseContext->State = ISSUED_PLATFORM_CHALLENGE;
  1527. Status = LICENSE_STATUS_CONTINUE;
  1528. done:
  1529. FreeBinaryBlob( &NewLicenseRequest.EncryptedPreMasterSecret );
  1530. FreeBinaryBlob( &NewLicenseRequest.ClientUserName );
  1531. FreeBinaryBlob( &NewLicenseRequest.ClientMachineName );
  1532. if( pPreMasterSecret )
  1533. {
  1534. LicenseMemoryFree( &pPreMasterSecret );
  1535. }
  1536. return( Status );
  1537. }
  1538. ///////////////////////////////////////////////////////////////////////////////
  1539. LICENSE_STATUS
  1540. HandleClientError(
  1541. PHS_Protocol_Context pLicenseContext,
  1542. DWORD cbInBuf,
  1543. PBYTE pInBuf,
  1544. DWORD * pcbOutBuf,
  1545. PBYTE * ppOutBuf )
  1546. {
  1547. LICENSE_STATUS Status;
  1548. License_Error_Message ClientError;
  1549. ASSERT( NULL != pInBuf );
  1550. ASSERT( cbInBuf > 0 );
  1551. if( ( NULL == pInBuf ) || ( 0 >= cbInBuf ) )
  1552. {
  1553. return( LICENSE_STATUS_INVALID_INPUT );
  1554. }
  1555. InitBinaryBlob( &ClientError.bbErrorInfo );
  1556. //
  1557. // unpack the client error
  1558. //
  1559. Status = UnPackHydraClientErrorMessage( pInBuf, cbInBuf, &ClientError );
  1560. if( LICENSE_STATUS_OK != Status )
  1561. {
  1562. return( Status );
  1563. }
  1564. //
  1565. // Process the client error code, the possible errors are:
  1566. // (1) Error processing the hydra server certificate
  1567. // (2) Client has no license and does not want one
  1568. //
  1569. // For now, just record the client error and abort the operation
  1570. //
  1571. pLicenseContext->dwClientError = ClientError.dwErrorCode;
  1572. pLicenseContext->State = ABORTED;
  1573. FreeBinaryBlob( &ClientError.bbErrorInfo );
  1574. return( LICENSE_STATUS_CLIENT_ABORT );
  1575. }
  1576. LICENSE_STATUS
  1577. AuthWithLicenseServer(
  1578. PHS_Protocol_Context pLicenseContext )
  1579. {
  1580. LICENSE_STATUS Status = LICENSE_STATUS_OK;
  1581. LPBYTE lpCert = NULL;
  1582. DWORD dwResult, RpcStatus;
  1583. DWORD dwSize;
  1584. if (pLicenseContext->hLSHandle == NULL)
  1585. return LICENSE_STATUS_INVALID_SERVER_CONTEXT;
  1586. Status = TLSGetTSCertificate(CERT_TYPE_X509, &lpCert, &dwSize);
  1587. if (Status != LICENSE_STATUS_OK)
  1588. {
  1589. Status = TLSGetTSCertificate(CERT_TYPE_PROPRIETORY, &lpCert, &dwSize);
  1590. }
  1591. if (Status != LICENSE_STATUS_OK)
  1592. {
  1593. goto done;
  1594. }
  1595. RpcStatus = TLSSendServerCertificate(
  1596. pLicenseContext->hLSHandle,
  1597. dwSize,
  1598. lpCert,
  1599. &dwResult
  1600. );
  1601. if( ( RPC_S_OK != RpcStatus ) || ( LSERVER_S_SUCCESS != dwResult ) )
  1602. {
  1603. Status = LICENSE_STATUS_AUTHENTICATION_ERROR;
  1604. goto done;
  1605. }
  1606. done:
  1607. if (lpCert)
  1608. TLSFreeTSCertificate(lpCert);
  1609. return Status;
  1610. }
  1611. ///////////////////////////////////////////////////////////////////////////////
  1612. LICENSE_STATUS
  1613. CheckConnectLicenseServer(
  1614. PHS_Protocol_Context pLicenseContext )
  1615. {
  1616. LICENSE_STATUS Status = LICENSE_STATUS_NO_LICENSE_SERVER;
  1617. if (pLicenseContext->hLSHandle != NULL)
  1618. return LICENSE_STATUS_OK;
  1619. pLicenseContext->hLSHandle = TLSConnectToAnyLsServer(LS_DISCOVERY_TIMEOUT);
  1620. if (NULL != pLicenseContext->hLSHandle)
  1621. {
  1622. Status = AuthWithLicenseServer(pLicenseContext);
  1623. if (Status == LICENSE_STATUS_OK)
  1624. {
  1625. goto done;
  1626. }
  1627. }
  1628. else
  1629. {
  1630. BOOL fInDomain;
  1631. LPWSTR szDomain = NULL;
  1632. DWORD dwErr;
  1633. dwErr = TLSInDomain(&fInDomain,&szDomain);
  1634. if ((ERROR_SUCCESS == dwErr) && (NULL != szDomain))
  1635. {
  1636. ThrottleLicenseLogEvent(
  1637. EVENTLOG_WARNING_TYPE,
  1638. fInDomain
  1639. ? EVENT_NO_LICENSE_SERVER_DOMAIN
  1640. : EVENT_NO_LICENSE_SERVER_WORKGROUP,
  1641. 1,
  1642. &szDomain );
  1643. }
  1644. else
  1645. {
  1646. ThrottleLicenseLogEvent(
  1647. EVENTLOG_WARNING_TYPE,
  1648. EVENT_NO_LICENSE_SERVER,
  1649. 0,
  1650. NULL );
  1651. }
  1652. if (NULL != szDomain)
  1653. {
  1654. NetApiBufferFree(szDomain);
  1655. }
  1656. }
  1657. // error case
  1658. if (NULL != pLicenseContext->hLSHandle)
  1659. {
  1660. TLSDisconnectFromServer(pLicenseContext->hLSHandle);
  1661. pLicenseContext->hLSHandle = NULL;
  1662. }
  1663. done:
  1664. return Status;
  1665. }
  1666. ///////////////////////////////////////////////////////////////////////////////
  1667. LICENSE_STATUS
  1668. CheckConnectNamedLicenseServer(
  1669. PHS_Protocol_Context pLicenseContext,
  1670. TCHAR *tszComputerName)
  1671. {
  1672. LICENSE_STATUS Status = LICENSE_STATUS_OK;
  1673. if (pLicenseContext->hLSHandle != NULL)
  1674. return LICENSE_STATUS_OK;
  1675. pLicenseContext->hLSHandle = TLSConnectToLsServer(tszComputerName);
  1676. if (NULL == pLicenseContext->hLSHandle)
  1677. {
  1678. Status = LICENSE_STATUS_NO_LICENSE_SERVER;
  1679. goto done;
  1680. }
  1681. Status = AuthWithLicenseServer(pLicenseContext);
  1682. if (Status != LICENSE_STATUS_OK)
  1683. {
  1684. TLSDisconnectFromServer(pLicenseContext->hLSHandle);
  1685. pLicenseContext->hLSHandle = NULL;
  1686. }
  1687. done:
  1688. return Status;
  1689. }
  1690. ///////////////////////////////////////////////////////////////////////////////
  1691. LICENSE_STATUS
  1692. CheckUpgradeLicense(
  1693. PHS_Protocol_Context pLicenseContext,
  1694. PDWORD pSupportFlags,
  1695. PLicense_Request pLicenseRequest,
  1696. DWORD cbChallengeResponse,
  1697. PBYTE pbChallengeResponse,
  1698. PHWID pHwid,
  1699. PDWORD pcbOutBuf,
  1700. PBYTE * ppOutBuf )
  1701. {
  1702. LICENSE_STATUS
  1703. Status = LICENSE_STATUS_OK;
  1704. DWORD
  1705. cbLicense = 0;
  1706. PBYTE
  1707. pbLicense = NULL;
  1708. Validation_Info
  1709. ValidationInfo;
  1710. DWORD
  1711. dwLicenseState = 0;
  1712. DWORD
  1713. RpcStatus, LsStatus;
  1714. BOOL
  1715. fRetried = FALSE;
  1716. reconnect:
  1717. Status = CheckConnectLicenseServer(pLicenseContext);
  1718. if( LICENSE_STATUS_OK != Status )
  1719. {
  1720. goto done;
  1721. }
  1722. RpcStatus = TLSUpgradeLicenseEx(pLicenseContext->hLSHandle,
  1723. pSupportFlags,
  1724. pLicenseRequest,
  1725. 0, // ChallengeContext unused
  1726. cbChallengeResponse,
  1727. pbChallengeResponse,
  1728. pLicenseContext->cbOldLicense,
  1729. pLicenseContext->pbOldLicense,
  1730. 1, // dwQuantity
  1731. &cbLicense,
  1732. &pbLicense,
  1733. &LsStatus
  1734. );
  1735. if ( RPC_S_OK != RpcStatus )
  1736. {
  1737. if (!fRetried)
  1738. {
  1739. fRetried = TRUE;
  1740. pLicenseContext->hLSHandle = NULL;
  1741. goto reconnect;
  1742. }
  1743. else
  1744. {
  1745. Status = LICENSE_STATUS_NO_LICENSE_SERVER;
  1746. }
  1747. }
  1748. else if ( LSERVER_ERROR_BASE <= LsStatus )
  1749. {
  1750. Status = LsStatusToLicenseStatus(LsStatus,
  1751. LICENSE_STATUS_CANNOT_UPGRADE_LICENSE);
  1752. }
  1753. ValidationInfo.pValidationData = ( PBYTE )pHwid;
  1754. ValidationInfo.cbValidationData = LICENSE_HWID_LENGTH;
  1755. ValidationInfo.pProductInfo = &pLicenseContext->ProductInfo;
  1756. //
  1757. // if we cannot upgrade the license, check if the current license is
  1758. // still good. If it is, return it to the client.
  1759. //
  1760. if( LICENSE_STATUS_OK != Status )
  1761. {
  1762. LICENSE_STATUS
  1763. LicenseStatus;
  1764. ValidationInfo.pLicense = pLicenseContext->pbOldLicense;
  1765. ValidationInfo.cbLicense = pLicenseContext->cbOldLicense;
  1766. LicenseStatus = ValidateLicense(
  1767. pLicenseContext,
  1768. &ValidationInfo,
  1769. &dwLicenseState,
  1770. FALSE // fCheckForPermanent
  1771. );
  1772. if( ( LICENSE_STATUS_OK == LicenseStatus ) ||
  1773. ( LICENSE_STATUS_SHOULD_UPGRADE_LICENSE == LicenseStatus ) )
  1774. {
  1775. //
  1776. // Store the raw license bits for later use. Ignore failure;
  1777. // that only means that if this is a license that should be
  1778. // marked, termsrv won't be able to.
  1779. //
  1780. CacheRawLicenseData(pLicenseContext,
  1781. pLicenseContext->pbOldLicense,
  1782. pLicenseContext->cbOldLicense);
  1783. //
  1784. // The current license is still OK, send it back to the client.
  1785. //
  1786. Status = PackageLicense(
  1787. pLicenseContext,
  1788. pLicenseContext->cbOldLicense,
  1789. pLicenseContext->pbOldLicense,
  1790. pcbOutBuf,
  1791. ppOutBuf,
  1792. FALSE );
  1793. }
  1794. else
  1795. {
  1796. //
  1797. // The current license is not good any more
  1798. //
  1799. #if DBG
  1800. DbgPrint( "UpgradeLicense: cannot upgrade license 0x%x\n", Status );
  1801. #endif
  1802. }
  1803. goto done;
  1804. }
  1805. //
  1806. // the license upgrade was successful. Now validate the new license so
  1807. // that the new license info will be cached.
  1808. //
  1809. ValidationInfo.pLicense = pbLicense;
  1810. ValidationInfo.cbLicense = cbLicense;
  1811. ValidateLicense(
  1812. pLicenseContext,
  1813. &ValidationInfo,
  1814. &dwLicenseState,
  1815. TRUE // fCheckForPermanent
  1816. );
  1817. //
  1818. // Store the raw license bits for later use. Ignore failure; that only
  1819. // means that if this is a license that should be marked, termsrv won't be
  1820. // able to.
  1821. //
  1822. CacheRawLicenseData(pLicenseContext,
  1823. pLicenseContext->pbOldLicense,
  1824. pLicenseContext->cbOldLicense);
  1825. //
  1826. // pack up the upgraded license
  1827. //
  1828. Status = PackageLicense( pLicenseContext,
  1829. cbLicense,
  1830. pbLicense,
  1831. pcbOutBuf,
  1832. ppOutBuf,
  1833. FALSE );
  1834. done:
  1835. if( pbLicense )
  1836. {
  1837. LicenseMemoryFree( &pbLicense );
  1838. }
  1839. return( Status );
  1840. }
  1841. ///////////////////////////////////////////////////////////////////////////////
  1842. LICENSE_STATUS
  1843. HandlePlatformChallengeResponse(
  1844. PHS_Protocol_Context pLicenseContext,
  1845. DWORD cbInBuf,
  1846. PBYTE pInBuf,
  1847. DWORD * pcbOutBuf,
  1848. PBYTE * ppOutBuf )
  1849. {
  1850. LICENSE_STATUS Status;
  1851. Hydra_Client_Platform_Challenge_Response PlatformChallengeResponse;
  1852. BYTE ChallengeResponse[PLATFORM_CHALLENGE_LENGTH];
  1853. PBYTE pLicense = NULL;
  1854. DWORD cbLicenseSize = 0;
  1855. License_Request LicenseRequest;
  1856. HS_LICENSE_STATE HsState = ABORTED;
  1857. License_Requester_Info RequesterInfo;
  1858. BYTE bEncryptedHwid[ sizeof( HWID ) ];
  1859. PBYTE pbSecretKey = NULL;
  1860. DWORD cbMacData = 0, cbSecretKey = 0, cbEncryptedHwid = sizeof( HWID );
  1861. BYTE MacData[ sizeof( HWID ) + PLATFORM_CHALLENGE_LENGTH ];
  1862. BYTE ComputedMac[LICENSE_MAC_DATA];
  1863. HWID Hwid;
  1864. DWORD RpcStatus,LsStatus;
  1865. TCHAR tszComputerName[MAX_COMPUTERNAME_LENGTH + 1];
  1866. TCHAR tszUserName[UNLEN + 1];
  1867. DWORD dwComputerName = MAX_COMPUTERNAME_LENGTH + 1;
  1868. DWORD dwUserName = UNLEN + 1;
  1869. DWORD dwSupportFlags = ALL_KNOWN_SUPPORT_FLAGS;
  1870. BOOL fRetried = FALSE;
  1871. ASSERT( NULL != pInBuf );
  1872. ASSERT( cbInBuf > 0 );
  1873. if( ( NULL == pInBuf ) || ( 0 >= cbInBuf ) )
  1874. {
  1875. return( LICENSE_STATUS_INVALID_INPUT );
  1876. }
  1877. //
  1878. // unpack the platform challenge response
  1879. //
  1880. InitBinaryBlob( &PlatformChallengeResponse.EncryptedChallengeResponse );
  1881. InitBinaryBlob( &PlatformChallengeResponse.EncryptedHWID );
  1882. Status = UnPackHydraClientPlatformChallengeResponse( pInBuf, cbInBuf, &PlatformChallengeResponse );
  1883. if( LICENSE_STATUS_OK != Status )
  1884. {
  1885. goto done;
  1886. }
  1887. //
  1888. // decrypt the encrypted challenge response and HWID
  1889. //
  1890. ASSERT(PlatformChallengeResponse.EncryptedChallengeResponse.wBlobLen
  1891. <= PLATFORM_CHALLENGE_LENGTH);
  1892. memcpy( ChallengeResponse,
  1893. PlatformChallengeResponse.EncryptedChallengeResponse.pBlob,
  1894. PlatformChallengeResponse.EncryptedChallengeResponse.wBlobLen );
  1895. Status = LicenseDecryptSessionData( &pLicenseContext->CryptoContext,
  1896. ChallengeResponse,
  1897. ( DWORD )PlatformChallengeResponse.EncryptedChallengeResponse.wBlobLen );
  1898. if( LICENSE_STATUS_OK != Status )
  1899. {
  1900. goto done;
  1901. }
  1902. //
  1903. // decrypt the client's HWID
  1904. //
  1905. if( PlatformChallengeResponse.EncryptedHWID.wBlobLen > sizeof(Hwid) )
  1906. {
  1907. Status = LICENSE_STATUS_INVALID_MAC_DATA;
  1908. goto done;
  1909. }
  1910. memcpy( &Hwid,
  1911. PlatformChallengeResponse.EncryptedHWID.pBlob,
  1912. PlatformChallengeResponse.EncryptedHWID.wBlobLen );
  1913. Status = LicenseDecryptSessionData( &pLicenseContext->CryptoContext,
  1914. ( PBYTE )&Hwid,
  1915. ( DWORD )PlatformChallengeResponse.EncryptedHWID.wBlobLen );
  1916. if( LICENSE_STATUS_OK != Status )
  1917. {
  1918. goto done;
  1919. }
  1920. //
  1921. // Verify the MAC data on the decrypted challenge response and the HWID
  1922. //
  1923. cbMacData += ( DWORD )PlatformChallengeResponse.EncryptedChallengeResponse.wBlobLen;
  1924. memcpy( MacData,
  1925. ChallengeResponse,
  1926. ( DWORD )PlatformChallengeResponse.EncryptedChallengeResponse.wBlobLen );
  1927. cbMacData += ( DWORD )PlatformChallengeResponse.EncryptedHWID.wBlobLen;
  1928. memcpy( MacData + ( DWORD )PlatformChallengeResponse.EncryptedChallengeResponse.wBlobLen,
  1929. &Hwid,
  1930. ( DWORD )PlatformChallengeResponse.EncryptedHWID.wBlobLen );
  1931. Status = LicenseGenerateMAC( &pLicenseContext->CryptoContext,
  1932. MacData,
  1933. cbMacData,
  1934. ComputedMac );
  1935. if( LICENSE_STATUS_OK != Status )
  1936. {
  1937. Status = LICENSE_STATUS_INVALID_MAC_DATA;
  1938. goto done;
  1939. }
  1940. if( 0 != memcmp( ComputedMac,
  1941. PlatformChallengeResponse.MACData,
  1942. LICENSE_MAC_DATA ) )
  1943. {
  1944. Status = LICENSE_STATUS_INVALID_MAC_DATA;
  1945. goto done;
  1946. }
  1947. //
  1948. // now get the license server's secret key and encrypt the HWID before transmitting it.
  1949. //
  1950. LicenseGetSecretKey( &cbSecretKey, NULL );
  1951. Status = LicenseMemoryAllocate( cbSecretKey, &pbSecretKey );
  1952. if( LICENSE_STATUS_OK != Status )
  1953. {
  1954. goto done;
  1955. }
  1956. Status = LicenseGetSecretKey( &cbSecretKey, pbSecretKey );
  1957. if( LICENSE_STATUS_OK != Status )
  1958. {
  1959. goto done;
  1960. }
  1961. Status = LicenseEncryptHwid( &Hwid, &cbEncryptedHwid, bEncryptedHwid,
  1962. cbSecretKey, pbSecretKey );
  1963. if( LICENSE_STATUS_OK != Status )
  1964. {
  1965. goto done;
  1966. }
  1967. LicenseRequest.cbEncryptedHwid = cbEncryptedHwid;
  1968. LicenseRequest.pbEncryptedHwid = bEncryptedHwid;
  1969. //
  1970. // send the platform challenge response to the license manager and wait for it
  1971. // to issue a new license.
  1972. //
  1973. LicenseRequest.pProductInfo = &pLicenseContext->ProductInfo;
  1974. LicenseRequest.dwPlatformID = pLicenseContext->dwClientPlatformID;
  1975. LicenseRequest.dwLanguageID = GetSystemDefaultLCID();
  1976. //
  1977. // if we don't have the client's user and machine name, get it now.
  1978. //
  1979. if( NULL == pLicenseContext->ptszClientMachineName )
  1980. {
  1981. //
  1982. // if we don't have the client machine name, just use the
  1983. // hydra server machine name
  1984. //
  1985. if( !GetComputerName( tszComputerName, &dwComputerName ) )
  1986. {
  1987. #if DBG
  1988. DbgPrint( "HandlePlatformChallengeResponse: cannot get computer name: 0x%x\n", GetLastError() );
  1989. #endif
  1990. memset( tszComputerName, 0, ( MAX_COMPUTERNAME_LENGTH + 1 ) * sizeof( TCHAR ) );
  1991. }
  1992. RequesterInfo.ptszMachineName = tszComputerName;
  1993. }
  1994. else
  1995. {
  1996. RequesterInfo.ptszMachineName = pLicenseContext->ptszClientMachineName;
  1997. }
  1998. if( NULL == pLicenseContext->ptszClientUserName )
  1999. {
  2000. //
  2001. // if we don't have the client's user name, just use the
  2002. // hydra server logged on user name.
  2003. //
  2004. if( !GetUserName( tszUserName, &dwUserName ) )
  2005. {
  2006. #if DBG
  2007. DbgPrint( "HandlePlatformChallengeResponse: cannot get user name: 0x%x\n", GetLastError() );
  2008. #endif
  2009. memset( tszUserName, 0, ( UNLEN + 1 ) * sizeof( TCHAR ) );
  2010. }
  2011. RequesterInfo.ptszUserName = tszUserName;
  2012. }
  2013. else
  2014. {
  2015. RequesterInfo.ptszUserName = pLicenseContext->ptszClientUserName;
  2016. }
  2017. if( pLicenseContext->pbOldLicense )
  2018. {
  2019. //
  2020. // attempt to upgrade an old license
  2021. //
  2022. Status = CheckUpgradeLicense(
  2023. pLicenseContext,
  2024. &dwSupportFlags,
  2025. &LicenseRequest,
  2026. ( DWORD )PlatformChallengeResponse.EncryptedChallengeResponse.wBlobLen,
  2027. ChallengeResponse,
  2028. &Hwid,
  2029. pcbOutBuf,
  2030. ppOutBuf );
  2031. if ((NULL != pLicenseContext->pTsLicenseInfo)
  2032. && (LICENSE_STATUS_OK != Status))
  2033. {
  2034. pLicenseContext->fLoggedProtocolError = TRUE;
  2035. if (pLicenseContext->pTsLicenseInfo->fTempLicense)
  2036. {
  2037. // The expired temporary license could not be upgraded
  2038. LicenseLogEvent(
  2039. EVENTLOG_INFORMATION_TYPE,
  2040. EVENT_EXPIRED_TEMPORARY_LICENSE,
  2041. 1,
  2042. &(RequesterInfo.ptszMachineName)
  2043. );
  2044. }
  2045. else
  2046. {
  2047. // The expired permanent license could not be renewed
  2048. LicenseLogEvent(
  2049. EVENTLOG_INFORMATION_TYPE,
  2050. EVENT_EXPIRED_PERMANENT_LICENSE,
  2051. 1,
  2052. &(RequesterInfo.ptszMachineName)
  2053. );
  2054. }
  2055. }
  2056. if( LICENSE_STATUS_OK != Status )
  2057. {
  2058. goto done;
  2059. }
  2060. }
  2061. else
  2062. {
  2063. reconnect:
  2064. Status = CheckConnectLicenseServer(pLicenseContext);
  2065. if( LICENSE_STATUS_OK != Status )
  2066. {
  2067. goto done;
  2068. }
  2069. RpcStatus = TLSIssueNewLicenseEx(
  2070. pLicenseContext->hLSHandle,
  2071. &dwSupportFlags,
  2072. 0, // ChallengeContext unused
  2073. &LicenseRequest,
  2074. RequesterInfo.ptszMachineName,
  2075. RequesterInfo.ptszUserName,
  2076. ( DWORD )PlatformChallengeResponse.EncryptedChallengeResponse.wBlobLen,
  2077. ChallengeResponse,
  2078. TRUE,
  2079. 1, // dwQuantity
  2080. &cbLicenseSize,
  2081. &pLicense,
  2082. &LsStatus );
  2083. if ( RPC_S_OK != RpcStatus )
  2084. {
  2085. if (!fRetried)
  2086. {
  2087. fRetried = TRUE;
  2088. pLicenseContext->hLSHandle = NULL;
  2089. goto reconnect;
  2090. }
  2091. else
  2092. {
  2093. Status = LICENSE_STATUS_NO_LICENSE_SERVER;
  2094. }
  2095. }
  2096. else if ( LSERVER_ERROR_BASE <= LsStatus )
  2097. {
  2098. Status = LsStatusToLicenseStatus(LsStatus,
  2099. LICENSE_STATUS_NO_LICENSE_ERROR);
  2100. }
  2101. else
  2102. {
  2103. DWORD dwLicenseState;
  2104. Validation_Info ValidationInfo;
  2105. //
  2106. // Validate the license for the sole purpose of caching the
  2107. // information.
  2108. //
  2109. ValidationInfo.pValidationData = ( PBYTE )&Hwid;
  2110. ValidationInfo.cbValidationData = LICENSE_HWID_LENGTH;
  2111. ValidationInfo.pProductInfo = &pLicenseContext->ProductInfo;
  2112. ValidationInfo.pLicense = pLicense;
  2113. ValidationInfo.cbLicense = cbLicenseSize;
  2114. ValidateLicense(pLicenseContext,
  2115. &ValidationInfo,
  2116. &dwLicenseState,
  2117. TRUE // fCheckForPermanent
  2118. );
  2119. //
  2120. // Store the raw license bits for later use. Ignore failure;
  2121. // that only means that if this is a license that should be
  2122. // marked, termsrv won't be able to.
  2123. //
  2124. CacheRawLicenseData(pLicenseContext, pLicense, cbLicenseSize);
  2125. //
  2126. // package up the new license
  2127. //
  2128. Status = PackageLicense( pLicenseContext,
  2129. cbLicenseSize,
  2130. pLicense,
  2131. pcbOutBuf,
  2132. ppOutBuf,
  2133. TRUE );
  2134. }
  2135. }
  2136. SetExtendedData(pLicenseContext, dwSupportFlags);
  2137. if( LICENSE_STATUS_OK != Status )
  2138. {
  2139. goto done;
  2140. }
  2141. //
  2142. // done with the protocol
  2143. //
  2144. HsState = ISSUED_LICENSE_COMPLETE;
  2145. Status = LICENSE_STATUS_ISSUED_LICENSE;
  2146. done:
  2147. //
  2148. // log all issue license failures
  2149. //
  2150. if( (LICENSE_STATUS_ISSUED_LICENSE != Status)
  2151. && (pLicenseContext != NULL)
  2152. && (!pLicenseContext->fLoggedProtocolError) )
  2153. {
  2154. pLicenseContext->fLoggedProtocolError = TRUE;
  2155. LicenseLogEvent( EVENTLOG_INFORMATION_TYPE,
  2156. EVENT_CANNOT_ISSUE_LICENSE,
  2157. 0, NULL );
  2158. }
  2159. if( pLicense )
  2160. {
  2161. LicenseMemoryFree( &pLicense );
  2162. }
  2163. if( pbSecretKey )
  2164. {
  2165. LicenseMemoryFree( &pbSecretKey );
  2166. }
  2167. if( pLicenseContext->pbOldLicense )
  2168. {
  2169. //
  2170. // free the old license
  2171. //
  2172. LicenseMemoryFree( &pLicenseContext->pbOldLicense );
  2173. pLicenseContext->cbOldLicense = 0;
  2174. }
  2175. FreeBinaryBlob( &PlatformChallengeResponse.EncryptedChallengeResponse );
  2176. FreeBinaryBlob( &PlatformChallengeResponse.EncryptedHWID );
  2177. pLicenseContext->State = HsState;
  2178. return( Status );
  2179. }
  2180. ///////////////////////////////////////////////////////////////////////////////
  2181. LICENSE_STATUS
  2182. IssuePlatformChallenge(
  2183. PHS_Protocol_Context pLicenseContext,
  2184. PDWORD pcbOutBuf,
  2185. PBYTE * ppOutBuf )
  2186. {
  2187. Hydra_Server_Platform_Challenge
  2188. PlatformChallenge;
  2189. DWORD
  2190. dwChallengeLen;
  2191. LPBYTE
  2192. pbChallengeData = NULL;
  2193. LICENSE_STATUS
  2194. Status = LICENSE_STATUS_OK;
  2195. DWORD
  2196. RpcStatus,LsStatus;
  2197. CHALLENGE_CONTEXT
  2198. ChallengeContext;
  2199. //
  2200. // generate the platform challenge
  2201. //
  2202. ASSERT( pLicenseContext );
  2203. Status = CheckConnectLicenseServer(pLicenseContext);
  2204. if( LICENSE_STATUS_OK != Status )
  2205. {
  2206. goto done;
  2207. }
  2208. RpcStatus = TLSIssuePlatformChallenge(pLicenseContext->hLSHandle,
  2209. pLicenseContext->dwClientPlatformID,
  2210. &ChallengeContext, // Context is unused by server, but we need a non-null pointer
  2211. &dwChallengeLen,
  2212. &pbChallengeData,
  2213. &LsStatus);
  2214. if(( RPC_S_OK != RpcStatus ) || ( LSERVER_ERROR_BASE <= LsStatus ) )
  2215. {
  2216. Status = LICENSE_STATUS_NO_PLATFORM_CHALLENGE ;
  2217. #if DBG
  2218. DbgPrint( "LICPROT: cannot issue platform challenge: 0x%x\n", Status );
  2219. #endif
  2220. goto done;
  2221. }
  2222. //
  2223. // Form the platform challenge message
  2224. //
  2225. PlatformChallenge.EncryptedPlatformChallenge.wBlobLen = ( WORD )dwChallengeLen;
  2226. PlatformChallenge.EncryptedPlatformChallenge.pBlob = pbChallengeData;
  2227. //
  2228. // calculate the MAC for the unencrypted platform challenge
  2229. //
  2230. Status = LicenseGenerateMAC( &pLicenseContext->CryptoContext,
  2231. PlatformChallenge.EncryptedPlatformChallenge.pBlob,
  2232. ( DWORD )PlatformChallenge.EncryptedPlatformChallenge.wBlobLen,
  2233. PlatformChallenge.MACData );
  2234. if( LICENSE_STATUS_OK != Status )
  2235. {
  2236. #if DBG
  2237. DbgPrint( "LICPROT: cannot generate MAC data for challenge platform: 0x%x\n", Status );
  2238. #endif
  2239. goto done;
  2240. }
  2241. //
  2242. // encrypt the platform challenge
  2243. //
  2244. Status = LicenseEncryptSessionData( &pLicenseContext->CryptoContext,
  2245. PlatformChallenge.EncryptedPlatformChallenge.pBlob,
  2246. PlatformChallenge.EncryptedPlatformChallenge.wBlobLen );
  2247. if( LICENSE_STATUS_OK != Status )
  2248. {
  2249. #if DBG
  2250. DbgPrint( "LICPROT: cannot encrypt platform challenge data: 0x%x\n", Status );
  2251. #endif
  2252. goto done;
  2253. }
  2254. //
  2255. // pack the platform challenge
  2256. //
  2257. Status = PackHydraServerPlatformChallenge(
  2258. pLicenseContext->dwProtocolVersion,
  2259. &PlatformChallenge,
  2260. ppOutBuf,
  2261. pcbOutBuf );
  2262. if( LICENSE_STATUS_OK != Status )
  2263. {
  2264. #if DBG
  2265. DbgPrint( "LICPROT: cannot pack platform challenge data: 0x%x\n", Status );
  2266. #endif
  2267. goto done;
  2268. }
  2269. done:
  2270. if( pbChallengeData )
  2271. {
  2272. LicenseMemoryFree( &pbChallengeData );
  2273. }
  2274. return( Status );
  2275. }
  2276. ///////////////////////////////////////////////////////////////////////////////
  2277. LICENSE_STATUS
  2278. PackageLicense(
  2279. PHS_Protocol_Context pLicenseContext,
  2280. DWORD cbLicense,
  2281. PBYTE pLicense,
  2282. PDWORD pcbOutBuf,
  2283. PBYTE * ppOutBuf,
  2284. BOOL fNewLicense )
  2285. {
  2286. LICENSE_STATUS Status;
  2287. New_License_Info NewLicenseInfo;
  2288. Hydra_Server_New_License NewLicense;
  2289. DWORD cbEncryptedLicenseInfo = 0;
  2290. if( ( 0 == cbLicense ) || ( NULL == pLicense ) )
  2291. {
  2292. return( LICENSE_STATUS_INVALID_INPUT );
  2293. }
  2294. //
  2295. // Initialize the new license information
  2296. //
  2297. NewLicenseInfo.dwVersion = pLicenseContext->ProductInfo.dwVersion;
  2298. NewLicenseInfo.cbScope = strlen( pLicenseContext->Scope ) + 1;
  2299. NewLicenseInfo.pbScope = pLicenseContext->Scope;
  2300. NewLicenseInfo.cbCompanyName = pLicenseContext->ProductInfo.cbCompanyName;
  2301. NewLicenseInfo.pbCompanyName = pLicenseContext->ProductInfo.pbCompanyName;
  2302. NewLicenseInfo.cbProductID = pLicenseContext->ProductInfo.cbProductID;
  2303. NewLicenseInfo.pbProductID = pLicenseContext->ProductInfo.pbProductID;
  2304. NewLicenseInfo.cbLicenseInfo = cbLicense;
  2305. NewLicenseInfo.pbLicenseInfo = pLicense;
  2306. //
  2307. // initialize the blob that will contain the encrypted new license
  2308. // information
  2309. //
  2310. NewLicense.EncryptedNewLicenseInfo.wBlobLen = 0;
  2311. NewLicense.EncryptedNewLicenseInfo.pBlob = NULL;
  2312. //
  2313. // pack the new license information
  2314. //
  2315. Status = PackNewLicenseInfo( &NewLicenseInfo,
  2316. &NewLicense.EncryptedNewLicenseInfo.pBlob,
  2317. &cbEncryptedLicenseInfo );
  2318. NewLicense.EncryptedNewLicenseInfo.wBlobLen = ( WORD )cbEncryptedLicenseInfo;
  2319. if( LICENSE_STATUS_OK != Status )
  2320. {
  2321. goto done;
  2322. }
  2323. //
  2324. // calculate the mac data
  2325. //
  2326. Status = LicenseGenerateMAC( &pLicenseContext->CryptoContext,
  2327. NewLicense.EncryptedNewLicenseInfo.pBlob,
  2328. ( DWORD )NewLicense.EncryptedNewLicenseInfo.wBlobLen,
  2329. NewLicense.MACData );
  2330. if( LICENSE_STATUS_OK != Status )
  2331. {
  2332. goto done;
  2333. }
  2334. //
  2335. // Encrypt the new license info
  2336. //
  2337. Status = LicenseEncryptSessionData( &pLicenseContext->CryptoContext,
  2338. NewLicense.EncryptedNewLicenseInfo.pBlob,
  2339. cbEncryptedLicenseInfo );
  2340. if( LICENSE_STATUS_OK != Status )
  2341. {
  2342. goto done;
  2343. }
  2344. //
  2345. // package up the license for the client
  2346. //
  2347. if( fNewLicense )
  2348. {
  2349. Status = PackHydraServerNewLicense(
  2350. pLicenseContext->dwProtocolVersion,
  2351. &NewLicense,
  2352. ppOutBuf,
  2353. pcbOutBuf );
  2354. }
  2355. else
  2356. {
  2357. Status = PackHydraServerUpgradeLicense(
  2358. pLicenseContext->dwProtocolVersion,
  2359. &NewLicense,
  2360. ppOutBuf,
  2361. pcbOutBuf );
  2362. }
  2363. done:
  2364. if( NewLicense.EncryptedNewLicenseInfo.pBlob )
  2365. {
  2366. LicenseMemoryFree( &NewLicense.EncryptedNewLicenseInfo.pBlob );
  2367. }
  2368. return( Status );
  2369. }
  2370. ///////////////////////////////////////////////////////////////////////////////
  2371. LICENSE_STATUS
  2372. ConstructProtocolResponse(
  2373. HANDLE hLicense,
  2374. DWORD dwResponse,
  2375. PDWORD pcbOutBuf,
  2376. PBYTE * ppOutBuf )
  2377. {
  2378. PHS_Protocol_Context
  2379. pLicenseContext;
  2380. LICENSE_STATUS
  2381. Status;
  2382. pLicenseContext = ( PHS_Protocol_Context )hLicense;
  2383. if (pLicenseContext == NULL)
  2384. {
  2385. return( LICENSE_STATUS_INVALID_INPUT );
  2386. }
  2387. LOCK( &pLicenseContext->CritSec );
  2388. //
  2389. // construct the server response. If this is a per seat license context, use the
  2390. // licensing protocol version specified in the context. Otherwise, use the
  2391. // protocol version that is compatible with Terminal server 4.0.
  2392. //
  2393. Status = ConstructServerResponse(
  2394. pLicenseContext->dwProtocolVersion,
  2395. dwResponse,
  2396. pcbOutBuf,
  2397. ppOutBuf );
  2398. UNLOCK( &pLicenseContext->CritSec );
  2399. return( Status );
  2400. }
  2401. ///////////////////////////////////////////////////////////////////////////////
  2402. LICENSE_STATUS
  2403. ConstructServerResponse(
  2404. DWORD dwProtocolVersion,
  2405. DWORD dwResponse,
  2406. PDWORD pcbOutBuf,
  2407. PBYTE * ppOutBuf )
  2408. {
  2409. License_Error_Message ErrorMsg;
  2410. LICENSE_STATUS Status;
  2411. if( ( NULL == pcbOutBuf ) || ( NULL == ppOutBuf ) )
  2412. {
  2413. return( LICENSE_STATUS_INVALID_INPUT );
  2414. }
  2415. if( LICENSE_RESPONSE_VALID_CLIENT == dwResponse )
  2416. {
  2417. ErrorMsg.dwErrorCode = GM_HS_ERR_VALID_CLIENT;
  2418. ErrorMsg.dwStateTransition = ST_NO_TRANSITION;
  2419. }
  2420. else if( LICENSE_RESPONSE_INVALID_CLIENT == dwResponse )
  2421. {
  2422. ErrorMsg.dwErrorCode = GM_HS_ERR_INVALID_CLIENT;
  2423. ErrorMsg.dwStateTransition = ST_TOTAL_ABORT;
  2424. }
  2425. else
  2426. {
  2427. return( LICENSE_STATUS_INVALID_INPUT );
  2428. }
  2429. ErrorMsg.bbErrorInfo.wBlobLen = 0;
  2430. ErrorMsg.bbErrorInfo.pBlob = NULL;
  2431. Status = PackHydraServerErrorMessage(
  2432. dwProtocolVersion,
  2433. &ErrorMsg,
  2434. ppOutBuf,
  2435. pcbOutBuf );
  2436. return( Status );
  2437. }
  2438. ///////////////////////////////////////////////////////////////////////////////
  2439. LICENSE_STATUS
  2440. GetHydraServerPrivateKey(
  2441. CERT_TYPE CertType,
  2442. PBYTE * ppPrivateKey,
  2443. PDWORD pcbPrivateKey )
  2444. {
  2445. #ifndef USE_HARDCODED
  2446. LICENSE_STATUS Status = LICENSE_STATUS_OK;
  2447. HANDLE hPrivateKeyFile = NULL;
  2448. DWORD dwFileSizeHigh, dwFileSizeLow;
  2449. WCHAR szPrivateKeyFile[MAX_PATH];
  2450. //
  2451. // form the path to the private key file
  2452. //
  2453. GetSystemDirectory( ( LPTSTR )szPrivateKeyFile, MAX_PATH );
  2454. wcscat( szPrivateKeyFile, L"\\" );
  2455. wcscat( szPrivateKeyFile, HYDRA_SERVER_PRIVATE_KEY_FILE );
  2456. //
  2457. // get the private key of the hydra server.
  2458. // For now, get the private key from a file.
  2459. //
  2460. hPrivateKeyFile = CreateFile( szPrivateKeyFile,
  2461. GENERIC_READ,
  2462. 0,
  2463. NULL,
  2464. OPEN_EXISTING,
  2465. FILE_ATTRIBUTE_NORMAL,
  2466. NULL );
  2467. if( INVALID_HANDLE_VALUE == hPrivateKeyFile )
  2468. {
  2469. Status = LICENSE_STATUS_NO_PRIVATE_KEY;
  2470. goto done;
  2471. }
  2472. //
  2473. // get the private key file size. We're counting on the private key file
  2474. // not to exceed 64K
  2475. //
  2476. dwFileSizeLow = GetFileSize( hPrivateKeyFile, &dwFileSizeHigh );
  2477. if( 0xFFFFFFFF == dwFileSizeLow )
  2478. {
  2479. Status = LICENSE_STATUS_NO_PRIVATE_KEY;
  2480. goto done;
  2481. }
  2482. //
  2483. // allocate memory for the certificate and read the private key from the file.
  2484. //
  2485. *ppPrivateKey = NULL;
  2486. Status = LicenseMemoryAllocate( dwFileSizeLow, ppPrivateKey );
  2487. if( LICENSE_STATUS_OK != Status )
  2488. {
  2489. Status = LICENSE_STATUS_OUT_OF_MEMORY;
  2490. goto done;
  2491. }
  2492. if( 0 > ReadFile( hPrivateKeyFile,
  2493. *ppPrivateKey,
  2494. dwFileSizeLow,
  2495. pcbPrivateKey,
  2496. NULL ) )
  2497. {
  2498. if( *ppPrivateKey )
  2499. {
  2500. LicenseMemoryFree( ppPrivateKey );
  2501. }
  2502. Status = LICENSE_STATUS_NO_PRIVATE_KEY;
  2503. }
  2504. done:
  2505. if( hPrivateKeyFile )
  2506. {
  2507. CloseHandle( hPrivateKeyFile );
  2508. }
  2509. return( Status );
  2510. #else
  2511. LICENSE_STATUS Status;
  2512. DWORD dwSize;
  2513. LSCSPINFO CspData;
  2514. //
  2515. // Get the private key for the certificate that we are using
  2516. //
  2517. if( CERT_TYPE_PROPRIETORY == CertType )
  2518. {
  2519. CspData = LsCspInfo_PrivateKey;
  2520. }
  2521. else if( CERT_TYPE_X509 == CertType )
  2522. {
  2523. CspData = LsCspInfo_X509CertPrivateKey;
  2524. }
  2525. else
  2526. {
  2527. return( LICENSE_STATUS_NO_PRIVATE_KEY );
  2528. }
  2529. //
  2530. // call the Lscsp library to obtain the private key
  2531. //
  2532. if( LsCsp_GetServerData( CspData, NULL, &dwSize ) != LICENSE_STATUS_OK )
  2533. {
  2534. return( LICENSE_STATUS_NO_PRIVATE_KEY );
  2535. }
  2536. Status = LicenseMemoryAllocate( dwSize, ppPrivateKey );
  2537. if( LICENSE_STATUS_OK != Status )
  2538. {
  2539. return( Status );
  2540. }
  2541. if( LsCsp_GetServerData( CspData, *ppPrivateKey, &dwSize )
  2542. != LICENSE_STATUS_OK )
  2543. {
  2544. LicenseMemoryFree( ppPrivateKey );
  2545. return( LICENSE_STATUS_INSUFFICIENT_BUFFER );
  2546. }
  2547. *pcbPrivateKey = dwSize;
  2548. return( LICENSE_STATUS_OK );
  2549. #endif
  2550. }
  2551. ///////////////////////////////////////////////////////////////////////////////
  2552. LICENSE_STATUS
  2553. GetEnvelopedData(
  2554. CERT_TYPE CertType,
  2555. PBYTE pEnvelopedData,
  2556. DWORD dwEnvelopedDataLen,
  2557. PBYTE * ppData,
  2558. PDWORD pdwDataLen )
  2559. {
  2560. LICENSE_STATUS
  2561. Status;
  2562. LsCsp_DecryptEnvelopedData(
  2563. CertType,
  2564. pEnvelopedData,
  2565. dwEnvelopedDataLen,
  2566. NULL,
  2567. pdwDataLen );
  2568. Status = LicenseMemoryAllocate( *pdwDataLen, ppData );
  2569. if( LICENSE_STATUS_OK != Status )
  2570. {
  2571. goto done;
  2572. }
  2573. if( !LsCsp_DecryptEnvelopedData(
  2574. CertType,
  2575. pEnvelopedData,
  2576. dwEnvelopedDataLen,
  2577. *ppData,
  2578. pdwDataLen ) )
  2579. {
  2580. Status = LICENSE_STATUS_INVALID_INPUT;
  2581. }
  2582. done:
  2583. return( Status );
  2584. }
  2585. ///////////////////////////////////////////////////////////////////////////////
  2586. LICENSE_STATUS
  2587. InitProductInfo(
  2588. PProduct_Info pProductInfo,
  2589. LPTSTR lptszProductSku )
  2590. {
  2591. LICENSE_STATUS Status;
  2592. pProductInfo->pbCompanyName = NULL;
  2593. pProductInfo->pbProductID = NULL;
  2594. pProductInfo->dwVersion = g_dwTerminalServerVersion;
  2595. pProductInfo->cbCompanyName = wcslen( PRODUCT_INFO_COMPANY_NAME ) * sizeof( WCHAR )
  2596. + sizeof( WCHAR );
  2597. Status = LicenseMemoryAllocate( pProductInfo->cbCompanyName,
  2598. &pProductInfo->pbCompanyName );
  2599. if( LICENSE_STATUS_OK != Status )
  2600. {
  2601. #if DBG
  2602. DbgPrint( "InitProductInfo: cannot allocate memory: 0x%x\n", Status );
  2603. #endif
  2604. goto error;
  2605. }
  2606. wcscpy( ( PWCHAR )pProductInfo->pbCompanyName, PRODUCT_INFO_COMPANY_NAME );
  2607. pProductInfo->cbProductID = _tcslen( lptszProductSku ) * sizeof( TCHAR )
  2608. + sizeof( TCHAR );
  2609. Status = LicenseMemoryAllocate( pProductInfo->cbProductID,
  2610. &pProductInfo->pbProductID );
  2611. if( LICENSE_STATUS_OK != Status )
  2612. {
  2613. #if DBG
  2614. DbgPrint( "InitProductInfo: cannot allocate memory: 0x%x\n", Status );
  2615. #endif
  2616. goto error;
  2617. }
  2618. _tcscpy( ( PTCHAR )pProductInfo->pbProductID, lptszProductSku );
  2619. return( Status );
  2620. error:
  2621. //
  2622. // error return, free allocated resources
  2623. //
  2624. if( pProductInfo->pbCompanyName )
  2625. {
  2626. LicenseMemoryFree( &pProductInfo->pbCompanyName );
  2627. }
  2628. if( pProductInfo->pbProductID )
  2629. {
  2630. LicenseMemoryFree( &pProductInfo->pbProductID );
  2631. }
  2632. return( Status );
  2633. }
  2634. #define THROTTLE_WRAPAROUND 100
  2635. //
  2636. // Reduce the frequency of logging
  2637. // No need to strictly limit it to once every 100 calls
  2638. //
  2639. void
  2640. ThrottleLicenseLogEvent(
  2641. WORD wEventType,
  2642. DWORD dwEventId,
  2643. WORD cStrings,
  2644. PWCHAR * apwszStrings )
  2645. {
  2646. static LONG lLogged = THROTTLE_WRAPAROUND;
  2647. LONG lResult;
  2648. lResult = InterlockedIncrement(&lLogged);
  2649. if (THROTTLE_WRAPAROUND <= lResult)
  2650. {
  2651. LicenseLogEvent(
  2652. wEventType,
  2653. dwEventId,
  2654. cStrings,
  2655. apwszStrings );
  2656. lLogged = 0;
  2657. }
  2658. }
  2659. ///////////////////////////////////////////////////////////////////////////////
  2660. void
  2661. LicenseLogEvent(
  2662. WORD wEventType,
  2663. DWORD dwEventId,
  2664. WORD cStrings,
  2665. PWCHAR * apwszStrings )
  2666. {
  2667. if (!g_fEventLogOpen)
  2668. {
  2669. LOCK(&g_EventLogCritSec);
  2670. if (!g_fEventLogOpen)
  2671. {
  2672. g_hEventLog = RegisterEventSource( NULL,
  2673. TERMINAL_SERVICE_EVENT_LOG );
  2674. if (NULL != g_hEventLog)
  2675. {
  2676. g_fEventLogOpen = TRUE;
  2677. }
  2678. }
  2679. UNLOCK(&g_EventLogCritSec);
  2680. }
  2681. if( g_hEventLog )
  2682. {
  2683. WCHAR *wszStringEmpty = L"";
  2684. if (NULL == apwszStrings)
  2685. apwszStrings = &wszStringEmpty;
  2686. if ( !ReportEvent( g_hEventLog,
  2687. wEventType,
  2688. 0,
  2689. dwEventId,
  2690. NULL,
  2691. cStrings,
  2692. 0,
  2693. apwszStrings,
  2694. NULL ) )
  2695. {
  2696. #if DBG
  2697. DbgPrint( "LogEvent: could not log event: 0x%x\n", GetLastError() );
  2698. #endif
  2699. }
  2700. }
  2701. return;
  2702. }
  2703. #ifdef UNICODE
  2704. /*++
  2705. Function:
  2706. Ascii2Wchar
  2707. Description:
  2708. Convert an ascii string to a wide character string. This function is only
  2709. defined if UNICODE is defined. This function allocates memory for the
  2710. return value of the wide character string.
  2711. Arguments:
  2712. lpszAsciiStr - Points to the ascii string
  2713. ppwszWideStr - Points to the pointer to the wide character string.
  2714. Return:
  2715. LICENSE_STATUS_OK if successful or a LICENSE_STATUS error code otherwise.
  2716. --*/
  2717. LICENSE_STATUS
  2718. Ascii2Wchar
  2719. (
  2720. LPSTR lpszAsciiStr,
  2721. LPWSTR * ppwszWideStr )
  2722. {
  2723. LICENSE_STATUS
  2724. Status;
  2725. if( ( NULL == lpszAsciiStr ) || ( NULL == ppwszWideStr ) )
  2726. {
  2727. return( LICENSE_STATUS_INVALID_INPUT );
  2728. }
  2729. //
  2730. // allocate memory for the wide string
  2731. //
  2732. //
  2733. // Allocate extra space for NULL, mbstowcs() does not NULL terminate string
  2734. //
  2735. Status = LicenseMemoryAllocate(
  2736. ( _mbslen( lpszAsciiStr ) + 2 ) * sizeof( WCHAR ),
  2737. ppwszWideStr );
  2738. if( LICENSE_STATUS_OK != Status )
  2739. {
  2740. return( Status );
  2741. }
  2742. if( 0 >= mbstowcs( *ppwszWideStr, lpszAsciiStr, _mbslen( lpszAsciiStr ) + 1 ) )
  2743. {
  2744. #if DBG
  2745. DbgPrint( "LICPROT: Ascii2Wchar: cannot convert ascii string to wide char\n" );
  2746. #endif
  2747. Status = LICENSE_STATUS_INVALID_INPUT;
  2748. }
  2749. return( Status );
  2750. }
  2751. #endif
  2752. /*++
  2753. Function:
  2754. QueryLicenseInfo
  2755. Description:
  2756. Query the license information provided by the client
  2757. Parameters:
  2758. pLicenseContext - License protocol context
  2759. pTsLicenseInfo - Pointer to license information
  2760. Return:
  2761. If successful, pTsLicenseInfo will contain the license info and this
  2762. function returns LICENSE_STATUS_SUCCESS. Otherwise, returns a
  2763. LICENSE_STATUS error.
  2764. --*/
  2765. LICENSE_STATUS
  2766. QueryLicenseInfo(
  2767. HANDLE hContext,
  2768. PTS_LICENSE_INFO pTsLicenseInfo )
  2769. {
  2770. PHS_Protocol_Context
  2771. pLicenseContext = (PHS_Protocol_Context) hContext;
  2772. LICENSE_STATUS
  2773. Status;
  2774. if( ( NULL == hContext ) || ( NULL == pTsLicenseInfo ) )
  2775. {
  2776. return( LICENSE_STATUS_INVALID_INPUT );
  2777. }
  2778. if( NULL == pLicenseContext->pTsLicenseInfo )
  2779. {
  2780. return( LICENSE_STATUS_NO_LICENSE_ERROR );
  2781. }
  2782. //
  2783. // indicate if the license is temporary
  2784. //
  2785. pTsLicenseInfo->fTempLicense = pLicenseContext->pTsLicenseInfo->fTempLicense;
  2786. //
  2787. // license validity dates
  2788. //
  2789. pTsLicenseInfo->NotAfter = pLicenseContext->pTsLicenseInfo->NotAfter;
  2790. //
  2791. // raw license data
  2792. //
  2793. if (NULL != pTsLicenseInfo->pbRawLicense)
  2794. {
  2795. LicenseMemoryFree( &pTsLicenseInfo->pbRawLicense );
  2796. }
  2797. Status = LicenseMemoryAllocate(
  2798. pLicenseContext->pTsLicenseInfo->cbRawLicense,
  2799. &(pTsLicenseInfo->pbRawLicense));
  2800. if (Status != LICENSE_STATUS_OK)
  2801. {
  2802. return Status;
  2803. }
  2804. memcpy(pTsLicenseInfo->pbRawLicense,
  2805. pLicenseContext->pTsLicenseInfo->pbRawLicense,
  2806. pLicenseContext->pTsLicenseInfo->cbRawLicense);
  2807. pTsLicenseInfo->cbRawLicense
  2808. = pLicenseContext->pTsLicenseInfo->cbRawLicense;
  2809. //
  2810. // flags
  2811. //
  2812. pTsLicenseInfo->dwSupportFlags
  2813. = pLicenseContext->pTsLicenseInfo->dwSupportFlags;
  2814. return( LICENSE_STATUS_OK );
  2815. }
  2816. /*++
  2817. Function:
  2818. FreeLicenseInfo
  2819. Description:
  2820. Free the memory allocated for the elements in the TS_LICENSE_INFO structure.
  2821. Parameters:
  2822. pTsLicenseInfo - Pointer to a TS_LICENSE_INFO structure
  2823. Returns:
  2824. Nothing.
  2825. --*/
  2826. VOID
  2827. FreeLicenseInfo(
  2828. PTS_LICENSE_INFO pTsLicenseInfo )
  2829. {
  2830. FreeTsLicenseInfo( pTsLicenseInfo );
  2831. return;
  2832. }
  2833. ///////////////////////////////////////////////////////////////////////////////
  2834. LICENSE_STATUS
  2835. AcceptProtocolContext(
  2836. IN HANDLE hContext,
  2837. IN DWORD cbInBuf,
  2838. IN PBYTE pInBuf,
  2839. IN OUT DWORD * pcbOutBuf,
  2840. IN OUT PBYTE * ppOutBuf )
  2841. {
  2842. PHS_Protocol_Context pLicenseContext;
  2843. LICENSE_STATUS Status;
  2844. pLicenseContext = ( PHS_Protocol_Context )hContext;
  2845. LOCK( &pLicenseContext->CritSec );
  2846. if( INIT == pLicenseContext->State )
  2847. {
  2848. //
  2849. // Generate a hydra server hello message to request for client
  2850. // license
  2851. //
  2852. Status = CreateHydraServerHello(pLicenseContext,
  2853. cbInBuf,
  2854. pInBuf,
  2855. pcbOutBuf,
  2856. ppOutBuf);
  2857. goto done;
  2858. }
  2859. else if( SENT_SERVER_HELLO == pLicenseContext->State )
  2860. {
  2861. //
  2862. // Hello response from the client
  2863. //
  2864. Status = HandleHelloResponse(pLicenseContext,
  2865. cbInBuf,
  2866. pInBuf,
  2867. pcbOutBuf,
  2868. ppOutBuf);
  2869. goto done;
  2870. }
  2871. else if( ISSUED_PLATFORM_CHALLENGE == pLicenseContext->State )
  2872. {
  2873. //
  2874. // Handle the platform challenge response
  2875. //
  2876. Status = HandlePlatformChallengeResponse(pLicenseContext,
  2877. cbInBuf,
  2878. pInBuf,
  2879. pcbOutBuf,
  2880. ppOutBuf);
  2881. goto done;
  2882. }
  2883. else
  2884. {
  2885. Status = LICENSE_STATUS_INVALID_SERVER_CONTEXT;
  2886. }
  2887. //
  2888. // check other states to create other messages as required...
  2889. //
  2890. done:
  2891. //
  2892. // handle any error before returning.
  2893. //
  2894. // If the current status is LICENSE_STATUS_SERVER_ABORT, it means
  2895. // that we have already tried to handle the error conditions
  2896. // with no success and the only option is to abort without
  2897. // informing the client licensing protocol.
  2898. //
  2899. if( ( LICENSE_STATUS_OK != Status ) &&
  2900. ( LICENSE_STATUS_CONTINUE != Status ) &&
  2901. ( LICENSE_STATUS_ISSUED_LICENSE != Status ) &&
  2902. ( LICENSE_STATUS_SEND_ERROR != Status ) &&
  2903. ( LICENSE_STATUS_SERVER_ABORT != Status ) &&
  2904. ( LICENSE_STATUS_INVALID_SERVER_CONTEXT != Status ) )
  2905. {
  2906. HandleErrorCondition( pLicenseContext, pcbOutBuf, ppOutBuf, &Status );
  2907. }
  2908. UNLOCK( &pLicenseContext->CritSec );
  2909. return( Status );
  2910. }
  2911. LICENSE_STATUS
  2912. RequestNewLicense(
  2913. IN HANDLE hContext,
  2914. IN TCHAR *tszLicenseServerName,
  2915. IN LICENSEREQUEST *pLicenseRequest,
  2916. IN TCHAR *tszComputerName,
  2917. IN TCHAR *tszUserName,
  2918. IN BOOL fAcceptTempLicense,
  2919. IN BOOL fAcceptFewerLicenses,
  2920. IN DWORD *pdwQuantity,
  2921. OUT DWORD *pcbLicense,
  2922. OUT PBYTE *ppbLicense
  2923. )
  2924. {
  2925. PHS_Protocol_Context pLicenseContext;
  2926. LICENSE_STATUS LsStatus;
  2927. DWORD dwChallengeResponse = 0;
  2928. DWORD RpcStatus;
  2929. DWORD dwSupportFlags = SUPPORT_PER_SEAT_REISSUANCE;
  2930. BOOL fRetried = FALSE;
  2931. pLicenseContext = ( PHS_Protocol_Context )hContext;
  2932. LOCK( &pLicenseContext->CritSec );
  2933. reconnect:
  2934. if (NULL != tszLicenseServerName)
  2935. {
  2936. LsStatus = CheckConnectNamedLicenseServer(pLicenseContext,
  2937. tszLicenseServerName);
  2938. }
  2939. else
  2940. {
  2941. LsStatus = CheckConnectLicenseServer(pLicenseContext);
  2942. }
  2943. if( LICENSE_STATUS_OK != LsStatus )
  2944. {
  2945. goto done;
  2946. }
  2947. RpcStatus = TLSIssueNewLicenseExEx(
  2948. pLicenseContext->hLSHandle,
  2949. &dwSupportFlags,
  2950. 0, // Challenge Context
  2951. pLicenseRequest,
  2952. tszComputerName,
  2953. tszUserName,
  2954. sizeof(DWORD), // cbChallengeResponse
  2955. (PBYTE) &dwChallengeResponse,
  2956. fAcceptTempLicense,
  2957. fAcceptFewerLicenses,
  2958. pdwQuantity,
  2959. pcbLicense,
  2960. ppbLicense,
  2961. &LsStatus );
  2962. if ( RPC_S_OK != RpcStatus )
  2963. {
  2964. if (!fRetried)
  2965. {
  2966. fRetried = TRUE;
  2967. pLicenseContext->hLSHandle = NULL;
  2968. goto reconnect;
  2969. }
  2970. else
  2971. {
  2972. LsStatus = LICENSE_STATUS_NO_LICENSE_SERVER;
  2973. }
  2974. }
  2975. else if ( LSERVER_ERROR_BASE <= LsStatus )
  2976. {
  2977. LsStatus = LsStatusToLicenseStatus(LsStatus,
  2978. LICENSE_STATUS_NO_LICENSE_ERROR);
  2979. }
  2980. done:
  2981. UNLOCK( &pLicenseContext->CritSec );
  2982. return LsStatus;
  2983. }
  2984. // TODO: Generalize this for all license types
  2985. LICENSE_STATUS
  2986. ReturnInternetLicense(
  2987. IN HANDLE hContext,
  2988. IN TCHAR *tszLicenseServer,
  2989. IN LICENSEREQUEST *pLicenseRequest,
  2990. IN ULARGE_INTEGER ulSerialNumber,
  2991. IN DWORD dwQuantity
  2992. )
  2993. {
  2994. PHS_Protocol_Context pLicenseContext;
  2995. LICENSE_STATUS LsStatus;
  2996. DWORD RpcStatus;
  2997. BOOL fRetried = FALSE;
  2998. pLicenseContext = ( PHS_Protocol_Context )hContext;
  2999. LOCK( &pLicenseContext->CritSec );
  3000. reconnect:
  3001. if (NULL != tszLicenseServer)
  3002. {
  3003. LsStatus = CheckConnectNamedLicenseServer(pLicenseContext,
  3004. tszLicenseServer);
  3005. }
  3006. else
  3007. {
  3008. LsStatus = CheckConnectLicenseServer(pLicenseContext);
  3009. }
  3010. if (LICENSE_STATUS_OK != LsStatus)
  3011. {
  3012. goto done;
  3013. }
  3014. RpcStatus = TLSReturnInternetLicenseEx(
  3015. pLicenseContext->hLSHandle,
  3016. pLicenseRequest,
  3017. &ulSerialNumber,
  3018. dwQuantity,
  3019. &LsStatus );
  3020. if ( RPC_S_OK != RpcStatus )
  3021. {
  3022. if (!fRetried)
  3023. {
  3024. fRetried = TRUE;
  3025. pLicenseContext->hLSHandle = NULL;
  3026. goto reconnect;
  3027. }
  3028. else
  3029. {
  3030. LsStatus = LICENSE_STATUS_NO_LICENSE_SERVER;
  3031. }
  3032. }
  3033. else if ( LSERVER_ERROR_BASE <= LsStatus )
  3034. {
  3035. LsStatus = LsStatusToLicenseStatus(LsStatus,
  3036. LICENSE_STATUS_NOT_SUPPORTED);
  3037. }
  3038. done:
  3039. UNLOCK( &pLicenseContext->CritSec );
  3040. return( LsStatus );
  3041. }
  3042. /****************************************************************************
  3043. *
  3044. * FileTimeToUnixTime
  3045. *
  3046. * Convert FILETIME to UNIX time (time_t)
  3047. *
  3048. * ENTRY:
  3049. * pft (input)
  3050. * pointer FILETIME structure
  3051. * t (input/output)
  3052. * pointer to UNIX time
  3053. *
  3054. * EXIT:
  3055. * TRUE - Success
  3056. * FALSE - Failure
  3057. *
  3058. ****************************************************************************/
  3059. BOOL
  3060. FileTimeToUnixTime(
  3061. LPFILETIME pft,
  3062. time_t * t
  3063. )
  3064. {
  3065. SYSTEMTIME sysTime;
  3066. struct tm gmTime;
  3067. if( FileTimeToSystemTime( pft, &sysTime ) == FALSE )
  3068. {
  3069. return( FALSE );
  3070. }
  3071. if( sysTime.wYear >= 2038 )
  3072. {
  3073. *t = INT_MAX;
  3074. }
  3075. else
  3076. {
  3077. //
  3078. // Unix time support up to 2038/1/18
  3079. // restrict any expiration data
  3080. //
  3081. memset( &gmTime, 0, sizeof( gmTime ) );
  3082. gmTime.tm_sec = sysTime.wSecond;
  3083. gmTime.tm_min = sysTime.wMinute;
  3084. gmTime.tm_hour = sysTime.wHour;
  3085. gmTime.tm_year = sysTime.wYear - 1900;
  3086. gmTime.tm_mon = sysTime.wMonth - 1;
  3087. gmTime.tm_mday = sysTime.wDay;
  3088. *t = mktime( &gmTime );
  3089. }
  3090. return( *t != ( time_t )-1 );
  3091. }
  3092. /*++
  3093. Function:
  3094. DaysToExpiration
  3095. Description:
  3096. Return expiration info from the client license
  3097. Parameters:
  3098. hContext - License protocol context
  3099. pdwDaysLeft - Number of days to expiration is returned here. If the
  3100. license has already expired, this is 0. If the
  3101. license has no expiration date, this is 0xFFFFFFFF
  3102. pfTemporary - Whether the license is temporary is returned here
  3103. Return:
  3104. If successful, the output parameters are filled in, and this
  3105. function returns LICENSE_STATUS_SUCCESS. Otherwise, returns a
  3106. LICENSE_STATUS error.
  3107. --*/
  3108. LICENSE_STATUS
  3109. DaysToExpiration(
  3110. HANDLE hContext,
  3111. DWORD *pdwDaysLeft,
  3112. BOOL *pfTemporary
  3113. )
  3114. {
  3115. PHS_Protocol_Context
  3116. pLicenseContext = (PHS_Protocol_Context) hContext;
  3117. time_t
  3118. Expiration,
  3119. CurrentTime;
  3120. if ( NULL == hContext )
  3121. {
  3122. return( LICENSE_STATUS_INVALID_INPUT );
  3123. }
  3124. if( NULL == pLicenseContext->pTsLicenseInfo )
  3125. {
  3126. return( LICENSE_STATUS_NO_LICENSE_ERROR );
  3127. }
  3128. //
  3129. // indicate if the license is temporary
  3130. //
  3131. if (NULL != pfTemporary)
  3132. {
  3133. *pfTemporary = pLicenseContext->pTsLicenseInfo->fTempLicense;
  3134. }
  3135. //
  3136. // license validity dates
  3137. //
  3138. if (NULL != pdwDaysLeft)
  3139. {
  3140. if ( FALSE == FileTimeToUnixTime( &pLicenseContext->pTsLicenseInfo->NotAfter, &Expiration ) )
  3141. {
  3142. return (LICENSE_STATUS_INVALID_CLIENT_CONTEXT);
  3143. }
  3144. if (PERMANENT_LICENSE_EXPIRE_DATE == Expiration)
  3145. {
  3146. *pdwDaysLeft = 0xFFFFFFFF;
  3147. }
  3148. else
  3149. {
  3150. time( &CurrentTime );
  3151. if( CurrentTime >= Expiration )
  3152. {
  3153. //
  3154. // license already expired
  3155. //
  3156. *pdwDaysLeft = 0;
  3157. }
  3158. //
  3159. // figure out how many more days to go before license expires
  3160. //
  3161. *pdwDaysLeft = (DWORD)(( Expiration - CurrentTime ) / SECONDS_IN_A_DAY);
  3162. }
  3163. }
  3164. return( LICENSE_STATUS_OK );
  3165. }
  3166. /*++
  3167. Function:
  3168. MarkLicenseFlags
  3169. Description:
  3170. Marks the license at the license server as being used in a valid logon.
  3171. --*/
  3172. LICENSE_STATUS
  3173. MarkLicenseFlags(
  3174. HANDLE hContext,
  3175. UCHAR ucFlags
  3176. )
  3177. {
  3178. PHS_Protocol_Context pLicenseContext;
  3179. LICENSE_STATUS LsStatus;
  3180. DWORD RpcStatus;
  3181. BOOL fRetried = FALSE;
  3182. pLicenseContext = ( PHS_Protocol_Context )hContext;
  3183. if( NULL == pLicenseContext->pTsLicenseInfo )
  3184. {
  3185. return( LICENSE_STATUS_NO_LICENSE_ERROR );
  3186. }
  3187. if (!pLicenseContext->pTsLicenseInfo->fTempLicense)
  3188. {
  3189. return LICENSE_STATUS_OK;
  3190. }
  3191. LOCK( &pLicenseContext->CritSec );
  3192. reconnect:
  3193. LsStatus = CheckConnectLicenseServer(pLicenseContext);
  3194. if( LICENSE_STATUS_OK != LsStatus )
  3195. {
  3196. goto done;
  3197. }
  3198. RpcStatus = TLSMarkLicense(
  3199. pLicenseContext->hLSHandle,
  3200. ucFlags,
  3201. pLicenseContext->pTsLicenseInfo->cbRawLicense,
  3202. pLicenseContext->pTsLicenseInfo->pbRawLicense,
  3203. &LsStatus );
  3204. if ( RPC_S_OK != RpcStatus )
  3205. {
  3206. if (!fRetried)
  3207. {
  3208. fRetried = TRUE;
  3209. pLicenseContext->hLSHandle = NULL;
  3210. goto reconnect;
  3211. }
  3212. else
  3213. {
  3214. LsStatus = LICENSE_STATUS_NO_LICENSE_SERVER;
  3215. }
  3216. }
  3217. else if ( LSERVER_ERROR_BASE <= LsStatus )
  3218. {
  3219. LsStatus = LsStatusToLicenseStatus(LsStatus,
  3220. LICENSE_STATUS_NOT_SUPPORTED);
  3221. }
  3222. done:
  3223. UNLOCK( &pLicenseContext->CritSec );
  3224. return LsStatus;
  3225. }
  3226. /*++
  3227. Function:
  3228. CacheRawLicenseData
  3229. Description:
  3230. Caches the unpacked license bits in the TS_LICENSE_INFO for later use.
  3231. The TS_LICENSE_INFO struct should already be created.
  3232. --*/
  3233. LICENSE_STATUS
  3234. CacheRawLicenseData(
  3235. PHS_Protocol_Context pLicenseContext,
  3236. PBYTE pbRawLicense,
  3237. DWORD cbRawLicense
  3238. )
  3239. {
  3240. LICENSE_STATUS Status;
  3241. if ((pLicenseContext == NULL) || (pLicenseContext->pTsLicenseInfo == NULL))
  3242. {
  3243. return(LICENSE_STATUS_INVALID_INPUT);
  3244. }
  3245. if (pLicenseContext->pTsLicenseInfo->pbRawLicense != NULL)
  3246. {
  3247. LicenseMemoryFree(&(pLicenseContext->pTsLicenseInfo->pbRawLicense));
  3248. }
  3249. Status = LicenseMemoryAllocate(cbRawLicense,
  3250. &(pLicenseContext->pTsLicenseInfo->pbRawLicense));
  3251. if (Status == LICENSE_STATUS_OK)
  3252. {
  3253. memcpy(pLicenseContext->pTsLicenseInfo->pbRawLicense, pbRawLicense,
  3254. cbRawLicense);
  3255. pLicenseContext->pTsLicenseInfo->cbRawLicense = cbRawLicense;
  3256. }
  3257. return(Status);
  3258. }
  3259. /*++
  3260. Function:
  3261. SetExtendedData
  3262. Description:
  3263. Sets the new fields in the TsLicenseInfo.
  3264. --*/
  3265. LICENSE_STATUS
  3266. SetExtendedData(
  3267. PHS_Protocol_Context pLicenseContext,
  3268. DWORD dwSupportFlags
  3269. )
  3270. {
  3271. if ((pLicenseContext == NULL) || (pLicenseContext->pTsLicenseInfo == NULL))
  3272. {
  3273. return(LICENSE_STATUS_INVALID_INPUT);
  3274. }
  3275. pLicenseContext->pTsLicenseInfo->dwSupportFlags = dwSupportFlags;
  3276. return(LICENSE_STATUS_OK);
  3277. }
  3278. /*++
  3279. Function:
  3280. LsStatusToLicenseStatus
  3281. Description:
  3282. Map a license server error code to a LICENSE_STATUS
  3283. --*/
  3284. LICENSE_STATUS
  3285. LsStatusToLicenseStatus(
  3286. DWORD LsStatus,
  3287. DWORD LsStatusDefault
  3288. )
  3289. {
  3290. LICENSE_STATUS LicenseStatus;
  3291. switch (LsStatus)
  3292. {
  3293. case LSERVER_S_SUCCESS:
  3294. LicenseStatus = LICENSE_STATUS_OK;
  3295. break;
  3296. case LSERVER_E_OUTOFMEMORY:
  3297. LicenseStatus = LICENSE_STATUS_OUT_OF_MEMORY;
  3298. break;
  3299. case LSERVER_E_INVALID_DATA:
  3300. LicenseStatus = LICENSE_STATUS_INVALID_INPUT;
  3301. break;
  3302. case LSERVER_E_LS_NOTPRESENT:
  3303. case LSERVER_E_LS_NOTRUNNING:
  3304. LicenseStatus = LICENSE_STATUS_NO_LICENSE_SERVER;
  3305. break;
  3306. case LSERVER_E_NO_LICENSE:
  3307. case LSERVER_E_NO_PRODUCT:
  3308. case LSERVER_E_NO_CERTIFICATE: // not activated
  3309. LicenseStatus = LICENSE_STATUS_NO_LICENSE_ERROR;
  3310. break;
  3311. case LSERVER_E_INTERNAL_ERROR:
  3312. LicenseStatus = LICENSE_STATUS_UNSPECIFIED_ERROR;
  3313. break;
  3314. default:
  3315. LicenseStatus = LsStatusDefault;
  3316. break;
  3317. }
  3318. return LicenseStatus;
  3319. }