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.

688 lines
21 KiB

  1. /*++
  2. Copyright (c) 1994-1999 Microsoft Corporation
  3. Module Name:
  4. tsrvsec.c
  5. Abstract:
  6. Contains functions that are required to establish secure channel between
  7. client and server.
  8. Author:
  9. Madan Appiah (madana) 1-Jan-1999
  10. Environment:
  11. User Mode - Win32
  12. Revision History:
  13. --*/
  14. #include <tsrv.h>
  15. #include <tsrvinfo.h>
  16. #include <tsrvsec.h>
  17. #include <_tsrvinfo.h>
  18. #include <at128.h>
  19. #include <at120ex.h>
  20. #include <tlsapi.h>
  21. //-----------------------------------------------------------------------------
  22. //
  23. // Local functions
  24. //
  25. //-----------------------------------------------------------------------------
  26. NTSTATUS
  27. AppendSecurityData(
  28. IN PTSRVINFO pTSrvInfo,
  29. IN OUT PUSERDATAINFO *ppUserDataInfo,
  30. IN BOOLEAN bGetCert,
  31. OUT PVOID *ppSecInfo
  32. )
  33. /*++
  34. Routine Description:
  35. This function generates a server random key, saves it in the TShare Server
  36. info structure. It also retrieves the server Public Key Certificate to pass
  37. to the client. Later it appends the server random key and server CERT to the
  38. pUserDataInfo structure which is passed to the client as connection response
  39. data.
  40. Arguments:
  41. pTSrvInfo - pointer to a server info structure
  42. pUserDataInfo - pointer to location of user data
  43. bGetCert - indicates whether or not to retrieve the server certification
  44. ppSecInfo - pointer to the security info within the user data buffer
  45. Return Value:
  46. NT Status Code.
  47. --*/
  48. {
  49. NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
  50. PUSERDATAINFO pUserDataInfo;
  51. BOOL bError;
  52. DWORD dwError;
  53. DWORD dwCurrentLen;
  54. DWORD dwNewLen;
  55. PRNS_UD_SC_SEC1 pSecInfo = NULL;
  56. PBYTE pNextData;
  57. GCCOctetString FAR *pOctString;
  58. LPBYTE pbServerCert = NULL;
  59. DWORD cbServerCert;
  60. LICENSE_STATUS Status = LICENSE_STATUS_OK;
  61. pUserDataInfo = *ppUserDataInfo;
  62. TS_ASSERT( pTSrvInfo != NULL );
  63. TS_ASSERT( pUserDataInfo != NULL );
  64. //
  65. // generate a server random key.
  66. // serialize this call across mutiple caller.
  67. //
  68. EnterCriticalSection( &g_TSrvCritSect );
  69. bError =
  70. TSCAPI_GenerateRandomBits(
  71. (LPBYTE)pTSrvInfo->SecurityInfo.KeyPair.serverRandom,
  72. sizeof(pTSrvInfo->SecurityInfo.KeyPair.serverRandom) );
  73. if( !bError ) {
  74. LeaveCriticalSection( &g_TSrvCritSect );
  75. dwError = ERROR_INVALID_DATA;
  76. TRACE((DEBUG_TSHRSRV_ERROR,
  77. "TShrSRV: Unable to generate random key, %D\n", dwError));
  78. goto Cleanup;
  79. }
  80. // Return a pointer to the start of the security data
  81. pSecInfo = (PRNS_UD_SC_SEC1)
  82. ((LPBYTE)pUserDataInfo + (pUserDataInfo->cbSize - sizeof(RNS_UD_SC_SEC)));
  83. // note only a RNS_UD_SC_SEC structure is copied to the user info structure
  84. // when encryption is not enabled. Note that we signify B3 shadow encryption
  85. // disabled as a method of 0xffffffff.
  86. if ((pSecInfo->encryptionMethod == 0) ||
  87. (pSecInfo->encryptionMethod == 0xffffffff)) {
  88. dwError = ERROR_SUCCESS;
  89. pTSrvInfo->bSecurityEnabled = FALSE;
  90. LeaveCriticalSection( &g_TSrvCritSect );
  91. goto Cleanup;
  92. }
  93. pTSrvInfo->bSecurityEnabled = TRUE;
  94. // Only allocate and return the random + cert when we are going to send it
  95. // to a client. This does not happen for the shadow passthru stack
  96. if (bGetCert) {
  97. if( RNS_TERMSRV_40_UD_VERSION >= pUserDataInfo->version )
  98. {
  99. pTSrvInfo->SecurityInfo.CertType = CERT_TYPE_PROPRIETORY;
  100. }
  101. else
  102. {
  103. pTSrvInfo->SecurityInfo.CertType = CERT_TYPE_X509;
  104. }
  105. //
  106. // Find our the certificate type to transmit to the client.
  107. // If it is a Hydra 4.0 RTM client then we will use the old proprietory
  108. // format certificate. Otherwise, we will use the X509 certificate.
  109. //
  110. //
  111. // Get the Hydra server certificate if we haven't already done so.
  112. //
  113. if( CERT_TYPE_PROPRIETORY == pTSrvInfo->SecurityInfo.CertType )
  114. {
  115. //
  116. // Get the proprietory certificate
  117. //
  118. Status = TLSGetTSCertificate(
  119. pTSrvInfo->SecurityInfo.CertType,
  120. &pbServerCert,
  121. &cbServerCert );
  122. if( LICENSE_STATUS_OK != Status )
  123. {
  124. LeaveCriticalSection( &g_TSrvCritSect );
  125. dwError = ERROR_INVALID_DATA;
  126. goto Cleanup;
  127. }
  128. }
  129. else
  130. {
  131. Status = TLSGetTSCertificate(
  132. pTSrvInfo->SecurityInfo.CertType,
  133. &pbServerCert,
  134. &cbServerCert );
  135. //
  136. // if we don't yet have the X509 certificate, use the proprietory
  137. // certificate
  138. //
  139. if( LICENSE_STATUS_OK != Status )
  140. {
  141. pTSrvInfo->SecurityInfo.CertType = CERT_TYPE_PROPRIETORY;
  142. Status = TLSGetTSCertificate(
  143. pTSrvInfo->SecurityInfo.CertType,
  144. &pbServerCert,
  145. &cbServerCert );
  146. }
  147. if( LICENSE_STATUS_OK != Status )
  148. {
  149. //
  150. // other reasons for failing to get the certificate
  151. //
  152. LeaveCriticalSection( &g_TSrvCritSect );
  153. dwError = ERROR_INVALID_DATA;
  154. goto Cleanup;
  155. }
  156. }
  157. LeaveCriticalSection( &g_TSrvCritSect );
  158. TS_ASSERT( pbServerCert != NULL );
  159. TS_ASSERT( cbServerCert != 0 );
  160. //
  161. // compute the new data size required.
  162. //
  163. dwCurrentLen = pUserDataInfo->cbSize;
  164. dwNewLen =
  165. dwCurrentLen +
  166. cbServerCert +
  167. sizeof(pTSrvInfo->SecurityInfo.KeyPair.serverRandom) +
  168. sizeof(RNS_UD_SC_SEC1) - sizeof(RNS_UD_SC_SEC);
  169. //
  170. // check to see we have enough room in the current allotted block.
  171. //
  172. // Note: previously we allotted this memory in multiples of 128 bytes
  173. // blocks.
  174. //
  175. dwCurrentLen =
  176. (dwCurrentLen % 128) ?
  177. ((dwCurrentLen/128) + 1) * 128 :
  178. dwCurrentLen;
  179. if( dwNewLen > dwCurrentLen ) {
  180. PUSERDATAINFO pUserDataInfoNew;
  181. dwNewLen =
  182. (dwNewLen % 128) ?
  183. ((dwNewLen/128) + 1) * 128 :
  184. dwNewLen;
  185. pUserDataInfoNew = TShareRealloc( pUserDataInfo, dwNewLen );
  186. if( pUserDataInfoNew == NULL ) {
  187. dwError = ERROR_NOT_ENOUGH_MEMORY;
  188. goto Cleanup;
  189. }
  190. else {
  191. pUserDataInfo = pUserDataInfoNew;
  192. }
  193. *ppUserDataInfo = pUserDataInfo;
  194. }
  195. TS_ASSERT( dwNewLen >= dwCurrentLen );
  196. //
  197. // now we have enough room in the user data buffer for security data, copy
  198. // security data and adjust length fields.
  199. //
  200. pSecInfo = (PRNS_UD_SC_SEC1)
  201. ((LPBYTE)pUserDataInfo +
  202. (pUserDataInfo->cbSize) - sizeof(RNS_UD_SC_SEC) );
  203. // note only RNS_UD_SC_SEC structure is copied to the user info
  204. // structure.
  205. TS_ASSERT( pSecInfo->header.length == sizeof(RNS_UD_SC_SEC) );
  206. TS_ASSERT( pSecInfo->encryptionMethod != 0 );
  207. //
  208. // new security packet length.
  209. //
  210. pSecInfo->header.length =
  211. sizeof(RNS_UD_SC_SEC1) +
  212. sizeof(pTSrvInfo->SecurityInfo.KeyPair.serverRandom) +
  213. (unsigned short)cbServerCert;
  214. pSecInfo->serverRandomLen = sizeof(pTSrvInfo->SecurityInfo.KeyPair.serverRandom);
  215. pSecInfo->serverCertLen = cbServerCert;
  216. pNextData = (LPBYTE)pSecInfo + sizeof(RNS_UD_SC_SEC1);
  217. //
  218. // append server random.
  219. //
  220. memcpy(
  221. pNextData,
  222. (LPBYTE)pTSrvInfo->SecurityInfo.KeyPair.serverRandom,
  223. sizeof(pTSrvInfo->SecurityInfo.KeyPair.serverRandom) );
  224. pNextData += sizeof(pTSrvInfo->SecurityInfo.KeyPair.serverRandom);
  225. //
  226. // copy certificate blob now.
  227. //
  228. memcpy( pNextData, pbServerCert, cbServerCert );
  229. //
  230. // Free the cert
  231. //
  232. TLSFreeTSCertificate(pbServerCert);
  233. pbServerCert = NULL;
  234. //
  235. // now adjust other other length fields.
  236. //
  237. pUserDataInfo->cbSize +=
  238. (pSecInfo->header.length - sizeof(RNS_UD_SC_SEC));
  239. //
  240. // compute the octet string pointer.
  241. //
  242. pOctString = (GCCOctetString FAR *)
  243. ((LPBYTE)pUserDataInfo +
  244. (UINT_PTR)pUserDataInfo->rgUserData[0].octet_string);
  245. pOctString->octet_string_length +=
  246. (pSecInfo->header.length - sizeof(RNS_UD_SC_SEC));
  247. }
  248. else {
  249. LeaveCriticalSection( &g_TSrvCritSect );
  250. }
  251. //
  252. // we are done.
  253. //
  254. dwError = ERROR_SUCCESS;
  255. Cleanup:
  256. if (NULL != pbServerCert)
  257. TLSFreeTSCertificate(pbServerCert);
  258. // return the pointer values since the data may have been realloc'd
  259. *ppUserDataInfo = pUserDataInfo;
  260. *ppSecInfo = pSecInfo;
  261. if( dwError != ERROR_SUCCESS ) {
  262. TRACE((DEBUG_TSHRSRV_DEBUG,
  263. "TShrSRV: AppendSecurityData failed, %d\n", dwError ));
  264. return( STATUS_UNSUCCESSFUL );
  265. }
  266. return( STATUS_SUCCESS );
  267. }
  268. NTSTATUS
  269. SendSecurityData(IN HANDLE hStack, IN PVOID pvSecInfo)
  270. /*++
  271. Routine Description:
  272. This function sends the previously constructed shadow security data
  273. (cert + server random) to the client server in response to a shadow request.
  274. Arguments:
  275. hStack - handle to the appropriate stack.
  276. pTSrvInfo - pointer to a server info structure.
  277. Return Value:
  278. NT Status Code.
  279. --*/
  280. {
  281. PRNS_UD_SC_SEC1 pSecInfo = (PRNS_UD_SC_SEC1) pvSecInfo;
  282. ULONG secInfoSize, ulBytesReturned;
  283. NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
  284. //
  285. // There will only be a random + cert in the case we are encrypting
  286. //
  287. if (pSecInfo->encryptionLevel != 0) {
  288. secInfoSize = sizeof(RNS_UD_SC_SEC1) +
  289. pSecInfo->serverRandomLen +
  290. pSecInfo->serverCertLen;
  291. }
  292. else {
  293. pSecInfo->serverRandomLen = 0;
  294. pSecInfo->serverCertLen = 0;
  295. secInfoSize = sizeof(RNS_UD_SC_SEC1);
  296. }
  297. TRACE((DEBUG_TSHRSRV_NORMAL,
  298. "TShrSRV: Encryption level: %ld, Method: %lx, "
  299. "cert[%ld] + random[%ld] + header[%ld]: size=%ld\n",
  300. pSecInfo->encryptionLevel, pSecInfo->encryptionMethod,
  301. pSecInfo->encryptionLevel != 0 ? pSecInfo->serverCertLen : 0,
  302. pSecInfo->encryptionLevel != 0 ? pSecInfo->serverRandomLen : 0,
  303. sizeof(RNS_UD_SC_SEC1), secInfoSize));
  304. //
  305. // issue the IOCTL_TSHARE_SEND_CERT_DATA if this is not a B3 server
  306. //
  307. if (pSecInfo->encryptionMethod != 0xFFFFFFFF) {
  308. ntStatus = IcaStackIoControl(hStack,
  309. IOCTL_TSHARE_SEND_CERT_DATA,
  310. pSecInfo,
  311. secInfoSize,
  312. NULL, 0, &ulBytesReturned);
  313. if (NT_SUCCESS(ntStatus)) {
  314. TRACE((DEBUG_TSHRSRV_NORMAL,
  315. "TShrSRV: Sent shadow cert[%ld] + random[%ld] + header[%ld]: size=%ld\n",
  316. pSecInfo->encryptionLevel != 0 ? pSecInfo->serverCertLen : 0,
  317. pSecInfo->encryptionLevel != 0 ? pSecInfo->serverRandomLen : 0,
  318. sizeof(RNS_UD_SC_SEC1),
  319. secInfoSize));
  320. }
  321. else {
  322. TRACE((DEBUG_TSHRSRV_ERROR,
  323. "TShrSRV: Send shadow cert + random failed: size=%ld, rc=%lx\n",
  324. secInfoSize, ntStatus));
  325. }
  326. }
  327. // Grandfather in the old B3 shadow requests which do not support
  328. // an encrypted shadow pipe
  329. else {
  330. ntStatus = STATUS_SUCCESS;
  331. TRACE((DEBUG_TSHRSRV_ERROR,
  332. "TShrSRV: Grandfathering old B3 shadow request\n"));
  333. }
  334. return ntStatus;
  335. }
  336. /****************************************************************************/
  337. //
  338. // CreateSessionKeys()
  339. //
  340. // Purpose: Exchange client/server randoms and create
  341. // session keys.
  342. //
  343. // Parameters:
  344. // IN [hStack] - which stack
  345. // IN [pTSrvInfo] - TShareSrv object
  346. // IN PrevStatus - Status for send. If not success, we send null data to the
  347. // WD to indicate the session key was bad and allow release of the session
  348. // key event wait.
  349. //
  350. // Return: STATUS_SUCCESS - Success
  351. // other - Failure
  352. //
  353. // History: 4/26/99 jparsons Created
  354. // 9/24/1999 erikma Added PrevStatus to remove deadlock
  355. /****************************************************************************/
  356. NTSTATUS CreateSessionKeys(
  357. IN HANDLE hStack,
  358. IN PTSRVINFO pTSrvInfo,
  359. IN NTSTATUS PrevStatus)
  360. {
  361. NTSTATUS ntStatus;
  362. DWORD dwBytesReturned;
  363. TRACE((DEBUG_TSHRSRV_NORMAL, "TShrSRV: Sending sec info to WD\n"));
  364. if (NT_SUCCESS(PrevStatus)) {
  365. ntStatus = IcaStackIoControl(
  366. hStack,
  367. IOCTL_TSHARE_SET_SEC_DATA,
  368. (LPBYTE)&pTSrvInfo->SecurityInfo,
  369. sizeof(pTSrvInfo->SecurityInfo),
  370. NULL,
  371. 0,
  372. &dwBytesReturned);
  373. }
  374. else {
  375. ntStatus = IcaStackIoControl(hStack, IOCTL_TSHARE_SET_SEC_DATA,
  376. NULL, 0, NULL, 0, &dwBytesReturned);
  377. }
  378. if (NT_SUCCESS(ntStatus)) {
  379. TRACE((DEBUG_TSHRSRV_NORMAL,
  380. "TShrSRV: Session key transmission succeeded, PrevStatus=%X\n",
  381. PrevStatus));
  382. }
  383. else {
  384. TRACE((DEBUG_TSHRSRV_ERROR,
  385. "TShrSRV: Session key transmission failed: rc=%lx, "
  386. "PrevStatus=%X\n", ntStatus, PrevStatus));
  387. }
  388. return ntStatus;
  389. }
  390. //*************************************************************
  391. //
  392. // GetClientRandom()
  393. //
  394. // Purpose: Receive the encrypted client random & decrypt
  395. //
  396. // Parameters: IN [hStack] - which stack
  397. // IN [pTSrvInfo] - TShareSrv object
  398. // IN [ulTimeout] - msec to wait before timing out
  399. // IN [bShadow] - indicates a shadow setup
  400. //
  401. // Return: STATUS_SUCCESS - Success
  402. // other - Failure
  403. //
  404. // History: 4/26/99 jparsons Created
  405. //
  406. //*************************************************************
  407. NTSTATUS
  408. GetClientRandom(HANDLE hStack,
  409. PTSRVINFO pTSrvInfo,
  410. LONG ulTimeout,
  411. BOOLEAN bShadow) {
  412. NTSTATUS ntStatus;
  413. DWORD dwBytesReturned;
  414. BYTE abEncryptedClientRandom[512];
  415. BYTE abClientRandom[512];
  416. DWORD dwClientRandomBufLen;
  417. SECURITYTIMEOUT securityTimeout;
  418. TRACE((DEBUG_TSHRSRV_NORMAL,
  419. "TShrSRV: Waiting to receive client random: msec=%ld\n", ulTimeout));
  420. securityTimeout.ulTimeout = ulTimeout;
  421. ntStatus =
  422. IcaStackIoControl(
  423. hStack,
  424. bShadow ? IOCTL_TSHARE_GET_CLIENT_RANDOM :
  425. IOCTL_TSHARE_GET_SEC_DATA,
  426. &securityTimeout,
  427. sizeof(securityTimeout),
  428. (LPBYTE)abEncryptedClientRandom,
  429. sizeof(abEncryptedClientRandom),
  430. &dwBytesReturned);
  431. TRACE((DEBUG_TSHRSRV_NORMAL,
  432. "TShrSRV: Received encrypted client random, rc=%lx\n",
  433. ntStatus));
  434. if (NT_SUCCESS(ntStatus)) {
  435. TS_ASSERT(
  436. dwBytesReturned <= sizeof(abEncryptedClientRandom) );
  437. //
  438. // decrypt client random.
  439. //
  440. dwClientRandomBufLen = sizeof(abClientRandom);
  441. EnterCriticalSection( &g_TSrvCritSect );
  442. if (LsCsp_DecryptEnvelopedData(
  443. pTSrvInfo->SecurityInfo.CertType,
  444. (LPBYTE)abEncryptedClientRandom,
  445. dwBytesReturned,
  446. (LPBYTE)abClientRandom,
  447. &dwClientRandomBufLen)) {
  448. LeaveCriticalSection( &g_TSrvCritSect );
  449. TRACE((DEBUG_TSHRSRV_NORMAL,
  450. "TShrSRV: Decrypted client random: rc=%lx\n", ntStatus));
  451. TS_ASSERT( dwClientRandomBufLen >=
  452. sizeof(pTSrvInfo->SecurityInfo.KeyPair.clientRandom) );
  453. //
  454. // Make sure we got enough data!
  455. //
  456. if( dwClientRandomBufLen >=
  457. sizeof(pTSrvInfo->SecurityInfo.KeyPair.clientRandom) ) {
  458. //
  459. // copy decrypted data, only the part we need.
  460. //
  461. memcpy(
  462. (LPBYTE)pTSrvInfo->SecurityInfo.KeyPair.clientRandom,
  463. (LPBYTE)abClientRandom,
  464. sizeof(pTSrvInfo->SecurityInfo.KeyPair.clientRandom) );
  465. }
  466. else {
  467. ntStatus = STATUS_UNSUCCESSFUL;
  468. TRACE((DEBUG_TSHRSRV_ERROR,
  469. "TShrSRV: Client random key size: expected [%ld], got [%ld]\n",
  470. sizeof(pTSrvInfo->SecurityInfo.KeyPair.clientRandom,
  471. dwClientRandomBufLen)));
  472. }
  473. }
  474. else {
  475. LeaveCriticalSection(&g_TSrvCritSect);
  476. ntStatus = STATUS_UNSUCCESSFUL;
  477. TRACE((DEBUG_TSHRSRV_ERROR,
  478. "TShrSRV: Could not decrypt client random: rc=%lx\n", ntStatus));
  479. }
  480. }
  481. else {
  482. ntStatus = STATUS_UNSUCCESSFUL;
  483. TRACE((DEBUG_TSHRSRV_ERROR,
  484. "TShrSRV: Failed to receive encrypted client random, rc=%lx\n",
  485. ntStatus));
  486. }
  487. return ntStatus;
  488. }
  489. //*************************************************************
  490. //
  491. // SendClientRandom()
  492. //
  493. // Purpose: Encrypt and send the shadow random
  494. //
  495. // Return: STATUS_SUCCESS - Success
  496. // other - Failure
  497. //
  498. // History: 4/26/99 jparsons Created
  499. //
  500. //*************************************************************
  501. NTSTATUS
  502. SendClientRandom(HANDLE hStack,
  503. CERT_TYPE certType,
  504. PBYTE pbServerPublicKey,
  505. ULONG serverPublicKeyLen,
  506. PBYTE pbRandomKey,
  507. ULONG randomKeyLen)
  508. {
  509. NTSTATUS ntStatus = STATUS_SUCCESS;
  510. BOOL status;
  511. BYTE encClientRandom[CLIENT_RANDOM_MAX_SIZE]; // Largest possible key size
  512. ULONG encClientRandomLen;
  513. ULONG ulBytesReturned;
  514. //
  515. // encrypt the client random key. Serialize this call across mutiple
  516. // callers since the bogus routines are not multithread safe!
  517. //
  518. EnterCriticalSection( &g_TSrvCritSect );
  519. encClientRandomLen = sizeof(encClientRandom);
  520. status = EncryptClientRandom(
  521. pbServerPublicKey,
  522. serverPublicKeyLen,
  523. pbRandomKey,
  524. randomKeyLen,
  525. encClientRandom,
  526. &encClientRandomLen);
  527. LeaveCriticalSection( &g_TSrvCritSect );
  528. // Send the encrypted client random to the server
  529. if (NT_SUCCESS(status)) {
  530. TRACE((DEBUG_TSHRSRV_NORMAL,
  531. "TShrSRV: Attempting to send shadow client random: enc len=%ld\n",
  532. encClientRandomLen));
  533. ntStatus = IcaStackIoControl(hStack,
  534. IOCTL_TSHARE_SEND_CLIENT_RANDOM,
  535. encClientRandom,
  536. encClientRandomLen,
  537. NULL, 0, &ulBytesReturned);
  538. if (NT_SUCCESS(ntStatus)) {
  539. TRACE((DEBUG_TSHRSRV_NORMAL,
  540. "TShrSRV: Sent shadow client random: len=%ld\n",
  541. encClientRandomLen));
  542. }
  543. else {
  544. TRACE((DEBUG_TSHRSRV_ERROR,
  545. "TShrSRV: Send shadow client random failed: len=%ld, rc=%lx\n",
  546. encClientRandomLen, ntStatus));
  547. }
  548. }
  549. else {
  550. TRACE((DEBUG_TSHRSRV_ERROR,
  551. "TShrSRV: Could not encrypt shadow client random! rc=%lx\n",
  552. status));
  553. ntStatus = STATUS_UNSUCCESSFUL;
  554. }
  555. return ntStatus;
  556. }