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.

790 lines
18 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996-1998
  5. //
  6. // File: timebomb.cpp
  7. //
  8. // Contents: Implement licensing timebomb-related APIs
  9. //
  10. // History: 08-12-98 FredCh Created
  11. //
  12. //-----------------------------------------------------------------------------
  13. #include "precomp.h"
  14. #include "tlsapip.h"
  15. #include "time.h"
  16. extern "C" {
  17. //-----------------------------------------------------------------------------
  18. //
  19. // The LSA secret name used to store the licensing timebomb expiration
  20. //
  21. //-----------------------------------------------------------------------------
  22. #define LICENSING_TIME_BOMB_5_0 L"TIMEBOMB_832cc540-3244-11d2-b416-00c04fa30cc4"
  23. #define RTMLICENSING_TIME_BOMB_5_0 L"RTMTSTB_832cc540-3244-11d2-b416-00c04fa30cc4"
  24. #define BETA2_LICENSING_TIME_BOMB_5_1 L"BETA2TIMEBOMB_1320153D-8DA3-4e8e-B27B-0D888223A588"
  25. // L$ means only readable from the local machine
  26. #define BETA_LICENSING_TIME_BOMB_5_1 L"L$BETA3TIMEBOMB_1320153D-8DA3-4e8e-B27B-0D888223A588"
  27. #define RTM_LICENSING_TIME_BOMB_5_1 L"L$RTMTIMEBOMB_1320153D-8DA3-4e8e-B27B-0D888223A588"
  28. #define BETA_LICENSING_TIME_BOMB_LATEST_VERSION BETA_LICENSING_TIME_BOMB_5_1
  29. #define RTM_LICENSING_TIME_BOMB_LATEST_VERSION RTM_LICENSING_TIME_BOMB_5_1
  30. //-----------------------------------------------------------------------------
  31. //
  32. // The global licensing time bomb value.
  33. //
  34. //-----------------------------------------------------------------------------
  35. FILETIME g_LicenseTimeBomb;
  36. //-----------------------------------------------------------------------------
  37. //
  38. // The number of licensing grace period is 90 days. By default, we start
  39. // logging events when there are less than 15 days from expiration and the
  40. // terminal server has not registered itself with a license server.
  41. //
  42. //-----------------------------------------------------------------------------
  43. #define GRACE_PERIOD 120
  44. #define GRACE_PERIOD_EXPIRATION_WARNING_DAYS 15
  45. //-----------------------------------------------------------------------------
  46. //
  47. // Only log the grace period warning or error once a day.
  48. //
  49. //-----------------------------------------------------------------------------
  50. #define GRACE_PERIOD_EVENT_LOG_INTERVAL (1000*60*60*24)
  51. //-----------------------------------------------------------------------------
  52. //
  53. // Thread used to warn administrator when grace period is about to expire
  54. //
  55. //-----------------------------------------------------------------------------
  56. HANDLE g_GracePeriodThreadExitEvent = NULL;
  57. CRITICAL_SECTION g_EventCritSec;
  58. //-----------------------------------------------------------------------------
  59. //
  60. // Internal functions
  61. //
  62. //-----------------------------------------------------------------------------
  63. BOOL
  64. CalculateTimeBombExpiration(
  65. FILETIME * pExpiration );
  66. DWORD
  67. GetExpirationWarningDays();
  68. BOOL
  69. IsLicensingTimeBombExpired();
  70. /*++
  71. Function:
  72. InitializeLicensingTimeBomb
  73. Description:
  74. Initialize the licensing time bomb value.
  75. Argument:
  76. None.
  77. Return:
  78. A LICENSE_STATUS return code.
  79. --*/
  80. LICENSE_STATUS
  81. InitializeLicensingTimeBomb()
  82. {
  83. LICENSE_STATUS
  84. Status;
  85. DWORD
  86. cbTimeBomb = sizeof( FILETIME );
  87. NTSTATUS
  88. NtStatus;
  89. NtStatus = RtlInitializeCriticalSection(&g_EventCritSec);
  90. if (STATUS_SUCCESS != NtStatus)
  91. {
  92. return LICENSE_STATUS_INITIALIZATION_FAILED;
  93. }
  94. Status = LsCsp_RetrieveSecret(
  95. (TLSIsBetaNTServer()) ? BETA_LICENSING_TIME_BOMB_LATEST_VERSION : RTM_LICENSING_TIME_BOMB_LATEST_VERSION,
  96. ( LPBYTE )&g_LicenseTimeBomb,
  97. &cbTimeBomb );
  98. if( LICENSE_STATUS_OK == Status && cbTimeBomb == sizeof(g_LicenseTimeBomb) )
  99. {
  100. return( LICENSE_STATUS_OK );
  101. }
  102. //
  103. // Calculate and set the timebomb
  104. //
  105. if( FALSE == CalculateTimeBombExpiration( &g_LicenseTimeBomb ) )
  106. {
  107. #if DBG
  108. DbgPrint( "CalculateTimeBombExpiration: cannot calculate licensing time bomb expiration.\n" );
  109. #endif
  110. return( LICENSE_STATUS_INITIALIZATION_FAILED );
  111. }
  112. Status = LsCsp_StoreSecret(
  113. (TLSIsBetaNTServer()) ? BETA_LICENSING_TIME_BOMB_LATEST_VERSION : RTM_LICENSING_TIME_BOMB_LATEST_VERSION,
  114. ( LPBYTE )&g_LicenseTimeBomb,
  115. sizeof( g_LicenseTimeBomb ) );
  116. return( Status );
  117. }
  118. /*++
  119. Function:
  120. IsLicensingTimeBombExpired
  121. Description:
  122. Check if the licensing time bomb has expired.
  123. Argument:
  124. None.
  125. Return:
  126. TRUE if the timebomb has expired or FALSE otherwise.
  127. --*/
  128. BOOL
  129. IsLicensingTimeBombExpired()
  130. {
  131. SYSTEMTIME
  132. SysTimeNow;
  133. FILETIME
  134. FileTimeNow,
  135. FileTimeExpiration;
  136. GetSystemTime( &SysTimeNow );
  137. SystemTimeToFileTime( &SysTimeNow, &FileTimeNow );
  138. RtlEnterCriticalSection(&g_EventCritSec);
  139. FileTimeExpiration.dwLowDateTime = g_LicenseTimeBomb.dwLowDateTime;
  140. FileTimeExpiration.dwHighDateTime = g_LicenseTimeBomb.dwHighDateTime;
  141. RtlLeaveCriticalSection(&g_EventCritSec);
  142. if( 0 > CompareFileTime( &FileTimeExpiration, &FileTimeNow ) )
  143. {
  144. return( TRUE );
  145. }
  146. return( FALSE );
  147. }
  148. /*++
  149. Function:
  150. CalculateTimeBombExpiration
  151. Description:
  152. Calculate the licensing time bomb expiration.
  153. Argument:
  154. pExpiration - The timebomb expiration date and time
  155. Return:
  156. TRUE if the expiration is calculated successfully or FALSE otherwise.
  157. --*/
  158. BOOL
  159. CalculateTimeBombExpiration(
  160. FILETIME * pExpiration )
  161. {
  162. time_t
  163. now = time( NULL );
  164. struct tm *
  165. GmTime = gmtime( &now );
  166. SYSTEMTIME
  167. SysTime;
  168. if(( NULL == pExpiration ) || ( NULL == GmTime ))
  169. {
  170. return( FALSE );
  171. }
  172. //
  173. // Add the days of licensing grace period to get the time bomb
  174. // expiration.
  175. //
  176. GmTime->tm_mday += GRACE_PERIOD;
  177. if( ( ( time_t ) -1 ) == mktime( GmTime ) )
  178. {
  179. return( FALSE );
  180. }
  181. memset( &SysTime, 0, sizeof( SYSTEMTIME ) );
  182. SysTime.wYear = (WORD) GmTime->tm_year + 1900;
  183. SysTime.wMonth = (WORD) GmTime->tm_mon + 1;
  184. SysTime.wDay = (WORD) GmTime->tm_mday;
  185. SysTime.wDayOfWeek = (WORD) GmTime->tm_wday;
  186. SysTime.wHour = (WORD) GmTime->tm_hour;
  187. SysTime.wMinute = (WORD) GmTime->tm_min;
  188. SysTime.wSecond = (WORD) GmTime->tm_sec;
  189. return( SystemTimeToFileTime( &SysTime, pExpiration ) );
  190. }
  191. /*++
  192. Function:
  193. ReceivedPermanentLicense();
  194. Description:
  195. Store the fact that we've received a permanent license
  196. Argument:
  197. None.
  198. --*/
  199. VOID
  200. ReceivedPermanentLicense()
  201. {
  202. static fReceivedPermanent = FALSE;
  203. if (!fReceivedPermanent)
  204. {
  205. RtlEnterCriticalSection(&g_EventCritSec);
  206. if (IsLicensingTimeBombExpired())
  207. {
  208. // We expired at some time in the past (before the last reboot)
  209. fReceivedPermanent = TRUE;
  210. }
  211. else if (!fReceivedPermanent)
  212. {
  213. FILETIME ftNow;
  214. SYSTEMTIME stNow;
  215. fReceivedPermanent = TRUE;
  216. GetSystemTime( &stNow );
  217. SystemTimeToFileTime( &stNow , &ftNow );
  218. LsCsp_StoreSecret(
  219. (TLSIsBetaNTServer()) ? BETA_LICENSING_TIME_BOMB_LATEST_VERSION : RTM_LICENSING_TIME_BOMB_LATEST_VERSION,
  220. ( LPBYTE ) &ftNow,
  221. sizeof( ftNow ) );
  222. g_LicenseTimeBomb.dwLowDateTime = ftNow.dwLowDateTime;
  223. g_LicenseTimeBomb.dwHighDateTime = ftNow.dwHighDateTime;
  224. }
  225. RtlLeaveCriticalSection(&g_EventCritSec);
  226. }
  227. }
  228. /*++
  229. Function:
  230. CheckLicensingTimeBombExpiration();
  231. Description:
  232. The following events are logged when the terminal server
  233. has not registered itself with a license server:
  234. (1) The grace period for registration has expired
  235. (2) The grace period for registration is about to expire. By default,
  236. the system starts logging this event 15 days prior to the grace period
  237. expiration.
  238. Argument:
  239. None.
  240. Return:
  241. Nothing.
  242. --*/
  243. VOID
  244. CheckLicensingTimeBombExpiration()
  245. {
  246. SYSTEMTIME
  247. SysWarning,
  248. SysExpiration;
  249. FILETIME
  250. FileWarning,
  251. FileExpiration,
  252. CurrentTime;
  253. struct tm
  254. tmWarning,
  255. tmExpiration;
  256. DWORD
  257. dwWarningDays;
  258. //
  259. // if the licensing timebomb has expired, go ahead and log the event now
  260. //
  261. if( IsLicensingTimeBombExpired() )
  262. {
  263. LicenseLogEvent(
  264. EVENTLOG_ERROR_TYPE,
  265. EVENT_LICENSING_GRACE_PERIOD_EXPIRED,
  266. 0,
  267. NULL );
  268. return;
  269. }
  270. //
  271. // get the timebomb expiration in system time format
  272. //
  273. RtlEnterCriticalSection(&g_EventCritSec);
  274. FileExpiration.dwLowDateTime = g_LicenseTimeBomb.dwLowDateTime;
  275. FileExpiration.dwHighDateTime = g_LicenseTimeBomb.dwHighDateTime;
  276. RtlLeaveCriticalSection(&g_EventCritSec);
  277. if( !FileTimeToSystemTime( &FileExpiration, &SysExpiration ) )
  278. {
  279. #if DBG
  280. DbgPrint( "LICPROT: LogLicensingTimeBombExpirationEvent: FileTimeToSystemTime failed: 0x%x\n", GetLastError() );
  281. #endif
  282. return;
  283. }
  284. //
  285. // convert the timebomb expiration to tm format
  286. //
  287. tmExpiration.tm_year = SysExpiration.wYear - 1900;
  288. tmExpiration.tm_mon = SysExpiration.wMonth - 1;
  289. tmExpiration.tm_mday = SysExpiration.wDay;
  290. tmExpiration.tm_wday = SysExpiration.wDayOfWeek;
  291. tmExpiration.tm_hour = SysExpiration.wHour;
  292. tmExpiration.tm_min = SysExpiration.wMinute;
  293. tmExpiration.tm_sec = SysExpiration.wSecond;
  294. tmExpiration.tm_isdst = -1;
  295. memcpy( &tmWarning, &tmExpiration, sizeof( tm ) );
  296. //
  297. // Get the number of days prior to expiration to start logging event
  298. //
  299. dwWarningDays = GetExpirationWarningDays();
  300. //
  301. // subtract these number of days from the expiration date
  302. //
  303. tmWarning.tm_mday -= dwWarningDays;
  304. //
  305. // get the accurate date
  306. //
  307. if( ( ( time_t ) -1 ) == mktime( &tmWarning ) )
  308. {
  309. #if DBG
  310. DbgPrint( "LICPROT: LogLicensingTimeBombExpirationEvent: mktime failed\n" );
  311. #endif
  312. return;
  313. }
  314. //
  315. // convert the date to systemtime format
  316. //
  317. memset( &SysWarning, 0, sizeof( SYSTEMTIME ) );
  318. SysWarning.wYear = (WORD) tmWarning.tm_year + 1900;
  319. SysWarning.wMonth = (WORD) tmWarning.tm_mon + 1;
  320. SysWarning.wDay = (WORD) tmWarning.tm_mday;
  321. SysWarning.wDayOfWeek = (WORD) tmWarning.tm_wday;
  322. SysWarning.wHour = (WORD) tmWarning.tm_hour;
  323. SysWarning.wMinute = (WORD) tmWarning.tm_min;
  324. SysWarning.wSecond = (WORD) tmWarning.tm_sec;
  325. //
  326. // convert from systemtime to filetime
  327. //
  328. if( !SystemTimeToFileTime( &SysWarning, &FileWarning ) )
  329. {
  330. #if DBG
  331. DbgPrint( "LICPROT: LogLicensingTimeBombExpirationEvent: SystemTimeToFileTime failed: 0x%x\n", GetLastError() );
  332. #endif
  333. return;
  334. }
  335. //
  336. // get the current time
  337. //
  338. GetSystemTimeAsFileTime( &CurrentTime );
  339. //
  340. // Log an event if we are within the warning period
  341. //
  342. if( 0 > CompareFileTime( &FileWarning, &CurrentTime ) )
  343. {
  344. LPTSTR szDate = TEXT("err");
  345. LPTSTR
  346. ptszLogString[1];
  347. int cchDate;
  348. BOOL fAllocated = FALSE;
  349. //
  350. // get the expiration date in string format.
  351. //
  352. cchDate = GetDateFormat(LOCALE_SYSTEM_DEFAULT,
  353. LOCALE_NOUSEROVERRIDE,
  354. &SysWarning,
  355. NULL,
  356. NULL,
  357. 0);
  358. if (0 != cchDate)
  359. {
  360. szDate = (LPTSTR) LocalAlloc(LMEM_FIXED,cchDate * sizeof(TCHAR));
  361. if (NULL != szDate)
  362. {
  363. fAllocated = TRUE;
  364. if (0 == GetDateFormat(LOCALE_SYSTEM_DEFAULT,
  365. LOCALE_NOUSEROVERRIDE,
  366. &SysWarning,
  367. NULL,
  368. szDate,
  369. cchDate))
  370. {
  371. LocalFree(szDate);
  372. fAllocated = FALSE;
  373. szDate = TEXT("err");
  374. }
  375. }
  376. else
  377. {
  378. szDate = TEXT("err");
  379. }
  380. }
  381. //
  382. // log the event
  383. //
  384. ptszLogString[0] = szDate;
  385. LicenseLogEvent(
  386. EVENTLOG_WARNING_TYPE,
  387. EVENT_LICENSING_GRACE_PERIOD_ABOUT_TO_EXPIRE,
  388. 1,
  389. ptszLogString );
  390. if (fAllocated)
  391. {
  392. LocalFree(szDate);
  393. }
  394. }
  395. return;
  396. }
  397. /*++
  398. Function:
  399. GetExpirationWarningDays
  400. Descriptions:
  401. Get the number of days prior to grace period expiration to log warning.
  402. Arguments:
  403. none.
  404. Returns:
  405. Nothing.
  406. --*/
  407. DWORD
  408. GetExpirationWarningDays()
  409. {
  410. HKEY
  411. hKey = NULL;
  412. DWORD
  413. dwDays = GRACE_PERIOD_EXPIRATION_WARNING_DAYS,
  414. dwValueType,
  415. dwDisp,
  416. cbValue = sizeof( DWORD );
  417. LONG
  418. lReturn;
  419. lReturn = RegCreateKeyEx(
  420. HKEY_LOCAL_MACHINE,
  421. HYDRA_SERVER_PARAM,
  422. 0,
  423. NULL,
  424. REG_OPTION_NON_VOLATILE,
  425. KEY_ALL_ACCESS,
  426. NULL,
  427. &hKey,
  428. &dwDisp );
  429. if( ERROR_SUCCESS == lReturn )
  430. {
  431. //
  432. // query the number of days prior to expiration to log warnings
  433. //
  434. lReturn = RegQueryValueEx(
  435. hKey,
  436. HS_PARAM_GRACE_PERIOD_EXPIRATION_WARNING_DAYS,
  437. NULL,
  438. &dwValueType,
  439. ( LPBYTE )&dwDays,
  440. &cbValue );
  441. if( ERROR_SUCCESS == lReturn )
  442. {
  443. //
  444. // check if the warning days value is within bound
  445. //
  446. if( dwDays > GRACE_PERIOD )
  447. {
  448. dwDays = GRACE_PERIOD_EXPIRATION_WARNING_DAYS;
  449. }
  450. }
  451. else
  452. {
  453. //
  454. // can't query the value, set the default
  455. //
  456. dwDays = GRACE_PERIOD_EXPIRATION_WARNING_DAYS;
  457. lReturn = RegSetValueEx(
  458. hKey,
  459. HS_PARAM_GRACE_PERIOD_EXPIRATION_WARNING_DAYS,
  460. 0,
  461. REG_DWORD,
  462. ( PBYTE )&dwDays,
  463. sizeof( DWORD ) );
  464. }
  465. }
  466. if( hKey )
  467. {
  468. RegCloseKey( hKey );
  469. }
  470. return( dwDays );
  471. }
  472. /****************************************************************************
  473. *
  474. * _AllowLicensingGracePeriodConnection
  475. *
  476. * Check if the licensing grace period has expired.
  477. *
  478. * ENTRY:
  479. * Nothing.
  480. *
  481. * EXIT:
  482. * TRUE - Allow connection
  483. * FALSE - Disallow connection
  484. *
  485. ****************************************************************************/
  486. BOOL
  487. AllowLicensingGracePeriodConnection()
  488. {
  489. return !IsLicensingTimeBombExpired();
  490. }
  491. DWORD WINAPI
  492. GracePeriodCheckingThread(
  493. LPVOID lpParam)
  494. {
  495. HANDLE hExit = (HANDLE) lpParam;
  496. DWORD dwWaitStatus;
  497. DWORD dwWaitInterval = GRACE_PERIOD_EVENT_LOG_INTERVAL;
  498. // Yield our first time slice
  499. Sleep(0);
  500. while (1)
  501. {
  502. CheckLicensingTimeBombExpiration();
  503. dwWaitStatus = WaitForSingleObject(hExit, dwWaitInterval);
  504. if (WAIT_OBJECT_0 == dwWaitStatus)
  505. {
  506. // hExit was signalled
  507. CloseHandle(hExit);
  508. goto done;
  509. }
  510. }
  511. done:
  512. return 1;
  513. }
  514. DWORD
  515. StartCheckingGracePeriod()
  516. {
  517. HANDLE hThread = NULL;
  518. DWORD Status = ERROR_SUCCESS;
  519. if (NULL != g_GracePeriodThreadExitEvent)
  520. {
  521. // already started
  522. return ERROR_SUCCESS;
  523. }
  524. RtlEnterCriticalSection(&g_EventCritSec);
  525. // Check one more time
  526. if (NULL != g_GracePeriodThreadExitEvent)
  527. {
  528. // already started
  529. goto done;
  530. }
  531. //
  532. // Create the event to signal thread exit
  533. //
  534. g_GracePeriodThreadExitEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
  535. if( NULL == g_GracePeriodThreadExitEvent )
  536. {
  537. Status = GetLastError();
  538. goto done;
  539. }
  540. //
  541. // Create the caching thread
  542. //
  543. hThread = CreateThread(
  544. NULL,
  545. 0,
  546. GracePeriodCheckingThread,
  547. ( LPVOID )g_GracePeriodThreadExitEvent,
  548. 0,
  549. NULL );
  550. if (hThread == NULL)
  551. {
  552. CloseHandle(g_GracePeriodThreadExitEvent);
  553. g_GracePeriodThreadExitEvent = NULL;
  554. Status = GetLastError();
  555. goto done;
  556. }
  557. CloseHandle(hThread);
  558. done:
  559. RtlLeaveCriticalSection(&g_EventCritSec);
  560. return ERROR_SUCCESS;
  561. }
  562. DWORD
  563. StopCheckingGracePeriod()
  564. {
  565. //
  566. // Signal the thread to exit
  567. //
  568. if (NULL == g_GracePeriodThreadExitEvent)
  569. {
  570. // already stopped
  571. return ERROR_SUCCESS;
  572. }
  573. RtlEnterCriticalSection(&g_EventCritSec);
  574. // Check one more time
  575. if (NULL == g_GracePeriodThreadExitEvent)
  576. {
  577. // already stopped
  578. goto done;
  579. }
  580. SetEvent( g_GracePeriodThreadExitEvent );
  581. g_GracePeriodThreadExitEvent = NULL;
  582. done:
  583. RtlLeaveCriticalSection(&g_EventCritSec);
  584. return ERROR_SUCCESS;
  585. }
  586. } // extern "C"