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.

789 lines
19 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996-1998
  5. //
  6. // File: prottest.c
  7. //
  8. // Contents: Test program for hydra licensing protocol
  9. //
  10. // History: 01-07-98 FredCh Created
  11. //
  12. //-----------------------------------------------------------------------------
  13. #include <windows.h>
  14. #include <stdio.h>
  15. #include <time.h>
  16. #include <limits.h>
  17. #include <stdlib.h>
  18. #include "license.h"
  19. #include "hslice.h"
  20. #include "cryptkey.h"
  21. #include "hccontxt.h"
  22. #include "licecert.h"
  23. #include "lscsp.h"
  24. #include "sysapi.h"
  25. #include "prottest.h"
  26. #define MSG_SIZE 2048
  27. BOOL
  28. LsCsp_UnpackServerCert(
  29. LPBYTE pbCert,
  30. DWORD dwCertLen,
  31. PHydra_Server_Cert pServerCert );
  32. ///////////////////////////////////////////////////////////////////////////////
  33. HANDLE g_hServerEvent = NULL, g_hClientEvent = NULL;
  34. BYTE * pbServerMessage = NULL;
  35. PBYTE ClientMessage;//[MSG_SIZE];
  36. DWORD cbServerMessage = 0;
  37. DWORD cbClientMessage;
  38. LPBYTE g_pbPubKey = NULL;
  39. DWORD g_cbPubKey = 0;
  40. Hydra_Server_Cert g_ServerCertificate;
  41. const BYTE g_abServerCertificate[184] = {
  42. 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  43. 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x5C, 0x00,
  44. 0x52, 0x53, 0x41, 0x31, 0x48, 0x00, 0x00, 0x00,
  45. 0x00, 0x02, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00,
  46. 0x01, 0x00, 0x01, 0x00, 0x83, 0x76, 0x5B, 0x09,
  47. 0x8F, 0xC1, 0x74, 0x12, 0x1B, 0xD3, 0x4E, 0x72,
  48. 0x72, 0x4D, 0xBE, 0xCE, 0x55, 0x1D, 0x29, 0x3D,
  49. 0x0E, 0xED, 0x28, 0x09, 0x50, 0x66, 0x32, 0xFA,
  50. 0x1D, 0xD2, 0xCC, 0x42, 0xDE, 0x5B, 0x4E, 0x3C,
  51. 0x35, 0xF6, 0x73, 0x5B, 0x0C, 0x0D, 0xB0, 0xA6,
  52. 0x4D, 0x76, 0xBA, 0xC0, 0x88, 0x5F, 0xC4, 0x67,
  53. 0x0B, 0xB8, 0xA3, 0x23, 0xA6, 0xC7, 0x79, 0xBD,
  54. 0x80, 0xD1, 0xA8, 0x75, 0x00, 0x00, 0x00, 0x00,
  55. 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x48, 0x00,
  56. 0x19, 0x50, 0x2E, 0x2E, 0x82, 0xB4, 0xEB, 0xB3,
  57. 0x87, 0x85, 0xB9, 0x31, 0x4C, 0x29, 0x07, 0x05,
  58. 0xD7, 0x37, 0x99, 0x86, 0x15, 0x30, 0x56, 0xE4,
  59. 0x47, 0x7A, 0x2C, 0x2F, 0x4C, 0xBD, 0xF0, 0x37,
  60. 0xD3, 0x94, 0x01, 0xC8, 0x73, 0xEA, 0x5C, 0x2C,
  61. 0x3F, 0x60, 0x27, 0x1E, 0x5D, 0xA9, 0x54, 0x32,
  62. 0xDC, 0x49, 0xA4, 0x7E, 0x26, 0xAF, 0xEA, 0x07,
  63. 0xCA, 0x4E, 0xE9, 0x95, 0x8E, 0x66, 0xF0, 0x33,
  64. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  65. };
  66. ///////////////////////////////////////////////////////////////////////////////
  67. void
  68. _stdcall
  69. HydraServerThread();
  70. void
  71. _stdcall
  72. HydraClientThread();
  73. BOOL
  74. TsIssueLicenseExpirationWarning(
  75. LPDWORD lpdwDays,
  76. PTS_LICENSE_INFO pTsLicenseInfo );
  77. BOOL
  78. FileTimeToUnixTime(
  79. LPFILETIME pft,
  80. time_t * t );
  81. VOID
  82. DisplayLicenseMessage(
  83. DWORD dwDaysLeft );
  84. ///////////////////////////////////////////////////////////////////////////////
  85. void _cdecl main(int argc, char *argv[])
  86. {
  87. DWORD ServerThreadID, ClientThreadID;
  88. HANDLE ThreadHandles[2];
  89. DWORD WaitStatus = 0;
  90. Binary_Blob CertBlob;
  91. LICENSE_STATUS Status;
  92. DWORD dwFlag = CERT_DATE_DONT_VALIDATE;
  93. //
  94. // Create the server and client events
  95. //
  96. ThreadHandles[0] = NULL;
  97. ThreadHandles[1] = NULL;
  98. g_hServerEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
  99. g_hClientEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
  100. if( ( NULL == g_hServerEvent ) || ( NULL == g_hClientEvent ) )
  101. {
  102. printf( "Cannot create events\n" );
  103. return;
  104. }
  105. InitializeLicenseLib( TRUE );
  106. memset( &CertBlob, 0, sizeof( CertBlob ) );
  107. //
  108. // get the X509 certificate
  109. //
  110. Status = GetServerCertificate( CERT_TYPE_X509, &CertBlob, KEY_EXCHANGE_ALG_RSA );
  111. if( LICENSE_STATUS_OK == Status )
  112. {
  113. Status = VerifyCertChain(
  114. CertBlob.pBlob,
  115. CertBlob.wBlobLen,
  116. NULL,
  117. &g_cbPubKey,
  118. &dwFlag );
  119. if( LICENSE_STATUS_INSUFFICIENT_BUFFER == Status )
  120. {
  121. g_pbPubKey = LocalAlloc( LPTR, g_cbPubKey );
  122. if( NULL == g_pbPubKey )
  123. {
  124. goto done;
  125. }
  126. Status = VerifyCertChain( CertBlob.pBlob,
  127. CertBlob.wBlobLen,
  128. g_pbPubKey,
  129. &g_cbPubKey,
  130. &dwFlag );
  131. }
  132. if( LICENSE_STATUS_OK != Status )
  133. {
  134. printf( "Cannot verify X509 certificate chain: %x\n", Status );
  135. goto done;
  136. }
  137. }
  138. //
  139. // unpack the hardcoded certificate
  140. //
  141. if( !LsCsp_UnpackServerCert( ( LPBYTE )g_abServerCertificate, sizeof( g_abServerCertificate ),
  142. &g_ServerCertificate ) )
  143. {
  144. printf( "cannot unpack server certificate\n" );
  145. }
  146. //
  147. // Create the server and client threads
  148. //
  149. ThreadHandles[0] = CreateThread( NULL,
  150. 0,
  151. ( LPTHREAD_START_ROUTINE )HydraServerThread,
  152. NULL,
  153. 0,
  154. &ServerThreadID );
  155. ThreadHandles[1] = CreateThread( NULL,
  156. 0,
  157. ( LPTHREAD_START_ROUTINE )HydraClientThread,
  158. NULL,
  159. 0,
  160. &ClientThreadID );
  161. //
  162. // wait for the server and client thread to die
  163. //
  164. WaitStatus = WaitForMultipleObjects( 2, ThreadHandles, TRUE, INFINITE );
  165. //
  166. // close the event handles
  167. //
  168. done:
  169. if( g_hServerEvent )
  170. {
  171. CloseHandle( g_hServerEvent );
  172. }
  173. if( g_hClientEvent )
  174. {
  175. CloseHandle( g_hClientEvent );
  176. }
  177. if( ThreadHandles[0] )
  178. {
  179. CloseHandle( ThreadHandles[0] );
  180. }
  181. if( ThreadHandles[1] )
  182. {
  183. CloseHandle( ThreadHandles[1] );
  184. }
  185. ShutdownLicenseLib();
  186. if( pbServerMessage )
  187. {
  188. LocalFree( pbServerMessage );
  189. }
  190. if( CertBlob.pBlob )
  191. {
  192. LocalFree( CertBlob.pBlob );
  193. }
  194. if( g_pbPubKey )
  195. {
  196. LocalFree( g_pbPubKey );
  197. }
  198. return;
  199. }
  200. #define HYDRA_40_LICENSING_PROTOCOL_FLAG 0
  201. #define HYDRA_40_LICENSING_PROTOCOL_VERSION LICENSE_PROTOCOL_VERSION_1_0 | PREAMBLE_VERSION_2_0
  202. ///////////////////////////////////////////////////////////////////////////////
  203. void
  204. _stdcall
  205. HydraServerThread()
  206. {
  207. LICENSE_STATUS Status;
  208. HANDLE hContext = NULL;
  209. LICENSE_CAPABILITIES LicenseCap;
  210. TS_LICENSE_INFO
  211. TsLicenseInfo;
  212. Status = CreateLicenseContext( &hContext, LICENSE_CONTEXT_PER_SEAT );
  213. if( LICENSE_STATUS_OK != Status )
  214. {
  215. printf( "HydraServerThread(): error creating license context\n" );
  216. return;
  217. }
  218. memset( &LicenseCap, 0, sizeof( LicenseCap ) );
  219. LicenseCap.KeyExchangeAlg = KEY_EXCHANGE_ALG_RSA;
  220. #ifdef HYDRA_40_TEST
  221. //
  222. // talking to a Hydra 4.0 client
  223. //
  224. LicenseCap.ProtocolVer = HYDRA_40_LICENSING_PROTOCOL_VERSION;
  225. LicenseCap.fAuthenticateServer = TRUE;
  226. Status = InitializeLicenseContext(
  227. hContext,
  228. 0,
  229. &LicenseCap );
  230. #else
  231. #ifdef HYDRA_50_NO_SERVER_AUTHEN_X509
  232. //
  233. // talking to a Hydra 5.0 client and don't send certificate
  234. //
  235. LicenseCap.ProtocolVer = LICENSE_HIGHEST_PROTOCOL_VERSION;
  236. LicenseCap.fAuthenticateServer = FALSE;
  237. LicenseCap.CertType = CERT_TYPE_X509;
  238. Status = InitializeLicenseContext(
  239. hContext,
  240. 0,
  241. &LicenseCap );
  242. #else
  243. #ifdef HYDRA_50_NO_SERVER_AUTHEN_PROPRIETORY
  244. //
  245. // talking to a Hydra 5.0 client and don't send certificate
  246. //
  247. LicenseCap.ProtocolVer = LICENSE_HIGHEST_PROTOCOL_VERSION;
  248. LicenseCap.fAuthenticateServer = FALSE;
  249. LicenseCap.CertType = CERT_TYPE_PROPRIETORY;
  250. Status = InitializeLicenseContext(
  251. hContext,
  252. 0,
  253. &LicenseCap );
  254. #else
  255. //
  256. // talking to a Hydra 5.0 client and also send certificate
  257. //
  258. LicenseCap.ProtocolVer = LICENSE_HIGHEST_PROTOCOL_VERSION;
  259. LicenseCap.fAuthenticateServer = TRUE;
  260. Status = InitializeLicenseContext(
  261. hContext,
  262. 0,
  263. &LicenseCap );
  264. #endif // HYDRA_50_NO_SERVER_AUTHEN_X509
  265. #endif // HYDRA_50_NO_SERVER_AUTHEN_PROPRIETORY
  266. #endif // HYDRA_40_TEST
  267. if( LICENSE_STATUS_OK != Status )
  268. {
  269. printf( "HydraServerThread(): cannot initialize license context: %x\n", Status );
  270. goto done;
  271. }
  272. Status = AcceptLicenseContext( hContext,
  273. 0,
  274. NULL,
  275. &cbServerMessage,
  276. &pbServerMessage );
  277. while( LICENSE_STATUS_CONTINUE == Status )
  278. {
  279. SetEvent( g_hClientEvent );
  280. WaitForSingleObject( g_hServerEvent, INFINITE );
  281. if( pbServerMessage )
  282. {
  283. LocalFree( pbServerMessage );
  284. pbServerMessage = NULL;
  285. cbServerMessage = 0;
  286. }
  287. Status = AcceptLicenseContext( hContext,
  288. cbClientMessage,
  289. ClientMessage,
  290. &cbServerMessage,
  291. &pbServerMessage );
  292. }
  293. done:
  294. if( hContext )
  295. {
  296. DWORD
  297. dwDaysLeft = 0;
  298. memset( &TsLicenseInfo, 0, sizeof( TsLicenseInfo ) );
  299. Status = QueryLicenseInfo( hContext, &TsLicenseInfo );
  300. if( LICENSE_STATUS_OK != Status )
  301. {
  302. printf( "HydraSeverThread: cannot query license info: %x\n", Status );
  303. }
  304. if( TsIssueLicenseExpirationWarning( &dwDaysLeft, &TsLicenseInfo ) )
  305. {
  306. DisplayLicenseMessage( dwDaysLeft );
  307. }
  308. FreeLicenseInfo( &TsLicenseInfo );
  309. DeleteLicenseContext( hContext );
  310. }
  311. if( ( LICENSE_STATUS_ISSUED_LICENSE == Status ) ||
  312. ( LICENSE_STATUS_OK == Status ) )
  313. {
  314. //
  315. // issueing a license or the license has been successfully validated
  316. //
  317. printf( "HydraServerThread: Protocol completed successfully\n" );
  318. SetEvent( g_hClientEvent );
  319. }
  320. else if( LICENSE_STATUS_SEND_ERROR == Status )
  321. {
  322. printf( "HydraServerThread: sending error to client\n" );
  323. SetEvent( g_hClientEvent );
  324. }
  325. else
  326. {
  327. printf( "HydraServerThread: protocol error: aborted\n" );
  328. }
  329. return;
  330. }
  331. ///////////////////////////////////////////////////////////////////////////////
  332. void
  333. _stdcall
  334. HydraClientThread()
  335. {
  336. LICENSE_STATUS Status;
  337. HANDLE hContext;
  338. #ifdef HYDRA_50_NO_SERVER_AUTHEN_X509
  339. //
  340. // no server authentication required. Use the public key in the
  341. // X509 certificate
  342. //
  343. Status = LicenseInitializeContext(
  344. &hContext,
  345. LICENSE_CONTEXT_NO_SERVER_AUTHENTICATION );
  346. if( LICENSE_STATUS_OK != Status )
  347. {
  348. printf( "Cannot initialize client context: %x\n", Status );
  349. return;
  350. }
  351. //
  352. // set the public key
  353. //
  354. Status = LicenseSetPublicKey(
  355. hContext,
  356. g_cbPubKey,
  357. g_pbPubKey );
  358. if( LICENSE_STATUS_OK != Status )
  359. {
  360. printf( "Cannot set public key: %x\n", Status );
  361. goto done;
  362. }
  363. #else
  364. #ifdef HYDRA_50_NO_SERVER_AUTHEN_PROPRIETORY
  365. //
  366. // no server authentication required. Use the proprietory certificate
  367. //
  368. Status = LicenseInitializeContext(
  369. &hContext,
  370. LICENSE_CONTEXT_NO_SERVER_AUTHENTICATION );
  371. if( LICENSE_STATUS_OK != Status )
  372. {
  373. printf( "Cannot initialize client context: %x\n", Status );
  374. return;
  375. }
  376. //
  377. // set the proprietory certificate
  378. //
  379. Status = LicenseSetCertificate(
  380. hContext,
  381. &g_ServerCertificate );
  382. if( LICENSE_STATUS_OK != Status )
  383. {
  384. printf( "cannot set certificate: %x\n", Status );
  385. goto done;
  386. }
  387. #else
  388. //
  389. // hydra 4.0/5.0 licensing protocol.with certificate validation
  390. //
  391. Status = LicenseInitializeContext(
  392. &hContext,
  393. 0 );
  394. if( LICENSE_STATUS_OK != Status )
  395. {
  396. printf( "Cannot initialize client context: %x\n", Status );
  397. return;
  398. }
  399. #endif
  400. #endif
  401. if( NULL == hContext )
  402. {
  403. printf( "HydraClientThread(): error creating license context\n" );
  404. return;
  405. }
  406. if( LICENSE_STATUS_OK != Status )
  407. {
  408. printf( "HydraClientThread(): error setting certificate: %x\n", Status );
  409. LicenseDeleteContext( hContext );
  410. return;
  411. }
  412. WaitForSingleObject( g_hClientEvent, INFINITE );
  413. cbClientMessage = 0;//MSG_SIZE;
  414. if( LICENSE_STATUS_CONTINUE != (Status = LicenseAcceptContext( hContext,
  415. 0,
  416. pbServerMessage,
  417. cbServerMessage,
  418. NULL,//ClientMessage,
  419. &cbClientMessage )) )
  420. {
  421. printf("Error handling Server request\n");
  422. return;
  423. }
  424. if( NULL == (ClientMessage = (PBYTE)GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT, cbClientMessage)) )
  425. {
  426. printf("Error allocating memory\n");
  427. return;
  428. }
  429. //memset(ClientMessage, 0x00, cbClientMessage);
  430. Status = LicenseAcceptContext(hContext,
  431. 0,
  432. pbServerMessage,
  433. cbServerMessage,
  434. ClientMessage,
  435. &cbClientMessage);
  436. while( LICENSE_STATUS_CONTINUE == Status )
  437. {
  438. SetEvent( g_hServerEvent );
  439. WaitForSingleObject( g_hClientEvent, INFINITE );
  440. cbClientMessage = 0;
  441. if(ClientMessage)
  442. {
  443. GlobalFree((HGLOBAL)ClientMessage);
  444. ClientMessage = NULL;
  445. }
  446. Status = LicenseAcceptContext( hContext,
  447. 0,
  448. pbServerMessage,
  449. cbServerMessage,
  450. NULL,//ClientMessage,
  451. &cbClientMessage);
  452. if( ( Status == LICENSE_STATUS_OK ) || ( Status != LICENSE_STATUS_CONTINUE ) )
  453. {
  454. break;
  455. }
  456. if( NULL == (ClientMessage = (PBYTE)GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT, cbClientMessage)) )
  457. {
  458. printf("Error allocating memory\n");
  459. break;
  460. }
  461. memset(ClientMessage, 0x00, cbClientMessage);
  462. Status = LicenseAcceptContext( hContext,
  463. 0,
  464. pbServerMessage,
  465. cbServerMessage,
  466. ClientMessage,
  467. &cbClientMessage );
  468. }
  469. done:
  470. LicenseDeleteContext( hContext );
  471. if( LICENSE_STATUS_OK == Status )
  472. {
  473. printf( "HydraClientThread: license protocol completed successfully\n" );
  474. }
  475. else
  476. {
  477. printf( "HydraClientThread: license protocol failed: 0x%x\n", Status );
  478. }
  479. if( ClientMessage )
  480. {
  481. GlobalFree( ( HGLOBAL )ClientMessage );
  482. }
  483. return;
  484. }
  485. #define SECONDS_IN_A_DAY 86400 // number of seconds in a day
  486. #define ISSUE_LICENSE_WARNING_PERIOD 150 // days to expiration when warning should be issued.
  487. ///////////////////////////////////////////////////////////////////////////////
  488. BOOL
  489. TsIssueLicenseExpirationWarning(
  490. LPDWORD lpdwDays,
  491. PTS_LICENSE_INFO pTsLicenseInfo )
  492. {
  493. time_t
  494. Expiration,
  495. CurrentTime;
  496. DWORD
  497. dwDaysLeft;
  498. if( NULL == pTsLicenseInfo )
  499. {
  500. return( FALSE );
  501. }
  502. if( FALSE == pTsLicenseInfo->fTempLicense )
  503. {
  504. return( FALSE );
  505. }
  506. //
  507. // The client license is temporary, figure out how long more
  508. // the license is valid
  509. //
  510. if( FALSE == FileTimeToUnixTime( &pTsLicenseInfo->NotAfter, &Expiration ) )
  511. {
  512. return( FALSE );
  513. }
  514. time( &CurrentTime );
  515. if( CurrentTime >= Expiration )
  516. {
  517. //
  518. // license already expired
  519. //
  520. *lpdwDays = 0xFFFFFFFF;
  521. return( TRUE );
  522. }
  523. dwDaysLeft = ( Expiration - CurrentTime ) / SECONDS_IN_A_DAY;
  524. printf( "Number of days left for temporary license expiration: %d\n", dwDaysLeft );
  525. if( ISSUE_LICENSE_WARNING_PERIOD >= dwDaysLeft )
  526. {
  527. *lpdwDays = dwDaysLeft;
  528. return( TRUE );
  529. }
  530. return( FALSE );
  531. }
  532. ///////////////////////////////////////////////////////////////////////////////
  533. BOOL
  534. FileTimeToUnixTime(
  535. LPFILETIME pft,
  536. time_t * t )
  537. {
  538. SYSTEMTIME sysTime;
  539. struct tm gmTime;
  540. if( FileTimeToSystemTime( pft, &sysTime ) == FALSE )
  541. {
  542. return( FALSE );
  543. }
  544. if( sysTime.wYear >= 2038 )
  545. {
  546. *t = INT_MAX;
  547. }
  548. else
  549. {
  550. //
  551. // Unix time support up to 2038/1/18
  552. // restrict any expiration data
  553. //
  554. memset( &gmTime, 0, sizeof( gmTime ) );
  555. gmTime.tm_sec = sysTime.wSecond;
  556. gmTime.tm_min = sysTime.wMinute;
  557. gmTime.tm_hour = sysTime.wHour;
  558. gmTime.tm_year = sysTime.wYear - 1900;
  559. gmTime.tm_mon = sysTime.wMonth - 1;
  560. gmTime.tm_mday = sysTime.wDay;
  561. *t = mktime( &gmTime );
  562. }
  563. return( *t != ( time_t )-1 );
  564. }
  565. ///////////////////////////////////////////////////////////////////////////////
  566. VOID
  567. DisplayLicenseMessage(
  568. DWORD dwDaysLeft )
  569. {
  570. TCHAR
  571. szMsgCaption[512],
  572. szMsgTitle[256];
  573. HMODULE
  574. hModule = GetModuleHandle( NULL );
  575. LPDWORD
  576. lpdw;
  577. TCHAR
  578. tszDays[ 10 ];
  579. if( 0xFFFFFFFF == dwDaysLeft )
  580. {
  581. printf( "Temporary License has expired!\n" );
  582. LoadString( hModule, STR_TEMP_LICENSE_EXPIRED_MSG, szMsgCaption, 512 );
  583. }
  584. else
  585. {
  586. printf( "%d days left before temporary license expires\n", dwDaysLeft );
  587. //
  588. // convert the number of days left to UNICODE character
  589. //
  590. _ultow( dwDaysLeft, tszDays, 10 );
  591. lpdw = ( LPDWORD )&tszDays[0];
  592. //
  593. // prepare license about to expire message
  594. //
  595. LoadString( hModule, STR_TEMP_LICENSE_EXPIRATION_MSG, szMsgCaption, 512 );
  596. FormatMessage(
  597. FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  598. szMsgCaption,
  599. 0,
  600. MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
  601. ( LPTSTR )szMsgCaption,
  602. sizeof( szMsgCaption ),
  603. ( va_list * )&lpdw );
  604. }
  605. //
  606. // prepare message title
  607. //
  608. LoadString( hModule, STR_TEMP_LICENSE_MSG_TITLE, szMsgTitle, 256 );
  609. MessageBox( NULL, szMsgCaption, szMsgTitle, MB_OK );
  610. return;
  611. }