Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1692 lines
74 KiB

  1. /****************************************************************************/
  2. /* asmapi.c */
  3. /* */
  4. /* Security Manager API */
  5. /* */
  6. /* Copyright (C) 1997-1999 Microsoft Corporation */
  7. /****************************************************************************/
  8. #include <precomp.h>
  9. #pragma hdrstop
  10. #define TRC_FILE "asmapi"
  11. #define pTRCWd (pRealSMHandle->pWDHandle)
  12. #include <adcg.h>
  13. #include <aprot.h>
  14. #include <acomapi.h>
  15. #include <nwdwapi.h>
  16. #include <anmapi.h>
  17. #include <asmint.h>
  18. #include <slicense.h>
  19. #include <regapi.h>
  20. #define DC_INCLUDE_DATA
  21. #include <asmdata.c>
  22. #undef DC_INCLUDE_DATA
  23. /****************************************************************************/
  24. /* Name: SM_GetDataSize */
  25. /* */
  26. /* Purpose: Returns size of per-instance SM data required */
  27. /* */
  28. /* Returns: size of data required */
  29. /* */
  30. /* Operation: SM stores per-instance data in a piece of memory allocated */
  31. /* by WDW. This function returns the size of the data required. */
  32. /* A pointer to this data (the 'SM Handle') is passed into all */
  33. /* subsequent SM functions. */
  34. /****************************************************************************/
  35. unsigned RDPCALL SM_GetDataSize(void)
  36. {
  37. DC_BEGIN_FN("SM_GetDataSize");
  38. DC_END_FN();
  39. return(sizeof(SM_HANDLE_DATA) + NM_GetDataSize());
  40. } /* SM_GetDataSize */
  41. /****************************************************************************/
  42. /* Name: SM_GetEncryptionMethods */
  43. /* */
  44. /* Purpose: Return the security settings supported by this server for use */
  45. /* in shadowing operations. The shadow target server dictates */
  46. /* the final selected method & level. */
  47. /* */
  48. /* Params: pSMHandle - SM handle */
  49. /****************************************************************************/
  50. VOID RDPCALL SM_GetEncryptionMethods(PVOID pSMHandle, PRNS_UD_CS_SEC pSecurityData)
  51. {
  52. PSM_HANDLE_DATA pRealSMHandle = (PSM_HANDLE_DATA)pSMHandle;
  53. ULONG ulMethods ;
  54. DC_BEGIN_FN("SM_SM_GetEncryptionMethods");
  55. // Allow a FIPS shadow client to remote control servers with lesser
  56. // encryption strength
  57. ulMethods = pRealSMHandle->encryptionMethodsSupported;
  58. if (ulMethods & SM_FIPS_ENCRYPTION_FLAG) {
  59. ulMethods |= (SM_128BIT_ENCRYPTION_FLAG | SM_40BIT_ENCRYPTION_FLAG | SM_56BIT_ENCRYPTION_FLAG);
  60. TRC_ALT((TB, "Allow FIPS client to shadow a lower security target: %lx",
  61. ulMethods));
  62. }
  63. else {
  64. // Allow a 128-bit shadow client to remote control servers with lesser
  65. // encryption strength
  66. if (ulMethods & SM_128BIT_ENCRYPTION_FLAG) {
  67. ulMethods |= (SM_40BIT_ENCRYPTION_FLAG | SM_56BIT_ENCRYPTION_FLAG);
  68. TRC_ALT((TB, "Allow 128-bit client to shadow a lower security target: %lx",
  69. ulMethods));
  70. }
  71. }
  72. if( !pRealSMHandle->frenchClient ) {
  73. pSecurityData->encryptionMethods = ulMethods;
  74. pSecurityData->extEncryptionMethods = 0;
  75. }
  76. else {
  77. pSecurityData->encryptionMethods = 0;
  78. pSecurityData->extEncryptionMethods = ulMethods;
  79. }
  80. DC_END_FN();
  81. return;
  82. }
  83. /****************************************************************************/
  84. /* Name: SM_GetDefaultSecuritySettings */
  85. /* */
  86. /* Purpose: Returns the security settings supported by this server */
  87. /* for shadowing operations. */
  88. /* */
  89. /* Params: pClientSecurityData - GCC user data identical to a standard */
  90. /* conference connection. */
  91. /****************************************************************************/
  92. NTSTATUS RDPCALL SM_GetDefaultSecuritySettings(PRNS_UD_CS_SEC pClientSecurityData)
  93. {
  94. pClientSecurityData->header.type = RNS_UD_CS_SEC_ID;
  95. pClientSecurityData->header.length = sizeof(*pClientSecurityData);
  96. pClientSecurityData->encryptionMethods =
  97. SM_40BIT_ENCRYPTION_FLAG |
  98. SM_56BIT_ENCRYPTION_FLAG |
  99. SM_128BIT_ENCRYPTION_FLAG |
  100. SM_FIPS_ENCRYPTION_FLAG;
  101. pClientSecurityData->extEncryptionMethods = 0;
  102. return STATUS_SUCCESS;
  103. }
  104. /****************************************************************************/
  105. /* Name: SM_Init */
  106. /* */
  107. /* Purpose: Initialize SM */
  108. /* */
  109. /* Params: pSMHandle - SM handle */
  110. /* pWDHandle - WD Handle (to be passed back on WDW_SMCallback) */
  111. /****************************************************************************/
  112. NTSTATUS RDPCALL SM_Init(PVOID pSMHandle,
  113. PTSHARE_WD pWDHandle,
  114. BOOLEAN bOldShadow)
  115. {
  116. BOOL rc;
  117. NTSTATUS status = STATUS_UNSUCCESSFUL;
  118. unsigned i;
  119. unsigned regRc;
  120. PSM_HANDLE_DATA pRealSMHandle = (PSM_HANDLE_DATA)pSMHandle;
  121. INT32 regValue;
  122. OBJECT_ATTRIBUTES ObjectAttributes;
  123. UNICODE_STRING UnicodeString;
  124. static UINT32 keyInfoBuffer[16];
  125. ULONG keyInfoLength;
  126. HANDLE RegistryKeyHandle;
  127. PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
  128. DC_BEGIN_FN("SM_Init");
  129. SM_CHECK_STATE(SM_EVT_INIT);
  130. /************************************************************************/
  131. /* Store the WDW Handle before we do anything else, as we can't trace */
  132. /* until we do so. */
  133. /************************************************************************/
  134. pRealSMHandle->pWDHandle = pWDHandle;
  135. pRealSMHandle->bForwardDataToSC = FALSE;
  136. /************************************************************************/
  137. /* Get default DONTDISPLAYLASTUSERNAME setting */
  138. /************************************************************************/
  139. pWDHandle->fDontDisplayLastUserName = FALSE;
  140. RtlInitUnicodeString(&UnicodeString, W2K_GROUP_POLICY_WINLOGON_KEY);
  141. InitializeObjectAttributes(&ObjectAttributes,
  142. &UnicodeString,
  143. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  144. NULL,
  145. NULL);
  146. status = ZwOpenKey(&RegistryKeyHandle, GENERIC_READ, &ObjectAttributes);
  147. if (NT_SUCCESS(status)) {
  148. RtlInitUnicodeString(&UnicodeString, WIN_DONTDISPLAYLASTUSERNAME);
  149. KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)keyInfoBuffer;
  150. status = ZwQueryValueKey(RegistryKeyHandle,
  151. &UnicodeString,
  152. KeyValuePartialInformation,
  153. KeyValueInformation,
  154. sizeof(keyInfoBuffer),
  155. &keyInfoLength);
  156. // For W2K the value should be a DWORD.
  157. if ((NT_SUCCESS(status)) &&
  158. (KeyValueInformation->Type == REG_DWORD) &&
  159. (KeyValueInformation->DataLength >= sizeof(DWORD))) {
  160. pWDHandle->fDontDisplayLastUserName =
  161. (BOOLEAN)(*(PDWORD)(KeyValueInformation->Data) == 1);
  162. }
  163. ZwClose(RegistryKeyHandle);
  164. }
  165. // Starting with W2K the place where the DontDislpayLastUserName policy
  166. // is store has moved to another key (W2K_GROUP_POLICY_WINLOGON_KEY). But
  167. // we still have to look at the old key in case we could not read the
  168. // value in the post W2K key (the policy is not definde). We want to follow
  169. // the winlogon behavior in the console.
  170. // In case there is a value set in the new policy key we will use that
  171. // value. In case there isn't one we look in the old place. As I said this
  172. // is what winlogon does.
  173. //
  174. if (!NT_SUCCESS(status)) {
  175. RtlInitUnicodeString(&UnicodeString, WINLOGON_KEY);
  176. InitializeObjectAttributes(&ObjectAttributes,
  177. &UnicodeString,
  178. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  179. NULL,
  180. NULL);
  181. status = ZwOpenKey(&RegistryKeyHandle, GENERIC_READ, &ObjectAttributes);
  182. if (NT_SUCCESS(status)) {
  183. RtlInitUnicodeString(&UnicodeString, WIN_DONTDISPLAYLASTUSERNAME);
  184. KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)keyInfoBuffer;
  185. status = ZwQueryValueKey(RegistryKeyHandle,
  186. &UnicodeString,
  187. KeyValuePartialInformation,
  188. KeyValueInformation,
  189. sizeof(keyInfoBuffer),
  190. &keyInfoLength);
  191. if (NT_SUCCESS(status)) {
  192. pWDHandle->fDontDisplayLastUserName =
  193. (BOOLEAN)(KeyValueInformation->Data[0] == '1');
  194. }
  195. ZwClose(RegistryKeyHandle);
  196. }
  197. }
  198. /************************************************************************/
  199. /* We don't run without encryption in a retail build */
  200. /************************************************************************/
  201. TRC_NRM((TB, "encryption level is %d", pRealSMHandle->encryptionLevel));
  202. if (pRealSMHandle->encryptionLevel < 1)
  203. {
  204. TRC_ALT((TB, "Forcing encryption back to level 1!"));
  205. pRealSMHandle->encryptionLevel = 1;
  206. }
  207. #ifdef INSTRUM_TRACK_DISCARDED
  208. pRealSMHandle->nDiscardNonVCPDUWhenDead = 0;
  209. pRealSMHandle->nDiscardPDUBadState = 0;
  210. pRealSMHandle->nDiscardVCDataWhenDead = 0;
  211. #endif
  212. if (pRealSMHandle->encryptionLevel == 0) {
  213. TRC_ALT((TB, "Not encrypting"));
  214. pRealSMHandle->encryptionMethodsSupported = 0;
  215. pRealSMHandle->encrypting = FALSE;
  216. pRealSMHandle->encryptDisplayData = FALSE;
  217. pRealSMHandle->encryptingLicToClient = FALSE;
  218. pRealSMHandle->encryptionMethodSelected = 0;
  219. pRealSMHandle->frenchClient = FALSE;
  220. pRealSMHandle->recvdClientRandom = FALSE;
  221. pRealSMHandle->bSessionKeysMade = FALSE;
  222. pRealSMHandle->encryptHeaderLen = 0;
  223. pRealSMHandle->encryptHeaderLenIfForceEncrypt = sizeof(RNS_SECURITY_HEADER1);
  224. }
  225. else {
  226. pRealSMHandle->encrypting = TRUE;
  227. pRealSMHandle->frenchClient = FALSE;
  228. TRC_NRM((TB, "Encrypting"));
  229. /********************************************************************/
  230. /* encrypt the display data if encryptionLevel is 2 (or above). */
  231. /********************************************************************/
  232. if (pRealSMHandle->encryptionLevel == 1) {
  233. pRealSMHandle->encryptDisplayData = FALSE;
  234. pRealSMHandle->encryptHeaderLen = sizeof(RNS_SECURITY_HEADER);
  235. pRealSMHandle->encryptHeaderLenIfForceEncrypt = sizeof(RNS_SECURITY_HEADER1);
  236. TRC_NRM((TB, "Displaydata not encrypted"));
  237. }
  238. else {
  239. pRealSMHandle->encryptDisplayData = TRUE;
  240. pRealSMHandle->encryptHeaderLen = sizeof(RNS_SECURITY_HEADER1);
  241. }
  242. /********************************************************************/
  243. /* for down level compatibility, support both 40bit, 56bit */
  244. /* and 128bit default. */
  245. /********************************************************************/
  246. pRealSMHandle->encryptionMethodsSupported =
  247. SM_128BIT_ENCRYPTION_FLAG |
  248. SM_56BIT_ENCRYPTION_FLAG |
  249. SM_40BIT_ENCRYPTION_FLAG |
  250. SM_FIPS_ENCRYPTION_FLAG;
  251. /********************************************************************/
  252. /* encrypt 128bit and above if encryptionLevel is 3 */
  253. /********************************************************************/
  254. if (pRealSMHandle->encryptionLevel == 3) {
  255. pRealSMHandle->encryptionMethodsSupported =
  256. SM_128BIT_ENCRYPTION_FLAG | SM_FIPS_ENCRYPTION_FLAG;
  257. }
  258. /********************************************************************/
  259. /* encrypt in FIPS only if encryption level is 4 or above. */
  260. /********************************************************************/
  261. if (pRealSMHandle->encryptionLevel >= 4) {
  262. pRealSMHandle->encryptionMethodsSupported = SM_FIPS_ENCRYPTION_FLAG;
  263. }
  264. TRC_NRM((TB, "Encryption methods supported %08lx: Level %ld\n",
  265. pRealSMHandle->encryptionMethodsSupported,
  266. pRealSMHandle->encryptionLevel));
  267. /********************************************************************/
  268. /* initally set the encryption method selected as */
  269. /* SM_56BIT_ENCRYPTION_FLAG, later it will be set according to the */
  270. /* client support. */
  271. /********************************************************************/
  272. pRealSMHandle->encryptionMethodSelected = SM_56BIT_ENCRYPTION_FLAG;
  273. /********************************************************************/
  274. /* misc init. */
  275. /********************************************************************/
  276. pRealSMHandle->recvdClientRandom = FALSE;
  277. pRealSMHandle->bSessionKeysMade = FALSE;
  278. }
  279. /************************************************************************/
  280. /* We do not know the certificate type used in the key exchange till */
  281. /* after the exchange has taken place. */
  282. /************************************************************************/
  283. pRealSMHandle->CertType = CERT_TYPE_INVALID;
  284. #ifdef USE_LICENSE
  285. /************************************************************************/
  286. /* Initialize the Server license manager */
  287. /************************************************************************/
  288. pRealSMHandle->pLicenseHandle = SLicenseInit();
  289. if (!pRealSMHandle->pLicenseHandle)
  290. {
  291. TRC_ERR((TB, "Failed to initialize License Manager"));
  292. DC_QUIT;
  293. }
  294. pWDHandle->pSLicenseHandle = pRealSMHandle->pLicenseHandle;
  295. #endif
  296. /************************************************************************/
  297. /* Initialize the console buffer stuff */
  298. /************************************************************************/
  299. InitializeListHead(&pRealSMHandle->consoleBufferList);
  300. pRealSMHandle->consoleBufferCount = 0;
  301. /************************************************************************/
  302. /* Finally, initialize the Network Manager */
  303. /************************************************************************/
  304. rc = NM_Init(pRealSMHandle->pWDHandle->pNMInfo,
  305. pSMHandle,
  306. pWDHandle,
  307. pWDHandle->hDomainKernel);
  308. if (!rc)
  309. {
  310. TRC_ERR((TB, "Failed to init NM"));
  311. DC_QUIT;
  312. }
  313. /************************************************************************/
  314. /* Update the state */
  315. /************************************************************************/
  316. SM_SET_STATE(SM_STATE_INITIALIZED);
  317. /************************************************************************/
  318. /* All worked */
  319. /************************************************************************/
  320. status = STATUS_SUCCESS;
  321. DC_EXIT_POINT:
  322. /************************************************************************/
  323. /* If anything failed, clean up. Must be done after calling */
  324. /* FreeContextBuffer as this clears the function table. */
  325. /************************************************************************/
  326. if (!NT_SUCCESS(status))
  327. {
  328. TRC_ERR((TB, "Something failed - clean up"));
  329. SMFreeInitResources(pRealSMHandle);
  330. }
  331. DC_END_FN();
  332. return(status);
  333. } /* SM_Init */
  334. /****************************************************************************/
  335. /* Name: SM_Term */
  336. /****************************************************************************/
  337. void RDPCALL SM_Term(PVOID pSMHandle)
  338. {
  339. PSM_HANDLE_DATA pRealSMHandle = (PSM_HANDLE_DATA)pSMHandle;
  340. DC_BEGIN_FN("SM_Term");
  341. /************************************************************************/
  342. /* SM_Term is called from WD_Close. This can be called on the */
  343. /* listening stack (and maybe in other situations) where SM_Init has */
  344. /* not been called. Check for state != SM_STATE_STARTED before going */
  345. /* any further. */
  346. /* */
  347. /* AND DON'T TRACE IF SM_INIT HASN'T BEEN CALLED. */
  348. /************************************************************************/
  349. if (pRealSMHandle->state == SM_STATE_STARTED)
  350. {
  351. DC_QUIT;
  352. }
  353. /************************************************************************/
  354. /* Free connection resources */
  355. /************************************************************************/
  356. TRC_NRM((TB, "Free connection resources"));
  357. SMFreeConnectResources(pRealSMHandle);
  358. /************************************************************************/
  359. /* Free initialization resources */
  360. /************************************************************************/
  361. TRC_NRM((TB, "Free initialization resources"));
  362. SMFreeInitResources(pRealSMHandle);
  363. #ifdef USE_LICENSE
  364. /************************************************************************/
  365. /* Terminate License Manager */
  366. /************************************************************************/
  367. SLicenseTerm(pRealSMHandle->pLicenseHandle);
  368. #endif
  369. /************************************************************************/
  370. /* Terminate Network Manager */
  371. /************************************************************************/
  372. NM_Term(pRealSMHandle->pWDHandle->pNMInfo);
  373. /************************************************************************/
  374. /* Terminate FIPS */
  375. /************************************************************************/
  376. TSFIPS_Term(&(pRealSMHandle->FIPSData));
  377. /************************************************************************/
  378. /* Free the console buffers */
  379. /************************************************************************/
  380. while (!IsListEmpty(&pRealSMHandle->consoleBufferList)) {
  381. PSM_CONSOLE_BUFFER pBlock;
  382. pBlock = CONTAINING_RECORD(pRealSMHandle->consoleBufferList.Flink, SM_CONSOLE_BUFFER, links);
  383. RemoveEntryList(&pBlock->links);
  384. COM_Free(pBlock);
  385. };
  386. /************************************************************************/
  387. /* Update the state */
  388. /************************************************************************/
  389. SM_SET_STATE(SM_STATE_STARTED);
  390. DC_EXIT_POINT:
  391. DC_END_FN();
  392. } /* SM_Term */
  393. /****************************************************************************/
  394. /* Name: SM_Connect */
  395. /* */
  396. /* Purpose: Accept or Reject an incoming Client */
  397. /* */
  398. /* Returns: TRUE - Connect started OK */
  399. /* FALSE - Connect failed to start */
  400. /* */
  401. /* Params: ppSMHandle - handle for subsequent SM calls on behalf of */
  402. /* this Client */
  403. /* pUserDataIn - SM user data received from Client */
  404. /* pNetUserData - Net user data received from Client */
  405. /* bOldShadow - indicates this is a B3 shadow request */
  406. /* */
  407. /* Operation: Note that this function completes asynchronously. The caller */
  408. /* must wait for an SM_CB_CONNECTED or SM_CB_DISCONNECTED */
  409. /* callback to find out whether the Connect succeeded or failed. */
  410. /****************************************************************************/
  411. NTSTATUS RDPCALL SM_Connect(PVOID pSMHandle,
  412. PRNS_UD_CS_SEC pUserDataIn,
  413. PRNS_UD_CS_NET pNetUserData,
  414. BOOLEAN bOldShadow)
  415. {
  416. NTSTATUS status = STATUS_SUCCESS;
  417. BOOL rc = FALSE;
  418. PSM_HANDLE_DATA pRealSMHandle = (PSM_HANDLE_DATA)pSMHandle;
  419. UINT32 encMethodPicked = 0;
  420. DC_BEGIN_FN("SM_Connect");
  421. SM_CHECK_STATE(SM_EVT_CONNECT);
  422. pRealSMHandle->pUserData = NULL;
  423. /************************************************************************/
  424. /* pick a matching encryption method. */
  425. /************************************************************************/
  426. TRC_ALT((TB, "Client supports encryption: %lx",
  427. pUserDataIn->encryptionMethods));
  428. TRC_NRM((TB, "Server supports encryption: %lx",
  429. pRealSMHandle->encryptionMethodsSupported));
  430. /************************************************************************/
  431. /* if the server does not require any encryption .. */
  432. /************************************************************************/
  433. if( pRealSMHandle->encryptionMethodsSupported == 0 ) {
  434. encMethodPicked = 0;
  435. goto DC_ENC_PICKED;
  436. }
  437. //
  438. // French Client (old and new) set the encryptionMethods value 0.
  439. //
  440. if (pUserDataIn->encryptionMethods == 0) {
  441. pRealSMHandle->frenchClient = TRUE;
  442. //
  443. // check to see the request is from a new client, if so
  444. // use the new field to set the appropriate encryption level.
  445. //
  446. if( pUserDataIn->header.length >= sizeof(RNS_UD_CS_SEC) ) {
  447. pUserDataIn->encryptionMethods = pUserDataIn->extEncryptionMethods;
  448. }
  449. else {
  450. //
  451. // force old client to use 40-bit encryption.
  452. //
  453. pUserDataIn->encryptionMethods = SM_40BIT_ENCRYPTION_FLAG;
  454. }
  455. /************************************************************************/
  456. /* pick a matching encryption method. */
  457. /************************************************************************/
  458. TRC_ALT((TB, "French Client supports encryption: %lx",
  459. pUserDataIn->encryptionMethods));
  460. }
  461. /************************************************************************/
  462. /* if the client only supports FIPS */
  463. /************************************************************************/
  464. if (pUserDataIn->encryptionMethods == SM_FIPS_ENCRYPTION_FLAG) {
  465. /********************************************************************/
  466. /* if the server supports FIPS .... */
  467. /********************************************************************/
  468. if (pRealSMHandle->encryptionMethodsSupported & SM_FIPS_ENCRYPTION_FLAG) {
  469. encMethodPicked = SM_FIPS_ENCRYPTION_FLAG;
  470. goto DC_ENC_PICKED;
  471. }
  472. }
  473. /********************************************************************/
  474. /* if the server only supports FIPS .... */
  475. /********************************************************************/
  476. if (pRealSMHandle->encryptionMethodsSupported == SM_FIPS_ENCRYPTION_FLAG) {
  477. /************************************************************************/
  478. /* if the client supports FIPS */
  479. /************************************************************************/
  480. if (pUserDataIn->encryptionMethods & SM_FIPS_ENCRYPTION_FLAG) {
  481. encMethodPicked = SM_FIPS_ENCRYPTION_FLAG;
  482. goto DC_ENC_PICKED;
  483. }
  484. }
  485. /************************************************************************/
  486. /* if the client supports 128 bit */
  487. /************************************************************************/
  488. if (pUserDataIn->encryptionMethods & SM_128BIT_ENCRYPTION_FLAG) {
  489. /********************************************************************/
  490. /* if the server supports 128bit .... */
  491. /********************************************************************/
  492. if (pRealSMHandle->encryptionMethodsSupported &
  493. SM_128BIT_ENCRYPTION_FLAG) {
  494. encMethodPicked = SM_128BIT_ENCRYPTION_FLAG;
  495. goto DC_ENC_PICKED;
  496. }
  497. }
  498. /************************************************************************/
  499. /* if the client supports 56 bit */
  500. /************************************************************************/
  501. if( pUserDataIn->encryptionMethods & SM_56BIT_ENCRYPTION_FLAG ) {
  502. /********************************************************************/
  503. /* if the server supports 56bit ... */
  504. /********************************************************************/
  505. if( pRealSMHandle->encryptionMethodsSupported &
  506. SM_56BIT_ENCRYPTION_FLAG ) {
  507. encMethodPicked = SM_56BIT_ENCRYPTION_FLAG;
  508. goto DC_ENC_PICKED;
  509. }
  510. }
  511. /************************************************************************/
  512. /* if the client supports 40 bit */
  513. /************************************************************************/
  514. if( pUserDataIn->encryptionMethods & SM_40BIT_ENCRYPTION_FLAG ) {
  515. /********************************************************************/
  516. /* if the server supports 40bit ... */
  517. /********************************************************************/
  518. if( pRealSMHandle->encryptionMethodsSupported &
  519. SM_40BIT_ENCRYPTION_FLAG ) {
  520. encMethodPicked = SM_40BIT_ENCRYPTION_FLAG;
  521. goto DC_ENC_PICKED;
  522. }
  523. }
  524. /************************************************************************/
  525. /* if we are here, we did not find a match */
  526. /************************************************************************/
  527. TRC_ERR((TB, "Failed to match encryption package: %lx",
  528. pUserDataIn->encryptionMethods));
  529. status = STATUS_ENCRYPTION_FAILED;
  530. /****************************************************************/
  531. /* Log an error and disconnect the Client */
  532. /****************************************************************/
  533. if (pRealSMHandle->pWDHandle->StackClass == Stack_Primary) {
  534. WDW_LogAndDisconnect(
  535. pRealSMHandle->pWDHandle, TRUE,
  536. Log_RDP_ENC_EncPkgMismatch,
  537. NULL,
  538. 0);
  539. }
  540. DC_QUIT;
  541. DC_ENC_PICKED:
  542. TRC_ALT((TB, "Encryption Method=%d, Level=%ld, Display=%ld",
  543. encMethodPicked,
  544. pRealSMHandle->encryptionLevel,
  545. pRealSMHandle->encryptDisplayData));
  546. /************************************************************************/
  547. /* remember the encryption method that we picked. */
  548. /************************************************************************/
  549. pRealSMHandle->encryptionMethodSelected = encMethodPicked;
  550. // For FIPS, do initialization
  551. // Even the enc method is not FIPS, we need to do initialization since we might
  552. // shadow a FIPS later
  553. if (TSFIPS_Init(&(pRealSMHandle->FIPSData))) {
  554. TRC_NRM((TB, "Init Fips succeed\n"));
  555. }
  556. else {
  557. TRC_ERR((TB, "Init Fips Failed\n"));
  558. // This is only a fatal failure if FIPS was selected as the encryption
  559. // method. If we chose something other than FIPS, then we should
  560. // proceed, although shadowing a FIPS session later should fail.
  561. //
  562. if (SM_FIPS_ENCRYPTION_FLAG == encMethodPicked)
  563. {
  564. status = STATUS_ENCRYPTION_FAILED;
  565. DC_QUIT;
  566. }
  567. }
  568. /************************************************************************/
  569. /* Build user data to return to Client */
  570. /************************************************************************/
  571. pRealSMHandle->pUserData =
  572. (PRNS_UD_SC_SEC)COM_Malloc(sizeof(RNS_UD_SC_SEC));
  573. if (pRealSMHandle->pUserData == NULL)
  574. {
  575. TRC_ERR((TB, "Failed to allocated %d bytes for user data",
  576. sizeof(RNS_UD_SC_SEC)));
  577. status = STATUS_NO_MEMORY;
  578. DC_QUIT;
  579. }
  580. pRealSMHandle->pUserData->header.type = RNS_UD_SC_SEC_ID;
  581. pRealSMHandle->pUserData->header.length = sizeof(RNS_UD_SC_SEC);
  582. pRealSMHandle->pUserData->encryptionMethod =
  583. (bOldShadow ? 0xffffffff : encMethodPicked);
  584. pRealSMHandle->pUserData->encryptionLevel =
  585. pRealSMHandle->encryptionLevel;
  586. /************************************************************************/
  587. /* Call Network Manager */
  588. /************************************************************************/
  589. SM_SET_STATE(SM_STATE_NM_CONNECTING);
  590. TRC_NRM((TB, "Connect to Network Manager"));
  591. rc = NM_Connect(pRealSMHandle->pWDHandle->pNMInfo, pNetUserData);
  592. if (rc != TRUE)
  593. {
  594. status = STATUS_CANCELLED;
  595. DC_QUIT;
  596. }
  597. // Shadow/passthru stacks start out with no encryption. If the target end
  598. // determines that the client server supports encryption, an encrypted
  599. // context will be set up by rdpwsx.
  600. if (pRealSMHandle->pWDHandle->StackClass != Stack_Primary) {
  601. pRealSMHandle->pWDHandle->connected = TRUE;
  602. pRealSMHandle->encrypting = FALSE;
  603. pRealSMHandle->encryptDisplayData = FALSE;
  604. pRealSMHandle->encryptHeaderLen = 0;
  605. pRealSMHandle->encryptHeaderLenIfForceEncrypt = 0;
  606. SM_SET_STATE(SM_STATE_CONNECTED);
  607. SM_SET_STATE(SM_STATE_SC_REGISTERED);
  608. SM_Dead(pRealSMHandle, FALSE);
  609. TRC_ALT((TB, "%s stack: Suspending encryption during key exchange",
  610. pRealSMHandle->pWDHandle->StackClass == Stack_Shadow ?
  611. "Shadow" : "Passthru"));
  612. }
  613. DC_EXIT_POINT:
  614. /************************************************************************/
  615. /* If anything failed, release resources */
  616. /************************************************************************/
  617. if (status != STATUS_SUCCESS)
  618. {
  619. TRC_ERR((TB, "Failed - free connect resources"));
  620. SMFreeConnectResources(pRealSMHandle);
  621. }
  622. DC_END_FN();
  623. return status;
  624. } /* SM_Connect */
  625. /****************************************************************************/
  626. /* Name: SM_Disconnect */
  627. /* */
  628. /* Purpose: Disconnect from a Client */
  629. /* */
  630. /* Returns: TRUE - Disconnect started OK */
  631. /* FALSE - Disconnect failed */
  632. /* */
  633. /* Params: pSMHandle - SM handle */
  634. /* */
  635. /* Operation: Detach the user from the domain. */
  636. /* Note that this function completes asynchronously. The caller */
  637. /* must wait for an SM_CB_DISCONNECTED callback to find whether */
  638. /* the Disconnect succeeded or failed. */
  639. /****************************************************************************/
  640. BOOL RDPCALL SM_Disconnect(PVOID pSMHandle)
  641. {
  642. BOOL rc = FALSE;
  643. PSM_HANDLE_DATA pRealSMHandle = (PSM_HANDLE_DATA)pSMHandle;
  644. DC_BEGIN_FN("SM_Disconnect");
  645. if (SM_CHECK_STATE_Q(SM_EVT_DISCONNECT)) {
  646. // Call Network Layer.
  647. SM_SET_STATE(SM_STATE_DISCONNECTING);
  648. rc = NM_Disconnect(pRealSMHandle->pWDHandle->pNMInfo);
  649. }
  650. DC_END_FN();
  651. return rc;
  652. }
  653. void SM_BreakConnectionWorker(PTSHARE_WD pTSWd, PVOID pParam)
  654. {
  655. NTSTATUS status;
  656. ICA_CHANNEL_COMMAND Command;
  657. PSM_HANDLE_DATA pRealSMHandle = (PSM_HANDLE_DATA)pTSWd->pSmInfo;
  658. DC_BEGIN_FN("SM_BreakConnectionWorker");
  659. Command.Header.Command = ICA_COMMAND_BROKEN_CONNECTION;
  660. Command.BrokenConnection.Reason = Broken_Unexpected;
  661. Command.BrokenConnection.Source = BrokenSource_Server;
  662. status = IcaChannelInput(pTSWd->pContext, Channel_Command, 0, NULL, (BYTE *)&Command, sizeof(Command));
  663. if (!NT_SUCCESS(status)) {
  664. TRC_NRM((TB, "Can't send ICA_COMMAND_BROKEN_CONNECTION, error code 0x%08x", status));
  665. }
  666. DC_END_FN();
  667. }
  668. /****************************************************************************/
  669. /* Name: SM_AllocBuffer */
  670. /* */
  671. /* Purpose: Allocate a buffer */
  672. /* */
  673. /* Returns: TRUE - buffer allocated OK */
  674. /* FALSE - failed to allocate buffer */
  675. /* */
  676. /* Params: pSMHandle - SM Handle */
  677. /* ppBuffer - pointer to packet (returned) */
  678. /* bufferLen - length of buffer */
  679. /* fForceEncrypt - Always encrypt or not */
  680. /* Used only if encryptDisplayData is FALSE */
  681. /* i.e., encryptionLevel is less than 2 */
  682. /****************************************************************************/
  683. NTSTATUS __fastcall SM_AllocBuffer(PVOID pSMHandle,
  684. PPVOID ppBuffer,
  685. UINT32 bufferLen,
  686. BOOLEAN fWait,
  687. BOOLEAN fForceEncrypt)
  688. {
  689. NTSTATUS status;
  690. PSM_HANDLE_DATA pRealSMHandle = (PSM_HANDLE_DATA)pSMHandle;
  691. PRNS_SECURITY_HEADER2 pSecHeader2;
  692. UINT32 newBufferLen, padLen;
  693. DC_BEGIN_FN("SM_AllocBuffer");
  694. if (SM_CHECK_STATE_Q(SM_EVT_ALLOCBUFFER)) {
  695. if (pRealSMHandle->pWDHandle->StackClass != Stack_Console) {
  696. // If FIPS, adjust the BufferLen to the whole FIPS_BLOCK_LEN size
  697. if (pRealSMHandle->encryptionMethodSelected == SM_FIPS_ENCRYPTION_FLAG) {
  698. newBufferLen = TSFIPS_AdjustDataLen(bufferLen);
  699. padLen = newBufferLen - bufferLen;
  700. bufferLen = newBufferLen;
  701. }
  702. // Add enough space for a security header. We always send at least
  703. // a short security header.
  704. if (pRealSMHandle->encryptDisplayData) {
  705. bufferLen += pRealSMHandle->encryptHeaderLen;
  706. }
  707. else {
  708. if (!fForceEncrypt) {
  709. bufferLen += pRealSMHandle->encryptHeaderLen;
  710. }
  711. else {
  712. bufferLen += pRealSMHandle->encryptHeaderLenIfForceEncrypt;
  713. }
  714. }
  715. status = NM_AllocBuffer(pRealSMHandle->pWDHandle->pNMInfo, ppBuffer,
  716. bufferLen, fWait);
  717. if ( STATUS_SUCCESS == status ) {
  718. TRC_NRM((TB, "Alloc buffer size %d at %p", bufferLen,
  719. *ppBuffer));
  720. // If FIPS, fill in padSize in Header
  721. if (pRealSMHandle->encryptionMethodSelected == SM_FIPS_ENCRYPTION_FLAG) {
  722. pSecHeader2 = (PRNS_SECURITY_HEADER2)(*ppBuffer);
  723. pSecHeader2->padlen = (TSUINT8)padLen;
  724. }
  725. // Adjust return pointer for security header.
  726. if (pRealSMHandle->encryptDisplayData) {
  727. *ppBuffer = (PVOID)((PBYTE)(*ppBuffer) +
  728. pRealSMHandle->encryptHeaderLen);
  729. }
  730. else {
  731. if (!fForceEncrypt) {
  732. *ppBuffer = (PVOID)((PBYTE)(*ppBuffer) +
  733. pRealSMHandle->encryptHeaderLen);
  734. }
  735. else {
  736. *ppBuffer = (PVOID)((PBYTE)(*ppBuffer) +
  737. pRealSMHandle->encryptHeaderLenIfForceEncrypt);
  738. }
  739. }
  740. }
  741. else
  742. {
  743. if( status == STATUS_IO_TIMEOUT && TRUE == fWait ) {
  744. //
  745. // WARNING : Disconnect client on first allocation failure, different
  746. // result ranging from TS client AV to immediate lock up on
  747. // re-connect if this scheme is changed disconnect on 2nd
  748. // try, 3rd try ...
  749. //
  750. TRC_NRM((TB, "Failed to alloc buffer size %d, disconnecting client", bufferLen));
  751. // 254514 STRESS: TS: Tdtcp!TdRawWrite needs synchronization with the write complete routine
  752. // Calling the following function will hold the connection lock in tdtcp TDSyncWrite to wait
  753. // for all pending IRP to finish. This will cause deadlock in the system.
  754. //WDW_LogAndDisconnect(pRealSMHandle->pWDHandle, FALSE, Log_RDP_AllocOutBuf, NULL, 0);
  755. // return STATUS_IO_TIMEOUT back to caller,
  756. // looks like we use this return code.
  757. if (!pRealSMHandle->bDisconnectWorkerSent) {
  758. status = IcaQueueWorkItem(pRealSMHandle->pWDHandle->pContext,
  759. SM_BreakConnectionWorker,
  760. 0,
  761. ICALOCK_DRIVER);
  762. if (!NT_SUCCESS(status)) {
  763. TRC_NRM((TB, "IcaQueueWorkItem failed, error code 0x%08x", status));
  764. } else {
  765. pRealSMHandle->bDisconnectWorkerSent = TRUE;
  766. }
  767. }
  768. status = STATUS_IO_TIMEOUT;
  769. }
  770. else {
  771. // NM_AllocBuffer will have traced appropriately if the alloc
  772. // failed, no need for TRC_ERR here.
  773. TRC_NRM((TB, "Failed to alloc buffer size %d", bufferLen));
  774. }
  775. }
  776. }
  777. else {
  778. PSM_CONSOLE_BUFFER pBlock;
  779. // For a console stack, just alloc a suitable block - we're not
  780. // actually going to send it!
  781. TRC_NRM((TB, "console stack requesting %d bytes", bufferLen));
  782. *ppBuffer = NULL;
  783. if (!IsListEmpty(&pRealSMHandle->consoleBufferList)) {
  784. pBlock = CONTAINING_RECORD(pRealSMHandle->consoleBufferList.Flink, SM_CONSOLE_BUFFER, links);
  785. do {
  786. // we could improve this by taking the smaller of the suitable blocks
  787. // it can be also faster if we order the list
  788. if (pBlock->length >= bufferLen) {
  789. RemoveEntryList(&pBlock->links);
  790. pRealSMHandle->consoleBufferCount -= 1;
  791. *ppBuffer = pBlock->buffer;
  792. break;
  793. }
  794. pBlock = CONTAINING_RECORD(pBlock->links.Flink, SM_CONSOLE_BUFFER, links);
  795. } while(pBlock != (PSM_CONSOLE_BUFFER)(&pRealSMHandle->consoleBufferList));
  796. }
  797. if (*ppBuffer == NULL) {
  798. // allocate a new block
  799. pBlock = COM_Malloc(sizeof(SM_CONSOLE_BUFFER) + bufferLen);
  800. if (pBlock != NULL) {
  801. pBlock->buffer = (PVOID)((PBYTE)pBlock + sizeof(SM_CONSOLE_BUFFER));
  802. pBlock->length = bufferLen;
  803. *ppBuffer = pBlock->buffer;
  804. } else {
  805. *ppBuffer = NULL;
  806. }
  807. }
  808. if (*ppBuffer != NULL) {
  809. TRC_NRM((TB, "and returning buffer at %p", *ppBuffer));
  810. status = STATUS_SUCCESS;
  811. }
  812. else {
  813. TRC_ERR((TB, "failed to alloc buffer"));
  814. status = STATUS_NO_MEMORY;
  815. }
  816. }
  817. }
  818. else {
  819. status = STATUS_UNSUCCESSFUL; // right error code?
  820. }
  821. DC_END_FN();
  822. return status;
  823. } /* SM_AllocBuffer */
  824. /****************************************************************************/
  825. /* Name: SM_FreeBuffer */
  826. /* */
  827. /* Purpose: Free a buffer */
  828. /* */
  829. /* Params: pSMHandle - SM Handle */
  830. /* pBuffer - buffer to free */
  831. /* fForceEncrypt - Always encrypt or not */
  832. /* Used only if encryptDisplayData is FALSE */
  833. /* i.e., encryptionLevel is less than 2 */
  834. /****************************************************************************/
  835. void __fastcall SM_FreeBuffer(PVOID pSMHandle, PVOID pBuffer, BOOLEAN fForceEncrypt)
  836. {
  837. PSM_HANDLE_DATA pRealSMHandle = (PSM_HANDLE_DATA)pSMHandle;
  838. DC_BEGIN_FN("SM_FreeBuffer");
  839. // Note that, unlike SM_AllocBuffer, we don't check the state table here,
  840. // since if we were able to allocate the buffer, we should always be
  841. // able to free it. Otherwise we may end up leaking buffers during
  842. // warn states.
  843. if (pRealSMHandle->pWDHandle->StackClass != Stack_Console) {
  844. // Adjust for security header.
  845. if (pRealSMHandle->encryptDisplayData) {
  846. pBuffer = (PVOID)((PBYTE)pBuffer -
  847. pRealSMHandle->encryptHeaderLen);
  848. }
  849. else {
  850. if (!fForceEncrypt) {
  851. pBuffer = (PVOID)((PBYTE)pBuffer -
  852. pRealSMHandle->encryptHeaderLen);
  853. }
  854. else {
  855. pBuffer = (PVOID)((PBYTE)pBuffer -
  856. pRealSMHandle->encryptHeaderLenIfForceEncrypt);
  857. }
  858. }
  859. TRC_NRM((TB, "Free buffer at %p", pBuffer));
  860. NM_FreeBuffer(pRealSMHandle->pWDHandle->pNMInfo, pBuffer);
  861. }
  862. else {
  863. PSM_CONSOLE_BUFFER pBlock;
  864. pBlock = (PSM_CONSOLE_BUFFER)((PBYTE)pBuffer - sizeof(SM_CONSOLE_BUFFER));
  865. // For console session, insert it in the list of freed blocks.
  866. TRC_NRM((TB, "console stack freeing buffer at %p", pBuffer));
  867. // Since this block was freshly used,
  868. // insert it at the beginning of the list.
  869. InsertHeadList(&pRealSMHandle->consoleBufferList, &pBlock->links);
  870. if (pRealSMHandle->consoleBufferCount >= 2) {
  871. PVOID listEntry;
  872. // Free a buffer since we have enough buffers.
  873. // Remove and free the last one (tail of the list),
  874. // assuming it's the less used.
  875. listEntry = RemoveTailList(&pRealSMHandle->consoleBufferList);
  876. pBlock = CONTAINING_RECORD(listEntry, SM_CONSOLE_BUFFER, links);
  877. COM_Free(pBlock);
  878. } else {
  879. pRealSMHandle->consoleBufferCount += 1;
  880. }
  881. }
  882. DC_END_FN();
  883. } /* SM_FreeBuffer */
  884. /****************************************************************************/
  885. // SM_SendData
  886. //
  887. // Sends a network buffer. Note that upper layers assume that, if the send
  888. // fails, the buffer will get deallocated. Returns FALSE on failure.
  889. //
  890. // Params: pSMHandle - SM Handle
  891. // pData - data to send
  892. // dataLen - length if data to send
  893. // priority - priority to use
  894. // channelID - channel ID (ignored in this version)
  895. // bFastPathOutput - whether pData contains fast-path output
  896. // flags - the flag that should be put in RNS_SECURITY_HEADER.flags
  897. // fForceEncrypt - Always encrypt or not
  898. // Used only if encryptDisplayData is FALSE
  899. // i.e., encryptionLevel is less than 2
  900. /****************************************************************************/
  901. BOOL __fastcall SM_SendData(
  902. PVOID pSMHandle,
  903. PVOID pData,
  904. UINT32 dataLen,
  905. UINT32 priority,
  906. UINT32 channelID,
  907. BOOL bFastPathOutput,
  908. UINT16 flags,
  909. BOOLEAN fForceEncrypt)
  910. {
  911. BOOL rc = FALSE;
  912. PRNS_SECURITY_HEADER pSecHeader;
  913. PRNS_SECURITY_HEADER2 pSecHeader2;
  914. PSM_HANDLE_DATA pRealSMHandle = (PSM_HANDLE_DATA)pSMHandle;
  915. UINT32 sendLen;
  916. BOOL fUseSafeChecksum = FALSE;
  917. UINT32 encryptHeaderLen = 0;
  918. DC_BEGIN_FN("SM_SendData");
  919. if (SM_CHECK_STATE_Q(SM_EVT_SENDDATA)) {
  920. if (pRealSMHandle->pWDHandle->StackClass != Stack_Console) {
  921. // Send the packet unchanged if we're not encrypting at all.
  922. if ((!pRealSMHandle->encrypting) && (!fForceEncrypt)) {
  923. TRC_DATA_DBG("Send never-encrypted data", pData, dataLen);
  924. rc = NM_SendData(pRealSMHandle->pWDHandle->pNMInfo,
  925. (BYTE *)pData, dataLen, priority, channelID,
  926. bFastPathOutput | NM_NO_SECURITY_HEADER);
  927. DC_QUIT;
  928. }
  929. // Get interesting pointers and lengths.
  930. if ((!pRealSMHandle->encryptDisplayData) && !fForceEncrypt) {
  931. // S->C is not encrypted
  932. encryptHeaderLen = pRealSMHandle->encryptHeaderLen;
  933. sendLen = dataLen + encryptHeaderLen;
  934. }
  935. else {
  936. if (pRealSMHandle->encryptDisplayData) {
  937. // S->C is encrypted
  938. encryptHeaderLen = pRealSMHandle->encryptHeaderLen;
  939. }
  940. else {
  941. // S->C is not encrypted, but we want to encrypt this packet
  942. encryptHeaderLen = pRealSMHandle->encryptHeaderLenIfForceEncrypt;
  943. }
  944. if (pRealSMHandle->encryptionMethodSelected == SM_FIPS_ENCRYPTION_FLAG) {
  945. pSecHeader2 = (PRNS_SECURITY_HEADER2)((PBYTE)pData - encryptHeaderLen);
  946. pSecHeader2->padlen = (TSUINT8)TSFIPS_AdjustDataLen(dataLen) - dataLen;
  947. sendLen = dataLen + encryptHeaderLen + pSecHeader2->padlen;
  948. pSecHeader2->length = sizeof(RNS_SECURITY_HEADER2);
  949. pSecHeader2->version = TSFIPS_VERSION1;
  950. }
  951. else {
  952. sendLen = dataLen + encryptHeaderLen;
  953. }
  954. }
  955. pSecHeader = (PRNS_SECURITY_HEADER)((PBYTE)pData - encryptHeaderLen);
  956. // Encrypt display data if we are asked to do so.
  957. if ((!pRealSMHandle->encryptDisplayData) && !fForceEncrypt) {
  958. pSecHeader->flags = 0;
  959. // We are implicitly not setting TS_OUTPUT_FASTPATH_ENCRYPTED
  960. // bit in bFastPathOutput before passing to NM_SendData.
  961. TRC_DBG((TB, "Data not encrypted"));
  962. }
  963. else {
  964. // Check to see if we need to update the session key.
  965. if (pRealSMHandle->encryptCount == UPDATE_SESSION_KEY_COUNT) {
  966. rc = TRUE;
  967. // Don't need to update the session key if using FIPS
  968. if (pRealSMHandle->encryptionMethodSelected != SM_FIPS_ENCRYPTION_FLAG) {
  969. rc = UpdateSessionKey(
  970. pRealSMHandle->startEncryptKey,
  971. pRealSMHandle->currentEncryptKey,
  972. pRealSMHandle->encryptionMethodSelected,
  973. pRealSMHandle->keyLength,
  974. &pRealSMHandle->rc4EncryptKey,
  975. pRealSMHandle->encryptionLevel);
  976. }
  977. if (rc) {
  978. // Reset counter.
  979. pRealSMHandle->encryptCount = 0;
  980. }
  981. else {
  982. TRC_ERR((TB, "SM failed to update session key"));
  983. WDW_LogAndDisconnect(
  984. pRealSMHandle->pWDHandle, TRUE,
  985. Log_RDP_ENC_UpdateSessionKeyFailed,
  986. NULL,
  987. 0);
  988. DC_QUIT;
  989. }
  990. }
  991. TRC_DATA_DBG("Data buffer before encryption", pData, dataLen);
  992. //
  993. // Disable the safe checksumming in the shadow pipe as there
  994. // is currently no way to reliably do caps negotiation in the
  995. // pipe.
  996. //
  997. // This is not an issue because we don't have fastpath in
  998. // the shadow pipe and as a result of this we're not vulnerable
  999. // to the checksum frequency analysis security vulnerability.
  1000. //
  1001. //
  1002. fUseSafeChecksum = pRealSMHandle->useSafeChecksumMethod &&
  1003. (pRealSMHandle->pWDHandle->StackClass == Stack_Primary);
  1004. if (pRealSMHandle->encryptionMethodSelected == SM_FIPS_ENCRYPTION_FLAG) {
  1005. rc = TSFIPS_EncryptData(
  1006. &(pRealSMHandle->FIPSData),
  1007. pData,
  1008. dataLen + pSecHeader2->padlen,
  1009. pSecHeader2->padlen,
  1010. pSecHeader2->dataSignature,
  1011. pRealSMHandle->totalEncryptCount);
  1012. }
  1013. else {
  1014. rc = EncryptData(
  1015. pRealSMHandle->encryptionLevel,
  1016. pRealSMHandle->currentEncryptKey,
  1017. &pRealSMHandle->rc4EncryptKey,
  1018. pRealSMHandle->keyLength,
  1019. pData,
  1020. dataLen,
  1021. pRealSMHandle->macSaltKey,
  1022. ((PRNS_SECURITY_HEADER1)pSecHeader)->dataSignature,
  1023. fUseSafeChecksum,
  1024. pRealSMHandle->totalEncryptCount);
  1025. }
  1026. if (rc) {
  1027. TRC_DBG((TB, "Data encrypted"));
  1028. TRC_DATA_DBG("Data buffer after encryption", pData,
  1029. dataLen);
  1030. // Successfully encrypted a packet, increment the
  1031. // encryption counter and set the header.
  1032. pRealSMHandle->encryptCount++;
  1033. pRealSMHandle->totalEncryptCount++;
  1034. TRC_ASSERT(((flags == RNS_SEC_ENCRYPT) ||
  1035. (flags == RDP_SEC_REDIRECTION_PKT3) ||
  1036. (flags == (RNS_SEC_ENCRYPT | RNS_SEC_LICENSE_PKT | RDP_SEC_LICENSE_ENCRYPT_CS))),
  1037. (TB,"SM_SendData shouldn't get this flag %d", flags));
  1038. pSecHeader->flags = flags;
  1039. if (fUseSafeChecksum) {
  1040. bFastPathOutput |= TS_OUTPUT_FASTPATH_SECURE_CHECKSUM;
  1041. pSecHeader->flags |= RDP_SEC_SECURE_CHECKSUM;
  1042. }
  1043. bFastPathOutput |= TS_OUTPUT_FASTPATH_ENCRYPTED;
  1044. }
  1045. else {
  1046. // If we failed, the in-place encryption probably
  1047. // destroyed part or all of the data. The stream is
  1048. // now corrupted, we need to disconnect.
  1049. TRC_ERR((TB, "SM failed to encrypt data"));
  1050. WDW_LogAndDisconnect(
  1051. pRealSMHandle->pWDHandle, TRUE,
  1052. Log_RDP_ENC_EncryptFailed,
  1053. NULL,
  1054. 0);
  1055. DC_QUIT;
  1056. }
  1057. }
  1058. // Send it!
  1059. rc = NM_SendData(pRealSMHandle->pWDHandle->pNMInfo, (BYTE *)pSecHeader,
  1060. sendLen, priority, channelID, bFastPathOutput);
  1061. }
  1062. else {
  1063. // For console session, simply claim to have sent it.
  1064. TRC_NRM((TB, "console stack sending buffer at %p", pData));
  1065. rc = TRUE;
  1066. // Note that we will have to free it.
  1067. SM_FreeBuffer(pSMHandle, pData, fForceEncrypt);
  1068. }
  1069. }
  1070. else {
  1071. // Bad state - we need to free the data.
  1072. TRC_ALT((TB,"Freeing buffer on bad state"));
  1073. SM_FreeBuffer(pSMHandle, pData, fForceEncrypt);
  1074. }
  1075. DC_EXIT_POINT:
  1076. DC_END_FN();
  1077. return rc;
  1078. } /* SM_SendData */
  1079. /****************************************************************************/
  1080. /* Name: SM_Dead */
  1081. /****************************************************************************/
  1082. void RDPCALL SM_Dead(PVOID pSMHandle, BOOL dead)
  1083. {
  1084. PSM_HANDLE_DATA pRealSMHandle = (PSM_HANDLE_DATA)pSMHandle;
  1085. DC_BEGIN_FN("SM_Dead");
  1086. pRealSMHandle->dead = (BOOLEAN)dead;
  1087. NM_Dead(pRealSMHandle->pWDHandle->pNMInfo, dead);
  1088. if (dead)
  1089. {
  1090. /********************************************************************/
  1091. /* SM_Dead(TRUE) can be called in any state to kill SM. Don't */
  1092. /* check the existing state - simply set the new state to */
  1093. /* DISCONNECTING. */
  1094. /********************************************************************/
  1095. TRC_ALT((TB, "SM Dead - change state to DISCONNECTING"));
  1096. SM_SET_STATE(SM_STATE_DISCONNECTING);
  1097. }
  1098. else
  1099. {
  1100. /********************************************************************/
  1101. /* SM_Dead(FALSE) is called on (re)connect. The SM state will be */
  1102. /* - SC_REGISTERED on connect */
  1103. /* - SM_DISCONNECTING on reconnect */
  1104. /* In both cases, set the state to SC_REGISTERED */
  1105. /********************************************************************/
  1106. SM_CHECK_STATE(SM_EVT_ALIVE);
  1107. TRC_ALT((TB, "SM Alive - change state to SC_REGISTERED"));
  1108. SM_SET_STATE(SM_STATE_SC_REGISTERED);
  1109. pRealSMHandle->bDisconnectWorkerSent = FALSE;
  1110. }
  1111. DC_EXIT_POINT:
  1112. DC_END_FN();
  1113. } /* SM_Dead */
  1114. #ifdef USE_LICENSE
  1115. /****************************************************************************/
  1116. /* Name: SM_LicenseOK */
  1117. /****************************************************************************/
  1118. void RDPCALL SM_LicenseOK(PVOID pSMHandle)
  1119. {
  1120. PSM_HANDLE_DATA pRealSMHandle = (PSM_HANDLE_DATA)pSMHandle;
  1121. DC_BEGIN_FN("SM_LicenseOK");
  1122. TRC_NRM((TB, "Licensing Done"));
  1123. SM_SET_STATE(SM_STATE_CONNECTED);
  1124. DC_END_FN();
  1125. } /* SM_LicenseOK */
  1126. #endif
  1127. /****************************************************************************/
  1128. /* Name: SM_GetSecurityData */
  1129. /* */
  1130. /* Purpose: Retrieve security data. This will be the encrypted client */
  1131. /* random for a Primary or Shadow connection. For passthru */
  1132. /* stacks the shadow server random and certificate is returned. */
  1133. /* */
  1134. /* Params: pSMHandle - SM handle */
  1135. /* INOUT PSD_IOCTL - pointer to received IOCtl */
  1136. /****************************************************************************/
  1137. NTSTATUS RDPCALL SM_GetSecurityData(PVOID pSMHandle, PSD_IOCTL pSdIoctl)
  1138. {
  1139. NTSTATUS status;
  1140. PSM_HANDLE_DATA pRealSMHandle = (PSM_HANDLE_DATA)pSMHandle;
  1141. PSECURITYTIMEOUT pSecurityTimeout = (PSECURITYTIMEOUT)
  1142. pSdIoctl->InputBuffer;
  1143. DC_BEGIN_FN("SM_GetSecurityData");
  1144. // Wait for the connected indication from SM.
  1145. TRC_ERR((TB, "About to wait for security data"));
  1146. if (pSdIoctl->InputBufferLength == sizeof(SECURITYTIMEOUT)) {
  1147. status = WDW_WaitForConnectionEvent(pRealSMHandle->pWDHandle,
  1148. pRealSMHandle->pWDHandle->pSecEvent,
  1149. pSecurityTimeout->ulTimeout);
  1150. }
  1151. else {
  1152. status = STATUS_INVALID_PARAMETER;
  1153. TRC_ERR((TB, "Bogus timeout value: %ld", pSecurityTimeout->ulTimeout));
  1154. DC_QUIT;
  1155. }
  1156. TRC_DBG((TB, "Back from wait for security data"));
  1157. if (status != STATUS_SUCCESS) {
  1158. TRC_ERR((TB, "SM connected indication timed out: (%lx), msec=%ld",
  1159. status, pSecurityTimeout->ulTimeout));
  1160. status = STATUS_IO_TIMEOUT;
  1161. DC_QUIT;
  1162. }
  1163. /********************************************************************/
  1164. /* check to see the given buffer is sufficient. */
  1165. /********************************************************************/
  1166. if ((pSdIoctl->OutputBuffer == NULL) ||
  1167. (pSdIoctl->OutputBufferLength <=
  1168. pRealSMHandle->encClientRandomLen)) {
  1169. status = STATUS_BUFFER_TOO_SMALL;
  1170. DC_QUIT;
  1171. }
  1172. /********************************************************************/
  1173. /* check to see security info is available. */
  1174. /********************************************************************/
  1175. TRC_ASSERT((pRealSMHandle->encryptionMethodSelected != 0),
  1176. (TB,"SM_GetSecurityData is called when encryption is not ON"));
  1177. if (pRealSMHandle->encryptionMethodSelected == 0) {
  1178. status = STATUS_UNSUCCESSFUL;
  1179. DC_QUIT;
  1180. }
  1181. TRC_ASSERT((pRealSMHandle->recvdClientRandom == TRUE),
  1182. (TB,"SM_GetSecurityData issued before the client random received"));
  1183. if (pRealSMHandle->recvdClientRandom == FALSE) {
  1184. status = STATUS_UNSUCCESSFUL;
  1185. DC_QUIT;
  1186. }
  1187. if (pRealSMHandle->pEncClientRandom == NULL) {
  1188. status = STATUS_UNSUCCESSFUL;
  1189. DC_QUIT;
  1190. }
  1191. TRC_ASSERT((pRealSMHandle->encClientRandomLen != 0 ),
  1192. (TB,"SM_GetSecurityData invalid pEncClientRandom buffer"));
  1193. if (pRealSMHandle->encClientRandomLen == 0) {
  1194. status = STATUS_UNSUCCESSFUL;
  1195. DC_QUIT;
  1196. }
  1197. /********************************************************************/
  1198. /* copy return data. */
  1199. /********************************************************************/
  1200. memcpy(
  1201. pSdIoctl->OutputBuffer,
  1202. pRealSMHandle->pEncClientRandom,
  1203. pRealSMHandle->encClientRandomLen);
  1204. /********************************************************************/
  1205. /* set returned buffer size. */
  1206. /********************************************************************/
  1207. pSdIoctl->BytesReturned = pRealSMHandle->encClientRandomLen;
  1208. /********************************************************************/
  1209. /* Free up the client pEncClientRandom Buffer, we don't need this */
  1210. /* any more. */
  1211. /********************************************************************/
  1212. COM_Free(pRealSMHandle->pEncClientRandom);
  1213. pRealSMHandle->pEncClientRandom = NULL;
  1214. pRealSMHandle->encClientRandomLen = 0;
  1215. /************************************************************************/
  1216. /* All worked OK */
  1217. /************************************************************************/
  1218. status = STATUS_SUCCESS;
  1219. DC_EXIT_POINT:
  1220. DC_END_FN();
  1221. return (status);
  1222. }
  1223. /****************************************************************************/
  1224. /* Name: SM_SetSecurityData */
  1225. /* */
  1226. /* Purpose: Set security data and compute session key. */
  1227. /* */
  1228. /* Params: pSMHandle - SM Handle */
  1229. /* pSecinfo - pointer to random key pair */
  1230. /****************************************************************************/
  1231. NTSTATUS RDPCALL SM_SetSecurityData(PVOID pSMHandle, PSECINFO pSecInfo)
  1232. {
  1233. BOOL rc;
  1234. NTSTATUS status;
  1235. PSM_HANDLE_DATA pRealSMHandle = (PSM_HANDLE_DATA)pSMHandle;
  1236. DC_BEGIN_FN("SM_SetSecurityData");
  1237. /************************************************************************/
  1238. /* use the given client and server random key pairs and arrive at */
  1239. /* session keys. */
  1240. /************************************************************************/
  1241. if ((pRealSMHandle->pWDHandle->StackClass == Stack_Primary) ||
  1242. (pRealSMHandle->pWDHandle->StackClass == Stack_Shadow)) {
  1243. if (pRealSMHandle->encryptionMethodSelected == SM_FIPS_ENCRYPTION_FLAG) {
  1244. rc = TSFIPS_MakeSessionKeys(&(pRealSMHandle->FIPSData), (LPRANDOM_KEYS_PAIR)&pSecInfo->KeyPair, NULL, FALSE);
  1245. }
  1246. else {
  1247. rc = MakeSessionKeys(
  1248. (LPRANDOM_KEYS_PAIR)&pSecInfo->KeyPair,
  1249. pRealSMHandle->startEncryptKey,
  1250. &pRealSMHandle->rc4EncryptKey,
  1251. pRealSMHandle->startDecryptKey,
  1252. &pRealSMHandle->rc4DecryptKey,
  1253. pRealSMHandle->macSaltKey,
  1254. pRealSMHandle->encryptionMethodSelected,
  1255. &pRealSMHandle->keyLength,
  1256. pRealSMHandle->encryptionLevel );
  1257. }
  1258. }
  1259. // Passthru stack looks like a client
  1260. else {
  1261. if (pRealSMHandle->encryptionMethodSelected == SM_FIPS_ENCRYPTION_FLAG) {
  1262. rc = TSFIPS_MakeSessionKeys(&(pRealSMHandle->FIPSData), (LPRANDOM_KEYS_PAIR)&pSecInfo->KeyPair, NULL, TRUE);
  1263. }
  1264. else {
  1265. rc = MakeSessionKeys(
  1266. (LPRANDOM_KEYS_PAIR)&pSecInfo->KeyPair,
  1267. pRealSMHandle->startDecryptKey,
  1268. &pRealSMHandle->rc4DecryptKey,
  1269. pRealSMHandle->startEncryptKey,
  1270. &pRealSMHandle->rc4EncryptKey,
  1271. pRealSMHandle->macSaltKey,
  1272. pRealSMHandle->encryptionMethodSelected,
  1273. &pRealSMHandle->keyLength,
  1274. pRealSMHandle->encryptionLevel );
  1275. }
  1276. }
  1277. if (!rc) {
  1278. TRC_ERR((TB, "Could not create session keys!"));
  1279. status = STATUS_UNSUCCESSFUL;
  1280. DC_QUIT;
  1281. }
  1282. /************************************************************************/
  1283. /* validate the key length returned. */
  1284. /************************************************************************/
  1285. if (pRealSMHandle->encryptionMethodSelected != SM_FIPS_ENCRYPTION_FLAG) {
  1286. if (pRealSMHandle->encryptionMethodSelected == SM_128BIT_ENCRYPTION_FLAG) {
  1287. TRC_ASSERT((pRealSMHandle->keyLength == MAX_SESSION_KEY_SIZE),
  1288. (TB,"Invalid session key length"));
  1289. }
  1290. else {
  1291. TRC_ASSERT((pRealSMHandle->keyLength == (MAX_SESSION_KEY_SIZE / 2)),
  1292. (TB,"Invalid session key length"));
  1293. }
  1294. /************************************************************************/
  1295. /* copy start session key to current. */
  1296. /************************************************************************/
  1297. memcpy(
  1298. pRealSMHandle->currentEncryptKey,
  1299. pRealSMHandle->startEncryptKey,
  1300. MAX_SESSION_KEY_SIZE);
  1301. memcpy(
  1302. pRealSMHandle->currentDecryptKey,
  1303. pRealSMHandle->startDecryptKey,
  1304. MAX_SESSION_KEY_SIZE);
  1305. }
  1306. pRealSMHandle->encryptCount = 0;
  1307. pRealSMHandle->decryptCount = 0;
  1308. pRealSMHandle->totalDecryptCount = 0;
  1309. pRealSMHandle->totalEncryptCount = 0;
  1310. pRealSMHandle->bSessionKeysMade = TRUE;
  1311. // Whenever we change the state of encrypting, we need to make sure
  1312. // we get the right header size for buffer allocations. If encrypting
  1313. // if FALSE, the header size is zero.
  1314. pRealSMHandle->encrypting = TRUE;
  1315. if (pRealSMHandle->encryptionLevel == 1) {
  1316. pRealSMHandle->encryptHeaderLen = sizeof(RNS_SECURITY_HEADER);
  1317. pRealSMHandle->encryptDisplayData = FALSE;
  1318. if (pRealSMHandle->encryptionMethodSelected == SM_FIPS_ENCRYPTION_FLAG)
  1319. pRealSMHandle->encryptHeaderLenIfForceEncrypt = sizeof(RNS_SECURITY_HEADER2);
  1320. else
  1321. pRealSMHandle->encryptHeaderLenIfForceEncrypt = sizeof(RNS_SECURITY_HEADER1);
  1322. }
  1323. else if (pRealSMHandle->encryptionLevel >= 2) {
  1324. if (pRealSMHandle->encryptionMethodSelected == SM_FIPS_ENCRYPTION_FLAG)
  1325. pRealSMHandle->encryptHeaderLen = sizeof(RNS_SECURITY_HEADER2);
  1326. else
  1327. pRealSMHandle->encryptHeaderLen = sizeof(RNS_SECURITY_HEADER1);
  1328. pRealSMHandle->encryptDisplayData = TRUE;
  1329. }
  1330. TRC_ALT((TB, "%s stack -> encryption %s: level=%ld, method=%ld, display=%ld",
  1331. pRealSMHandle->pWDHandle->StackClass == Stack_Primary ? "Primary" :
  1332. (pRealSMHandle->pWDHandle->StackClass == Stack_Shadow ? "Shadow" :
  1333. "PassThru"),
  1334. rc ? "ON" : "OFF",
  1335. pRealSMHandle->encryptionLevel,
  1336. pRealSMHandle->encryptionMethodSelected,
  1337. pRealSMHandle->encryptDisplayData));
  1338. /************************************************************************/
  1339. /* Remember the certificate type that was used for the key exchange */
  1340. /************************************************************************/
  1341. pRealSMHandle->CertType = pSecInfo->CertType;
  1342. /************************************************************************/
  1343. /* All worked OK */
  1344. /************************************************************************/
  1345. status = STATUS_SUCCESS;
  1346. DC_EXIT_POINT:
  1347. DC_END_FN();
  1348. return (status);
  1349. }
  1350. /****************************************************************************/
  1351. /* Name: SM_SetEncryptionParams */
  1352. /* */
  1353. /* Purpose: Updates the encryption level and method. Used to set */
  1354. /* negotiated encryption level for passthru stack. */
  1355. /* */
  1356. /* Params: pSMHandle - SM Handle */
  1357. /* ulLevel - negotiated encryption level */
  1358. /* ulMethod - negotiated encryption method */
  1359. /****************************************************************************/
  1360. NTSTATUS RDPCALL SM_SetEncryptionParams(
  1361. PVOID pSMHandle,
  1362. ULONG ulLevel,
  1363. ULONG ulMethod)
  1364. {
  1365. PSM_HANDLE_DATA pRealSMHandle = (PSM_HANDLE_DATA)pSMHandle;
  1366. DC_BEGIN_FN("SM_SetEncryptionParams");
  1367. // The passthru stack is simulating a client for the target server. As
  1368. // such, if we negotiated client input encryption, we've got to turn on
  1369. // output encryption for this stack since it conveys all client input
  1370. // to the target server.
  1371. if (ulLevel == 1) {
  1372. ulLevel = 2;
  1373. TRC_ALT((TB, "Passthru stack switching to duplex encryption."));
  1374. }
  1375. pRealSMHandle->encryptionLevel = ulLevel;
  1376. pRealSMHandle->encryptionMethodSelected = ulMethod;
  1377. DC_END_FN();
  1378. return STATUS_SUCCESS;
  1379. }
  1380. /****************************************************************************/
  1381. /* Name: SM_IsSecurityExchangeCompleted */
  1382. /* */
  1383. /* Purpose: Ask SM if the security exchange protocol has already been */
  1384. /* completed. */
  1385. /* */
  1386. /* Returns: TRUE if the protocol has already been completed or FALSE */
  1387. /* otherwise. */
  1388. /* */
  1389. /* Params: pSMHandle - SM Handle */
  1390. /* pCertType - The type of certificate that is used in the */
  1391. /* security exchange. */
  1392. /****************************************************************************/
  1393. BOOL RDPCALL SM_IsSecurityExchangeCompleted(
  1394. PVOID pSMHandle,
  1395. CERT_TYPE *pCertType)
  1396. {
  1397. PSM_HANDLE_DATA pRealSMHandle = (PSM_HANDLE_DATA)pSMHandle;
  1398. DC_BEGIN_FN("SM_IsSecurityExchangeCompleted");
  1399. *pCertType = pRealSMHandle->CertType;
  1400. DC_END_FN();
  1401. return pRealSMHandle->encrypting;
  1402. }
  1403. #ifdef DC_DEBUG
  1404. /****************************************************************************/
  1405. // SMCheckState
  1406. //
  1407. // Debug-only embodiment of the SM_CHECK_STATE logic.
  1408. /****************************************************************************/
  1409. BOOL RDPCALL SMCheckState(PSM_HANDLE_DATA pRealSMHandle, unsigned event)
  1410. {
  1411. BOOL rc;
  1412. DC_BEGIN_FN("SMCheckState");
  1413. if (smStateTable[event][pRealSMHandle->state] == SM_TABLE_OK) {
  1414. rc = TRUE;
  1415. }
  1416. else {
  1417. rc = FALSE;
  1418. if (smStateTable[event][pRealSMHandle->state] == SM_TABLE_WARN) {
  1419. TRC_ALT((TB, "Unusual event %s in state %s",
  1420. smEventName[event], smStateName[pRealSMHandle->state]));
  1421. }
  1422. else {
  1423. TRC_ABORT((TB, "Invalid event %s in state %s",
  1424. smEventName[event], smStateName[pRealSMHandle->state]));
  1425. }
  1426. }
  1427. DC_END_FN();
  1428. return rc;
  1429. }
  1430. #endif
  1431. /****************************************************************************/
  1432. /* Name: SM_SetSafeChecksumMethod
  1433. /*
  1434. /* Purpose: Sets flag to use safe checksum style
  1435. /*
  1436. /* Params: pSMHandle - SM Handle
  1437. // fEncryptChecksummedData -
  1438. /****************************************************************************/
  1439. NTSTATUS RDPCALL SM_SetSafeChecksumMethod(
  1440. PVOID pSMHandle,
  1441. BOOLEAN fSafeChecksumMethod
  1442. )
  1443. {
  1444. PSM_HANDLE_DATA pRealSMHandle = (PSM_HANDLE_DATA)pSMHandle;
  1445. DC_BEGIN_FN("SM_SetSafeChecksumMethod");
  1446. pRealSMHandle->useSafeChecksumMethod = fSafeChecksumMethod;
  1447. DC_END_FN();
  1448. return STATUS_SUCCESS;
  1449. }