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.

1946 lines
64 KiB

  1. /****************************************************************************/
  2. // tsrvcom.c
  3. //
  4. // RDPWSX routines for lower-layer (GCC, RDPWD) communications support
  5. //
  6. // Copyright (C) 1991-2000 Microsoft Corporation
  7. /****************************************************************************/
  8. #include <TSrv.h>
  9. #include <TSrvCom.h>
  10. #include <TSrvInfo.h>
  11. #include <_TSrvInfo.h>
  12. #include <_TSrvCom.h>
  13. #include <TSrvSec.h>
  14. #include <licecert.h>
  15. // Data declarations
  16. ULONG g_GCCAppID = 0;
  17. BOOL g_fGCCRegistered = FALSE;
  18. //*************************************************************
  19. //
  20. // TSrvValidateServerCertificate()
  21. //
  22. // Purpose: Validate the certificate received from the shadow
  23. // client's server is legit. Note that this function
  24. // is very similar to certificate validation by the
  25. // client.
  26. //
  27. // Return: STATUS_SUCCESS - Success
  28. // other - Failure
  29. //
  30. // History: 4/26/99 jparsons Created
  31. //
  32. //*************************************************************
  33. NTSTATUS
  34. TSrvValidateServerCertificate(HANDLE hStack,
  35. CERT_TYPE *pCertType,
  36. PULONG pcbServerPubKey,
  37. PBYTE *ppbServerPubKey,
  38. ULONG cbShadowRandom,
  39. PBYTE pShadowRandom,
  40. LONG ulTimeout)
  41. {
  42. ULONG ulCertVersion;
  43. NTSTATUS status;
  44. PSHADOWCERT pShadowCert = NULL;
  45. PBYTE pbNetCert;
  46. PBYTE pbNetRandom;
  47. ULONG ulBytesReturned;
  48. SECURITYTIMEOUT securityTimeout;
  49. *pcbServerPubKey = 0;
  50. *ppbServerPubKey = NULL;
  51. *pCertType = CERT_TYPE_INVALID;
  52. securityTimeout.ulTimeout = ulTimeout;
  53. // Wait for the shadow server certificate to arrive and determine how
  54. // much memory to allocate. Note that one potential outcome is that the
  55. // other server is not encrypting and thus sends no certificate
  56. TRACE((DEBUG_TSHRSRV_NORMAL,
  57. "TShrSRV: Waiting to receive server certificate: msec=%ld\n", ulTimeout));
  58. status = IcaStackIoControl(hStack,
  59. IOCTL_TSHARE_GET_CERT_DATA,
  60. &securityTimeout, sizeof(securityTimeout),
  61. NULL,
  62. 0,
  63. &ulBytesReturned);
  64. if (status == STATUS_BUFFER_TOO_SMALL) {
  65. ULONG ulBytesNeeded = ulBytesReturned;
  66. TRACE((DEBUG_TSHRSRV_NORMAL,
  67. "TShrSRV: Need %ld bytes for certificate\n", ulBytesNeeded));
  68. pShadowCert = TSHeapAlloc(0, ulBytesNeeded, TS_HTAG_TSS_CERTIFICATE);
  69. if (pShadowCert != NULL) {
  70. memset(pShadowCert, 0, sizeof(PSHADOWCERT));
  71. pShadowCert->encryptionMethod = 0xffffffff;
  72. status = IcaStackIoControl(hStack,
  73. IOCTL_TSHARE_GET_CERT_DATA,
  74. &securityTimeout, sizeof(securityTimeout),
  75. pShadowCert,
  76. ulBytesNeeded,
  77. &ulBytesReturned);
  78. // calculate pointers to embedded data (if any)
  79. if (status == STATUS_SUCCESS) {
  80. TRACE((DEBUG_TSHRSRV_ERROR, "TShrSRV: Received random [%ld], Certificate [%ld]\n",
  81. pShadowCert->shadowRandomLen, pShadowCert->shadowCertLen));
  82. if (pShadowCert->encryptionLevel != 0) {
  83. pbNetRandom = pShadowCert->data;
  84. pbNetCert = pbNetRandom + pShadowCert->shadowRandomLen;
  85. // Save off the server random to establish session keys later
  86. if (pShadowCert->shadowRandomLen == RANDOM_KEY_LENGTH) {
  87. memcpy(pShadowRandom, pbNetRandom, pShadowCert->shadowRandomLen);
  88. }
  89. else {
  90. memset(pShadowRandom, 0, RANDOM_KEY_LENGTH);
  91. TRACE((DEBUG_TSHRSRV_ERROR,
  92. "TShrSRV: Invalid shadow random key length: %ld\n",
  93. pShadowCert->shadowRandomLen));
  94. status = STATUS_INVALID_PARAMETER;
  95. }
  96. }
  97. // else there is no encryption so we're done!
  98. else {
  99. TRACE((DEBUG_TSHRSRV_NORMAL, "TShrSRV: Encryption is disabled\n"));
  100. return STATUS_SUCCESS;
  101. }
  102. }
  103. else {
  104. TRACE((DEBUG_TSHRSRV_ERROR,
  105. "TShrSRV: IOCTL_TSHARE_GET_CERT_DATA failed: rc=%lx\n",
  106. status));
  107. }
  108. }
  109. else {
  110. TRACE((DEBUG_TSHRSRV_ERROR,
  111. "TShrSRV: Could not allocate memory to validate shadow certificate\n"))
  112. status = STATUS_NO_MEMORY;
  113. }
  114. }
  115. // The other server returned a certificate, so validate it
  116. if (status == STATUS_SUCCESS && pShadowCert != NULL) {
  117. ULONG cbNetCert = pShadowCert->shadowCertLen;
  118. memcpy(&ulCertVersion, pbNetCert, sizeof(ULONG));
  119. // assume certificate validation is going to fail ;-(
  120. status = STATUS_LICENSE_VIOLATION;
  121. //
  122. // decode and validate proprietory certificate.
  123. //
  124. if( CERT_CHAIN_VERSION_2 > GET_CERTIFICATE_VERSION(ulCertVersion)) {
  125. Hydra_Server_Cert serverCertificate;
  126. *pCertType = CERT_TYPE_PROPRIETORY;
  127. // Unpack and validate the legacy certificate
  128. if (UnpackServerCert(pbNetCert, cbNetCert, &serverCertificate)) {
  129. if (ValidateServerCert(&serverCertificate)) {
  130. *ppbServerPubKey = TSHeapAlloc(
  131. HEAP_ZERO_MEMORY,
  132. serverCertificate.PublicKeyData.wBlobLen,
  133. TS_HTAG_TSS_PUBKEY);
  134. // Copy the public key from inside the proprietary blob!
  135. if (*ppbServerPubKey != NULL) {
  136. memcpy(*ppbServerPubKey,
  137. serverCertificate.PublicKeyData.pBlob,
  138. serverCertificate.PublicKeyData.wBlobLen);
  139. *pcbServerPubKey = serverCertificate.PublicKeyData.wBlobLen;
  140. status = STATUS_SUCCESS;
  141. }
  142. else {
  143. status = STATUS_NO_MEMORY;
  144. TRACE((DEBUG_TSHRSRV_ERROR,
  145. "TShrSRV: Failed to allocate %u bytes for server public key\n",
  146. *pcbServerPubKey)) ;
  147. }
  148. }
  149. else {
  150. TRACE((DEBUG_TSHRSRV_ERROR,
  151. "TShrSRV: Invalid proprietary server certificate received\n"));
  152. }
  153. }
  154. else {
  155. TRACE((DEBUG_TSHRSRV_ERROR,
  156. "TShrSRV: Failed to unpack proprietary server certificate\n")) ;
  157. }
  158. }
  159. //
  160. // decode X509 certificate and extract public key
  161. //
  162. else if( MAX_CERT_CHAIN_VERSION >= GET_CERTIFICATE_VERSION(ulCertVersion)) {
  163. ULONG fDates = CERT_DATE_DONT_VALIDATE;
  164. LICENSE_STATUS licStatus;
  165. *pCertType = CERT_TYPE_X509;
  166. *ppbServerPubKey = NULL;
  167. // Determine the length of the public key. Note that this stinking
  168. // function is not multi-thread safe!
  169. TRACE((DEBUG_TSHRSRV_ERROR,
  170. "TShrSRV: X.509 server certificate length: %ld\n",
  171. cbNetCert)) ;
  172. // Watch out! X509 routines are not thread safe.
  173. EnterCriticalSection( &g_TSrvCritSect );
  174. licStatus = VerifyCertChain(pbNetCert, cbNetCert, NULL,
  175. pcbServerPubKey, &fDates);
  176. LeaveCriticalSection( &g_TSrvCritSect );
  177. if( LICENSE_STATUS_INSUFFICIENT_BUFFER == licStatus )
  178. {
  179. *ppbServerPubKey = TSHeapAlloc(HEAP_ZERO_MEMORY, *pcbServerPubKey,
  180. TS_HTAG_TSS_PUBKEY);
  181. if (*ppbServerPubKey != NULL) {
  182. EnterCriticalSection( &g_TSrvCritSect );
  183. licStatus = VerifyCertChain(pbNetCert, cbNetCert,
  184. *ppbServerPubKey, pcbServerPubKey,
  185. &fDates);
  186. LeaveCriticalSection( &g_TSrvCritSect );
  187. if (LICENSE_STATUS_OK == licStatus) {
  188. status = STATUS_SUCCESS;
  189. }
  190. else {
  191. TRACE((DEBUG_TSHRSRV_ERROR,
  192. "TShrSRV: Failed to verify X.509 server certificate: %ld\n",
  193. licStatus)) ;
  194. // torch the server public key memory
  195. TSHeapFree(*ppbServerPubKey);
  196. *ppbServerPubKey = NULL;
  197. }
  198. }
  199. else {
  200. status = STATUS_NO_MEMORY;
  201. TRACE((DEBUG_TSHRSRV_ERROR,
  202. "TShrSRV: Failed to allocate %u bytes for server public key\n",
  203. *pcbServerPubKey)) ;
  204. }
  205. }
  206. else {
  207. TRACE((DEBUG_TSHRSRV_ERROR,
  208. "TShrSRV: Could not decode X.509 server public key length: %d\n",
  209. licStatus )) ;
  210. }
  211. }
  212. //
  213. // don't know how to decode this version of certificate
  214. //
  215. else {
  216. status = LICENSE_STATUS_UNSUPPORTED_VERSION;
  217. TRACE((DEBUG_TSHRSRV_ERROR,"TShrSRV: Invalid certificate version: %ld\n",
  218. GET_CERTIFICATE_VERSION(ulCertVersion))) ;
  219. }
  220. }
  221. // Something messed up!
  222. else {
  223. // Treat a timeout as fatal.
  224. if (status == STATUS_TIMEOUT)
  225. status = STATUS_IO_TIMEOUT;
  226. TRACE((DEBUG_TSHRSRV_ERROR,
  227. "TShrSRV: Failed to retrieve shadow server cerfificate, rc=%lx, "
  228. "pShadowCert=%p\n", status, pShadowCert));
  229. }
  230. if (pShadowCert != NULL)
  231. TSHeapFree(pShadowCert);
  232. return status;
  233. }
  234. //*************************************************************
  235. //
  236. // TSrvCalculateUserDataSize()
  237. //
  238. // Purpose: Calculates the amount of user data passed in
  239. // the pCreateMessage message
  240. //
  241. // Parameters: IN [pCreateMessage] - GCC CreateIndicationMessage
  242. //
  243. // Return: User data size (bytes)
  244. //
  245. // Notes: Function trucks it's way through the GCC user_data_list
  246. // structure summing up the amount of user data supplied
  247. //
  248. // History: 07-17-97 BrianTa Created
  249. //
  250. //*************************************************************
  251. ULONG
  252. TSrvCalculateUserDataSize(IN CreateIndicationMessage *pCreateMessage)
  253. {
  254. int i;
  255. ULONG ulUserDataSize;
  256. GCCUserData *pClientUserData;
  257. TRACE((DEBUG_TSHRSRV_FLOW,
  258. "TShrSRV: TSrvCalculateUserDataSize entry\n"));
  259. ulUserDataSize = 0;
  260. TSrvDumpUserData(pCreateMessage);
  261. for (i=0; i<pCreateMessage->number_of_user_data_members; i++)
  262. {
  263. pClientUserData = pCreateMessage->user_data_list[i];
  264. if (pClientUserData != NULL)
  265. {
  266. // Calcu KEY size
  267. if (pClientUserData->key.key_type == GCC_OBJECT_KEY)
  268. {
  269. ulUserDataSize += (sizeof(ULONG) *
  270. pClientUserData->key.u.object_id.long_string_length);
  271. }
  272. else
  273. {
  274. ulUserDataSize += (sizeof(UCHAR) *
  275. pClientUserData->key.u.h221_non_standard_id.octet_string_length);
  276. }
  277. // Calc client size
  278. if (pClientUserData->octet_string)
  279. {
  280. // Allow for the extra indirection
  281. ulUserDataSize += sizeof(*(pClientUserData->octet_string));
  282. // Allow for the actual data
  283. ulUserDataSize += (sizeof(UCHAR) *
  284. pClientUserData->octet_string->octet_string_length);
  285. }
  286. }
  287. }
  288. TRACE((DEBUG_TSHRSRV_FLOW,
  289. "TShrSRV: TSrvCalculateUserDataSize exit - 0x%x\n", ulUserDataSize));
  290. return (ulUserDataSize);
  291. }
  292. //*************************************************************
  293. //
  294. // TSrvSaveUserDataMember()
  295. //
  296. // Purpose: Saves off the provided userData member
  297. //
  298. // Parameters: IN [pInUserData] - Source userData
  299. // OUT [pOutUserData] - Destination userData
  300. // IN OUT [pulUserDataOffset] - Re-base offset
  301. //
  302. // Return: void
  303. //
  304. // Notes: This routine copies the src user data into the
  305. // destination user data, re-basing all the dest
  306. // user data ptrs to the provided pulUserDataOffset
  307. //
  308. // History: 07-17-97 BrianTa Created
  309. //
  310. //*************************************************************
  311. void
  312. TSrvSaveUserDataMember(IN GCCUserData *pInUserData,
  313. OUT GCCUserData *pOutUserData,
  314. IN PUSERDATAINFO pUserDataInfo,
  315. IN OUT PULONG pulUserDataOffset)
  316. {
  317. ULONG ulUserDataSize;
  318. GCCOctetString UNALIGNED *pOctetString;
  319. TRACE((DEBUG_TSHRSRV_FLOW,
  320. "TShrSRV: TSrvSaveUserDataMember entry\n"));
  321. *pOutUserData = *pInUserData;
  322. // Key data and length
  323. if (pInUserData->key.key_type == GCC_OBJECT_KEY)
  324. {
  325. pOutUserData->key.u.object_id.long_string =
  326. (PULONG FAR)ULongToPtr((*pulUserDataOffset));
  327. ulUserDataSize =
  328. pOutUserData->key.u.object_id.long_string_length * sizeof(ULONG);
  329. memcpy((PCHAR) pUserDataInfo + *pulUserDataOffset,
  330. pInUserData->key.u.object_id.long_string,
  331. ulUserDataSize);
  332. }
  333. else
  334. {
  335. pOutUserData->key.u.h221_non_standard_id.octet_string =
  336. (PUCHAR FAR)ULongToPtr((*pulUserDataOffset));
  337. ulUserDataSize =
  338. pInUserData->key.u.h221_non_standard_id.octet_string_length * sizeof(UCHAR);
  339. memcpy((PCHAR) pUserDataInfo + *pulUserDataOffset,
  340. pInUserData->key.u.h221_non_standard_id.octet_string,
  341. ulUserDataSize);
  342. }
  343. *pulUserDataOffset += ulUserDataSize;
  344. // Client data ptr, length, and data
  345. if (pInUserData->octet_string &&
  346. pInUserData->octet_string->octet_string)
  347. {
  348. // Data ptr
  349. pOutUserData->octet_string = (GCCOctetString *)ULongToPtr((*pulUserDataOffset));
  350. pOctetString = (GCCOctetString *)
  351. ((PUCHAR) pOutUserData->octet_string +
  352. (ULONG_PTR)pUserDataInfo);
  353. *pulUserDataOffset += sizeof(*(pInUserData->octet_string));
  354. // Data length
  355. pOctetString->octet_string_length =
  356. pInUserData->octet_string->octet_string_length;
  357. pOctetString->octet_string = (unsigned char FAR *)ULongToPtr((*pulUserDataOffset));
  358. ulUserDataSize =
  359. pInUserData->octet_string->octet_string_length * sizeof(UCHAR);
  360. // Data
  361. memcpy((PCHAR) pUserDataInfo + *pulUserDataOffset,
  362. pInUserData->octet_string->octet_string,
  363. ulUserDataSize);
  364. *pulUserDataOffset += ulUserDataSize;
  365. }
  366. TRACE((DEBUG_TSHRSRV_FLOW,
  367. "TShrSRV: TSrvSaveUserDataMember exit\n"));
  368. }
  369. //*************************************************************
  370. //
  371. // TSrvSaveUserData()
  372. //
  373. // Purpose: Saves off the provided userData
  374. //
  375. // Parameters: IN [pTSrvInfo] - TSrvInfo object
  376. // IN [pCreateMessage] - CreateIndicationMessage
  377. //
  378. // Return: STATUS_SUCCESS - Success
  379. // STATUS_NO_MEMORY - Failure
  380. //
  381. // Notes: This routine makes a new copy of the userdata
  382. // provided by the GCC CreateIndicationMessage
  383. //
  384. // History: 07-17-97 BrianTa Created
  385. //
  386. //*************************************************************
  387. NTSTATUS
  388. TSrvSaveUserData(IN PTSRVINFO pTSrvInfo,
  389. IN CreateIndicationMessage *pCreateMessage)
  390. {
  391. DWORD i;
  392. ULONG ulUserDataInfoSize;
  393. ULONG ulUserDataOffset;
  394. ULONG ulUserDataSize;
  395. PUSERDATAINFO pUserDataInfo;
  396. NTSTATUS ntStatus;
  397. TRACE((DEBUG_TSHRSRV_FLOW,
  398. "TShrSRV: TSrvSaveUserData entry\n"));
  399. ntStatus = STATUS_NO_MEMORY;
  400. // Calculate the size of the USERDATAINFO control structure and the
  401. // size of the data buffer needed to hold the GCC UserData
  402. ulUserDataInfoSize = sizeof(USERDATAINFO) +
  403. sizeof(GCCUserData) * pCreateMessage->number_of_user_data_members;
  404. ulUserDataSize = TSrvCalculateUserDataSize(pCreateMessage);
  405. pUserDataInfo = TSHeapAlloc(HEAP_ZERO_MEMORY,
  406. ulUserDataInfoSize + ulUserDataSize,
  407. TS_HTAG_TSS_USERDATA_IN);
  408. TS_ASSERT(pTSrvInfo->pUserDataInfo == NULL);
  409. pTSrvInfo->pUserDataInfo = pUserDataInfo;
  410. // If we can allocate enough memory to do the copy, then loop through
  411. // each member saving the associated userdata
  412. if (pUserDataInfo)
  413. {
  414. TRACE((DEBUG_TSHRSRV_DETAIL, "TShrSRV: Allocated 0x%x bytes for UserData save space\n",
  415. ulUserDataInfoSize + ulUserDataSize));
  416. pUserDataInfo->cbSize = ulUserDataInfoSize + ulUserDataSize;
  417. pUserDataInfo->hDomain = pTSrvInfo->hDomain;
  418. pUserDataInfo->ulUserDataMembers = pCreateMessage->number_of_user_data_members;
  419. ulUserDataOffset = ulUserDataInfoSize;
  420. TRACE((DEBUG_TSHRSRV_DETAIL, "TShrSRV: Saving each UserDataMenber to save space\n"));
  421. for (i=0; i<pUserDataInfo->ulUserDataMembers; i++)
  422. {
  423. TSrvSaveUserDataMember(pCreateMessage->user_data_list[i],
  424. &pUserDataInfo->rgUserData[i],
  425. pUserDataInfo,
  426. &ulUserDataOffset);
  427. }
  428. TS_ASSERT(ulUserDataOffset <= ulUserDataInfoSize + ulUserDataSize);
  429. ntStatus = STATUS_SUCCESS;
  430. }
  431. else
  432. {
  433. TRACE((DEBUG_TSHRSRV_WARN, "TShrSRV: Can't allocate 0x%x for userData save space\n",
  434. ulUserDataInfoSize + ulUserDataSize));
  435. }
  436. TRACE((DEBUG_TSHRSRV_FLOW,
  437. "TShrSRV: TSrvSaveUserData exit - 0x%x\n", ntStatus));
  438. return (ntStatus);
  439. }
  440. //*************************************************************
  441. //
  442. // TSrvSignalIndication()
  443. //
  444. // Purpose: Signals the worker thread
  445. //
  446. // Parameters: IN [pTSrvInfo] - TSrvInfo object
  447. // IN [ntStatus] - Signaling status
  448. //
  449. // Return: void
  450. //
  451. // History: 07-17-97 BrianTa Created
  452. //
  453. //*************************************************************
  454. void
  455. TSrvSignalIndication(IN PTSRVINFO pTSrvInfo,
  456. IN NTSTATUS ntStatus)
  457. {
  458. TRACE((DEBUG_TSHRSRV_FLOW,
  459. "TShrSRV: TSrvSignalIndication entry\n"));
  460. TS_ASSERT(pTSrvInfo->hWorkEvent);
  461. TRACE((DEBUG_TSHRSRV_DEBUG, "TShrSRV: Signaling workEvent %p, status 0x%x\n",
  462. pTSrvInfo->hWorkEvent, ntStatus));
  463. pTSrvInfo->ntStatus = ntStatus;
  464. if (!SetEvent(pTSrvInfo->hWorkEvent))
  465. {
  466. TRACE((DEBUG_TSHRSRV_DEBUG, "TShrSRV: Cannot Signal workEvent %p, gle 0x%x\n",
  467. pTSrvInfo->hWorkEvent, GetLastError()));
  468. ASSERT(0);
  469. }
  470. TRACE((DEBUG_TSHRSRV_FLOW,
  471. "TShrSRV: TSrvSignalIndication exit\n"));
  472. }
  473. //*************************************************************
  474. //
  475. // TSrvHandleCreateInd()
  476. //
  477. // Purpose: Handles GCC Gcc_Create_Indication
  478. //
  479. // Parameters: IN [pCreateInd] - CreateIndicationMessage
  480. //
  481. // Return: void
  482. //
  483. // History: 07-17-97 BrianTa Created
  484. //
  485. //*************************************************************
  486. void
  487. TSrvHandleCreateInd(IN PTSRVINFO pTSrvInfo,
  488. IN CreateIndicationMessage *pCreateInd)
  489. {
  490. NTSTATUS ntStatus;
  491. TRACE((DEBUG_TSHRSRV_FLOW,
  492. "TShrSRV: TSrvHandleCreateInd entry\n"));
  493. // Reject the conference if we are not allowed to accept any new calls
  494. if (TSrvIsReady(FALSE))
  495. {
  496. TRACE((DEBUG_TSHRSRV_NORMAL,
  497. "TShrSRV: Accepting create indication - Domain %p\n",
  498. pTSrvInfo->hDomain));
  499. TSrvDumpCreateIndDetails(pCreateInd);
  500. pTSrvInfo->hConnection = pCreateInd->connection_handle;
  501. // Save off UserData
  502. TRACE((DEBUG_TSHRSRV_DETAIL,
  503. "TShrSRV: Attempting to save CreateInd userData\n"));
  504. ntStatus = TSrvSaveUserData(pTSrvInfo, pCreateInd);
  505. TRACE((DEBUG_TSHRSRV_DETAIL,
  506. "TShrSRV: Save userData was%s successful\n",
  507. (ntStatus == STATUS_SUCCESS ? "" : " not")));
  508. }
  509. else
  510. {
  511. TRACE((DEBUG_TSHRSRV_NORMAL,
  512. "TShrSRV: Rejecting create indication - Domain %p\n",
  513. pTSrvInfo->hDomain));
  514. ntStatus = STATUS_DEVICE_NOT_READY;
  515. }
  516. // Signal completion, and pass along the completion status
  517. TSrvSignalIndication(pTSrvInfo, ntStatus);
  518. TRACE((DEBUG_TSHRSRV_FLOW,
  519. "TShrSRV: TSrvHandleCreateInd exit\n"));
  520. }
  521. //*************************************************************
  522. //
  523. // TSrvHandleTerminateInd()
  524. //
  525. // Purpose: Handles GCC Gcc_Terminate_Ind
  526. //
  527. // Parameters: IN [pTermInd] - TerminateIndicationMessage
  528. //
  529. // Return: void
  530. //
  531. // History: 07-17-97 BrianTa Created
  532. //
  533. //*************************************************************
  534. void
  535. TSrvHandleTerminateInd(IN PTSRVINFO pTSrvInfo,
  536. IN TerminateIndicationMessage *pTermInd)
  537. {
  538. BYTE fuConfState;
  539. GCCError GCCrc;
  540. TRACE((DEBUG_TSHRSRV_FLOW,
  541. "TShrSRV: TSrvHandleTerminateInd entry\n"));
  542. TRACE((DEBUG_TSHRSRV_DETAIL,
  543. "TShrSRV: Domain %p\n", pTSrvInfo->hDomain));
  544. TSrvDumpGCCReasonDetails(pTermInd->reason,
  545. "GCCTerminateConfirm");
  546. TSrvReferenceInfo(pTSrvInfo);
  547. EnterCriticalSection(&pTSrvInfo->cs);
  548. // If the disconnect was not requested (client, network) then disconnect the
  549. // connection, flag the status, and wait for ICASRV to ping us via the normal
  550. // termination mechanism.
  551. if (!pTSrvInfo->fDisconnect)
  552. {
  553. fuConfState = pTSrvInfo->fuConfState;
  554. pTSrvInfo->fDisconnect = TRUE;
  555. pTSrvInfo->ulReason = GCC_REASON_USER_INITIATED;
  556. pTSrvInfo->fuConfState = TSRV_CONF_TERMINATED;
  557. GCCrc = GCCConferenceTerminateRequest(pTSrvInfo->hIca, NULL,
  558. pTSrvInfo->hConnection, pTSrvInfo->ulReason);
  559. TSrvDumpGCCRCDetails(GCCrc,
  560. "GCCConferenceTerminateRequest");
  561. pTSrvInfo->hConnection = NULL;
  562. if (fuConfState == TSRV_CONF_PENDING)
  563. TSrvSignalIndication(pTSrvInfo, STATUS_SUCCESS);
  564. }
  565. LeaveCriticalSection(&pTSrvInfo->cs);
  566. TSrvDereferenceInfo(pTSrvInfo);
  567. TRACE((DEBUG_TSHRSRV_FLOW,
  568. "TShrSRV: TSrvHandleTerminateInd exit\n"));
  569. }
  570. //*************************************************************
  571. //
  572. // TSrvHandleDisconnectInd()
  573. //
  574. // Purpose: Handles GCC Gcc_Disconnect_Ind
  575. //
  576. // Parameters: IN [pDiscInd] - DisconnectIndicationMessage
  577. //
  578. // Return: void
  579. //
  580. // History: 07-17-97 BrianTa Created
  581. //
  582. //*************************************************************
  583. void
  584. TSrvHandleDisconnectInd(IN PTSRVINFO pTSrvInfo,
  585. IN DisconnectIndicationMessage *pDiscInd)
  586. {
  587. TRACE((DEBUG_TSHRSRV_FLOW,
  588. "TShrSRV: TSrvHandleDisconnectInd entry\n"));
  589. TRACE((DEBUG_TSHRSRV_DETAIL,
  590. "TShrSRV: Domain = 0x%x\n", pTSrvInfo->hDomain));
  591. TRACE((DEBUG_TSHRSRV_FLOW,
  592. "TShrSRV: TSrvHandleDisconnectInd exit\n"));
  593. }
  594. //*************************************************************
  595. //
  596. // TSrvGCCCallBack()
  597. //
  598. // Purpose: Handles GCC Callback messages
  599. //
  600. // Parameters: IN [pDiscInd] - DisconnectIndicationMessage
  601. //
  602. // Return: GCC_CALLBACK_PROCESSED
  603. //
  604. // History: 07-17-97 BrianTa Created
  605. //
  606. //*************************************************************
  607. T120Boolean
  608. APIENTRY
  609. TSrvGCCCallBack(IN GCCMessage *pGCCMessage)
  610. {
  611. PTSRVINFO pTSrvInfo;
  612. TRACE((DEBUG_TSHRSRV_FLOW,
  613. "TShrSRV: TSrvGCCCallBack entry\n"));
  614. TSrvDumpCallBackMessage(pGCCMessage);
  615. pTSrvInfo = pGCCMessage->user_defined;
  616. TSrvInfoValidate(pTSrvInfo);
  617. if (pTSrvInfo)
  618. {
  619. switch (pGCCMessage->message_type)
  620. {
  621. case GCC_CREATE_INDICATION:
  622. TSrvHandleCreateInd(pTSrvInfo, &(pGCCMessage->u.create_indication));
  623. break;
  624. case GCC_DISCONNECT_INDICATION:
  625. TSrvHandleDisconnectInd(pTSrvInfo, &(pGCCMessage->u.disconnect_indication));
  626. break;
  627. case GCC_TERMINATE_INDICATION:
  628. TSrvHandleTerminateInd(pTSrvInfo, &(pGCCMessage->u.terminate_indication));
  629. break;
  630. }
  631. }
  632. TRACE((DEBUG_TSHRSRV_FLOW,
  633. "TShrSRV: TSrvGCCCallBack exit - GCC_CALLBACK_PROCESSED\n"));
  634. return (GCC_CALLBACK_PROCESSED);
  635. }
  636. //*************************************************************
  637. //
  638. // TSrvRegisterNC()
  639. //
  640. // Purpose: Registers TShareSrv as Node Comtroller
  641. //
  642. // Parameters: void
  643. //
  644. // Return: TRUE - Success
  645. // FALSE - Failure
  646. //
  647. // History: 07-17-97 BrianTa Created
  648. //
  649. //*************************************************************
  650. BOOL
  651. TSrvRegisterNC(void)
  652. {
  653. USHORT usCapMask;
  654. USHORT usInitFlags;
  655. GCCVersion gccVersion;
  656. GCCVersion highVersion;
  657. GCCVersion versionRequested;
  658. GCCError GCCrc;
  659. TRACE((DEBUG_TSHRSRV_FLOW,
  660. "TShrSRV: TSrvRegisterNC entry\n"));
  661. usInitFlags = 0xffff;
  662. usCapMask = 0xffff;
  663. versionRequested.major_version = 1;
  664. versionRequested.minor_version = 0;
  665. TRACE((DEBUG_TSHRSRV_NORMAL, "TShrSRV: Registering Node Controller\n"));
  666. GCCrc = GCCRegisterNodeControllerApplication(TSrvGCCCallBack,
  667. NULL,
  668. versionRequested,
  669. &usInitFlags,
  670. &g_GCCAppID,
  671. &usCapMask,
  672. &highVersion,
  673. &gccVersion);
  674. g_fGCCRegistered = (GCCrc == GCC_NO_ERROR);
  675. if (g_fGCCRegistered)
  676. {
  677. TRACE((DEBUG_TSHRSRV_DETAIL,
  678. "TShrSRV: RegNC - usInitFlags 0x%x, AppID 0x%x, capMask 0x%x\n",
  679. usInitFlags, g_GCCAppID, usCapMask));
  680. TRACE((DEBUG_TSHRSRV_DETAIL,
  681. "TShrSRV: RegNC - High Version (major %d, minor %d)\n",
  682. highVersion.major_version,
  683. highVersion.minor_version));
  684. TRACE((DEBUG_TSHRSRV_DETAIL,
  685. "TShrSRV: RegNC - Version (major %d, minor %d)\n",
  686. gccVersion.major_version,
  687. gccVersion.minor_version));
  688. }
  689. TRACE((DEBUG_TSHRSRV_FLOW,
  690. "TShrSRV: TSrvRegisterNC exit - 0x%x\n", g_fGCCRegistered));
  691. return (g_fGCCRegistered);
  692. }
  693. //*************************************************************
  694. //
  695. // TSrvUnregisterNC()
  696. //
  697. // Purpose: Unregisters TShareSrv as Node Controller
  698. //
  699. // Parameters: void
  700. //
  701. // Return: void
  702. //
  703. // History: 07-17-97 BrianTa Created
  704. //
  705. //*************************************************************
  706. void
  707. TSrvUnregisterNC(void)
  708. {
  709. GCCError GCCrc;
  710. TRACE((DEBUG_TSHRSRV_FLOW, "TShrSRV: TSrvUnregisterNC entry\n"));
  711. if (g_fGCCRegistered)
  712. {
  713. TRACE((DEBUG_TSHRSRV_NORMAL, "TShrSRV: Performing GCCCleanup\n"));
  714. GCCrc = GCCCleanup(g_GCCAppID);
  715. g_fGCCRegistered = FALSE;
  716. TSrvDumpGCCRCDetails(GCCrc, "TShrSRV: GCCCleanup\n");
  717. }
  718. TRACE((DEBUG_TSHRSRV_FLOW, "TShrSRV: TSrvUnregisterNC exit\n"));
  719. }
  720. //*************************************************************
  721. //
  722. // TSrvBindStack()
  723. //
  724. // Purpose: Initiates MCSMux stack association
  725. //
  726. // Parameters: IN [pTSrvInfo] - TShareSrv object
  727. //
  728. // Return: void
  729. //
  730. // History: 07-17-97 BrianTa Created
  731. //
  732. //*************************************************************
  733. NTSTATUS
  734. TSrvBindStack(IN PTSRVINFO pTSrvInfo)
  735. {
  736. NTSTATUS ntStatus;
  737. GCCError GCCrc;
  738. TRACE((DEBUG_TSHRSRV_FLOW,
  739. "TShrSRV: TSrvBindStack entry\n"));
  740. TS_ASSERT(pTSrvInfo);
  741. TS_ASSERT(pTSrvInfo->hStack);
  742. TRACE((DEBUG_TSHRSRV_NORMAL, "TShrSRV: Binding Ica stack\n"));
  743. GCCrc = GCCConferenceInit(pTSrvInfo->hIca,
  744. pTSrvInfo->hStack,
  745. pTSrvInfo,
  746. &pTSrvInfo->hDomain);
  747. if (GCCrc == GCC_NO_ERROR)
  748. {
  749. ntStatus = STATUS_SUCCESS;
  750. TRACE((DEBUG_TSHRSRV_DEBUG, "TShrSRV: Ica stack bound successfully\n"));
  751. }
  752. else
  753. {
  754. ntStatus = STATUS_UNSUCCESSFUL;
  755. pTSrvInfo->hDomain = NULL;
  756. TRACE((DEBUG_TSHRSRV_ERROR,
  757. "TShrSRV: Unable to bind stack - hStack %p, GCCrc 0x%x\n",
  758. pTSrvInfo->hStack, GCCrc));
  759. }
  760. TRACE((DEBUG_TSHRSRV_FLOW,
  761. "TShrSRV: TSrvBindStack exit - 0x%x\n", ntStatus));
  762. return (ntStatus);
  763. }
  764. //*************************************************************
  765. //
  766. // TSrvInitWDConnectInfo()
  767. //
  768. // Purpose: Performs WDTshare connection initialization
  769. //
  770. // Return: STATUS_SUCCESS - Success
  771. // other - Failure
  772. //
  773. // History: 07-17-97 BrianTa Created
  774. //
  775. //*************************************************************
  776. NTSTATUS
  777. TSrvInitWDConnectInfo(IN HANDLE hStack,
  778. IN PTSRVINFO pTSrvInfo,
  779. IN OUT PUSERDATAINFO *ppUserDataInfo,
  780. IN ULONG ioctl,
  781. IN PBYTE pModuleData,
  782. IN ULONG cbModuleData,
  783. IN BOOLEAN bGetCert,
  784. OUT PVOID *ppSecInfo)
  785. {
  786. int i;
  787. ULONG ulInBufferSize;
  788. ULONG ulBytesReturned;
  789. PUSERDATAINFO pUserDataInfo;
  790. PUSERDATAINFO pUserDataInfo2;
  791. NTSTATUS ntStatus;
  792. TRACE((DEBUG_TSHRSRV_FLOW,
  793. "TShrSRV: TSrvInitWDConnectInfo entry\n"));
  794. // For a standard connection we receive client user data as part of the
  795. // GCC connection request. Shadow connections are initiated via RPC and
  796. // the input buffer contains the format sent by the other TS.
  797. if (ioctl == IOCTL_TSHARE_CONF_CONNECT) {
  798. TS_ASSERT(pTSrvInfo->pUserDataInfo);
  799. TS_ASSERT(pTSrvInfo->pUserDataInfo->cbSize);
  800. }
  801. // Allocate a block of memory to receive return UserData from
  802. // WDTShare. This data will subsequently be sent to the client
  803. // via TSrvConfCreateResp.
  804. pUserDataInfo = TSHeapAlloc(0, 128, TS_HTAG_TSS_USERDATA_OUT);
  805. if (pUserDataInfo != NULL) {
  806. // Set the UserData cbSize element. This is so that WDTShare can
  807. // determine if there is sufficient space available to place the
  808. // return data into
  809. pUserDataInfo->cbSize = 128 ;
  810. TRACE((DEBUG_TSHRSRV_DETAIL,
  811. "TShrSRV: Allocated 0x%x bytes to recieve WDTShare return data\n",
  812. pUserDataInfo->cbSize));
  813. // Exchange UserData with WDTShare. If the provided output buffer
  814. // (pUserDataInfo) is large enough then the data will be exchanged
  815. // in one call. If the buffer is not large enough, then it is up to
  816. // WDTShare to tell TShareSRV how to react. For general errors we
  817. // just exit. For STATUS_BUFFER_TOO_SMALL errors, TShareSrv looks at
  818. // the returned cbSize to determine how to adjust the buffer. If
  819. // WDTShare did not increase the cbSize then TShareSrv will increase
  820. // it by a default amount (128 bytes). TShareSrv will use the new value
  821. // to reallocate the output buffer and try the WDTShare call again.
  822. // (Note that TShareSrv will only try this a max of 20 times)
  823. for (i = 0; i < 20; i++) {
  824. TRACE((DEBUG_TSHRSRV_NORMAL, "TShrSRV: Performing connect (size=%ld)\n",
  825. pUserDataInfo->cbSize));
  826. ulBytesReturned = 0;
  827. // Pass the actual client user data to the WD
  828. if (ioctl == IOCTL_TSHARE_CONF_CONNECT) {
  829. ntStatus = IcaStackIoControl(hStack,
  830. ioctl,
  831. pTSrvInfo->pUserDataInfo,
  832. pTSrvInfo->pUserDataInfo->cbSize,
  833. pUserDataInfo,
  834. pUserDataInfo->cbSize,
  835. &ulBytesReturned);
  836. }
  837. // Pass the shadow module data to the WD
  838. else {
  839. ntStatus = IcaStackIoControl(hStack,
  840. ioctl,
  841. pModuleData,
  842. cbModuleData,
  843. pUserDataInfo,
  844. pUserDataInfo->cbSize,
  845. &ulBytesReturned);
  846. }
  847. if (ntStatus != STATUS_BUFFER_TOO_SMALL)
  848. break;
  849. // The output buffer is too small, if WDTShare told us how big to make
  850. // the buffer then we are all set. Otherwise, by default, bump the buffer
  851. // up by 128 bytes
  852. if (ulBytesReturned < sizeof(pUserDataInfo->cbSize))
  853. {
  854. pUserDataInfo->cbSize += 128;
  855. TRACE((DEBUG_TSHRSRV_DEBUG,
  856. "TShrSRV: Buffer too small - increasing it by 128 bytes to %d\n",
  857. pUserDataInfo->cbSize));
  858. }
  859. else
  860. {
  861. TRACE((DEBUG_TSHRSRV_DEBUG,
  862. "TShrSRV: Buffer too small - WDTShare set it to %d bytes\n",
  863. pUserDataInfo->cbSize));
  864. }
  865. pUserDataInfo2 = TSHeapReAlloc(0, pUserDataInfo, pUserDataInfo->cbSize);
  866. if (!pUserDataInfo2)
  867. {
  868. TRACE((DEBUG_TSHRSRV_WARN,
  869. "TShrSRV: Unable to allocate %d byte userData buffer\n"));
  870. break;
  871. }
  872. else {
  873. pUserDataInfo = pUserDataInfo2;
  874. }
  875. }
  876. }
  877. else
  878. {
  879. TRACE((DEBUG_TSHRSRV_WARN,
  880. "TShrSRV: Unable to allocate 0x%x bytes to recieve WDTShare return data\n",
  881. pUserDataInfo->cbSize));
  882. ntStatus = STATUS_NO_MEMORY;
  883. }
  884. // Free the input (client generated) UserData - we don't need it
  885. // lying aroung anymore.
  886. if (pTSrvInfo->pUserDataInfo != NULL) {
  887. TSHeapFree(pTSrvInfo->pUserDataInfo);
  888. pTSrvInfo->pUserDataInfo = NULL;
  889. }
  890. // If we succeeded in the exchange of info, add security info.
  891. if (NT_SUCCESS(ntStatus))
  892. {
  893. TS_ASSERT( pUserDataInfo != NULL );
  894. //
  895. // add user mode security data to the pUserDataInfo if we originally
  896. // received user data from the client.
  897. //
  898. ntStatus = AppendSecurityData(pTSrvInfo, &pUserDataInfo, bGetCert, ppSecInfo);
  899. }
  900. if (!NT_SUCCESS(ntStatus)) {
  901. if (pUserDataInfo != NULL) {
  902. TSHeapFree(pUserDataInfo);
  903. pUserDataInfo = NULL;
  904. }
  905. }
  906. // Return this pointer since the underlying routine does a realloc on it
  907. *ppUserDataInfo = pUserDataInfo;
  908. TRACE((DEBUG_TSHRSRV_FLOW,
  909. "TShrSRV: TSrvInitWDConnectInfo exit - 0x%x\n", ntStatus));
  910. return ntStatus;
  911. }
  912. //*************************************************************
  913. // TSrvShadowTargetConnect
  914. //
  915. // Purpose: Sends the shadow server's certificate and server
  916. // random to the client server for validation, then
  917. // waits for an encrypted client random to be returned.
  918. //
  919. // Return: STATUS_SUCCESS - Success
  920. // other - Failure
  921. //
  922. // History: 4/26/99 jparsons Created
  923. //*************************************************************
  924. NTSTATUS TSrvShadowTargetConnect(
  925. HANDLE hStack,
  926. PTSRVINFO pTSrvInfo,
  927. PBYTE pModuleData,
  928. ULONG cbModuleData)
  929. {
  930. PUSERDATAINFO pUserDataInfo;
  931. NTSTATUS status;
  932. PVOID pSecInfo;
  933. pUserDataInfo = NULL;
  934. status = TSrvInitWDConnectInfo(hStack,
  935. pTSrvInfo,
  936. &pUserDataInfo,
  937. IOCTL_TSHARE_SHADOW_CONNECT,
  938. pModuleData,
  939. cbModuleData,
  940. TRUE,
  941. &pSecInfo);
  942. if (status == STATUS_SUCCESS) {
  943. status = SendSecurityData(hStack, pSecInfo);
  944. if (NT_SUCCESS(status)) {
  945. if (pTSrvInfo->bSecurityEnabled) {
  946. NTSTATUS TempStatus;
  947. // We use the result of GetClientRandom() as the status to
  948. // determine the CreateSessionKeys() IOCTL type. We ignore
  949. // the return from CreateSessionKeys() is the client random
  950. // is not successful.
  951. status = GetClientRandom(hStack, pTSrvInfo, 15000, TRUE);
  952. if (!NT_SUCCESS(status)) {
  953. TRACE((DEBUG_TSHRSRV_ERROR,
  954. "TShrSRV: Could not get client random [%lx]\n",
  955. status));
  956. }
  957. TempStatus = CreateSessionKeys(hStack, pTSrvInfo, status);
  958. if (NT_SUCCESS(status))
  959. status = TempStatus;
  960. }
  961. }
  962. else {
  963. TRACE((DEBUG_TSHRSRV_ERROR,
  964. "TShrSRV: Could not send shadow security info[%lx]\n", status));
  965. }
  966. }
  967. else {
  968. TRACE((DEBUG_TSHRSRV_ERROR,
  969. "TShrSRV: Could not initialize shadow target [%lx]\n", status));
  970. }
  971. if (NT_SUCCESS(status)) {
  972. TRACE((DEBUG_TSHRSRV_NORMAL,
  973. "TShrSRV: Shadow target security exchange complete!\n"));
  974. }
  975. return status;
  976. }
  977. //*************************************************************
  978. //
  979. // TSrvShadowClientConnect
  980. //
  981. // Purpose: Validate the certificate received from the shadow
  982. // client's server. If legit generate and encrypt a
  983. // client random for use by the shadow server
  984. // client.
  985. //
  986. // Return: STATUS_SUCCESS - Success
  987. // other - Failure
  988. //
  989. // History: 4/26/99 jparsons Created
  990. //
  991. //*************************************************************
  992. NTSTATUS TSrvShadowClientConnect(HANDLE hStack, PTSRVINFO pTSrvInfo)
  993. {
  994. CERT_TYPE certType;
  995. ULONG cbServerPubKey;
  996. PBYTE pbServerPubKey = NULL;
  997. ULONG cbServerRandom;
  998. PBYTE pbServerRandom;
  999. PVOID pSecInfo;
  1000. PUSERDATAINFO pUserDataInfo;
  1001. NTSTATUS status;
  1002. pUserDataInfo = NULL;
  1003. status = TSrvInitWDConnectInfo(hStack,
  1004. pTSrvInfo,
  1005. &pUserDataInfo,
  1006. IOCTL_TSHARE_SHADOW_CONNECT,
  1007. (PBYTE) NULL,
  1008. 0,
  1009. FALSE,
  1010. &pSecInfo);
  1011. if (status == STATUS_SUCCESS) {
  1012. // This is the client passthru stack so validate the shadow server's
  1013. // certificate and if good, store the server random.
  1014. pbServerRandom = pTSrvInfo->SecurityInfo.KeyPair.serverRandom;
  1015. cbServerRandom = sizeof(pTSrvInfo->SecurityInfo.KeyPair.serverRandom);
  1016. status = TSrvValidateServerCertificate(
  1017. hStack,
  1018. &certType,
  1019. &cbServerPubKey,
  1020. &pbServerPubKey,
  1021. cbServerRandom,
  1022. pbServerRandom,
  1023. 15000);
  1024. if (NT_SUCCESS(status)) {
  1025. TRACE((DEBUG_TSHRSRV_NORMAL,
  1026. "TShrSRV: Validated server cert[%s]: PublicKeyLength = %ld\n",
  1027. (certType == CERT_TYPE_X509) ? "X509" :
  1028. ((certType == CERT_TYPE_PROPRIETORY) ? "PROPRIETORY" :
  1029. "INVALID"), cbServerPubKey));
  1030. // If encryption is enabled, then we need to encrypt a client random
  1031. // with the shadow server's public key, and send it.
  1032. if (cbServerPubKey != 0) {
  1033. BOOL success;
  1034. EnterCriticalSection( &g_TSrvCritSect );
  1035. success = TSRNG_GenerateRandomBits(
  1036. pTSrvInfo->SecurityInfo.KeyPair.clientRandom,
  1037. sizeof(pTSrvInfo->SecurityInfo.KeyPair.clientRandom));
  1038. LeaveCriticalSection( &g_TSrvCritSect );
  1039. if (!success) {
  1040. TRACE((DEBUG_TSHRSRV_ERROR,
  1041. "TShrSRV: Could not generate a client random!\n"));
  1042. }
  1043. // We use the result of TSRNG_GenerateRandomBits() to determine the
  1044. // CreateSessionKeys() IOCTL type.
  1045. status = CreateSessionKeys(hStack, pTSrvInfo,
  1046. (success ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL));
  1047. // send encrypted client random to the other server
  1048. if (NT_SUCCESS(status)) {
  1049. status = SendClientRandom(
  1050. hStack,
  1051. certType,
  1052. pbServerPubKey,
  1053. cbServerPubKey,
  1054. pTSrvInfo->SecurityInfo.KeyPair.clientRandom,
  1055. sizeof(pTSrvInfo->SecurityInfo.KeyPair.clientRandom));
  1056. }
  1057. if (pbServerPubKey != NULL) {
  1058. TSHeapFree(pbServerPubKey);
  1059. pbServerPubKey = NULL;
  1060. }
  1061. if (NT_SUCCESS(status)) {
  1062. TRACE((DEBUG_TSHRSRV_NORMAL,
  1063. "TShrSRV: Shadow client security exchange complete!\n"));
  1064. }
  1065. }
  1066. }
  1067. else {
  1068. TRACE((DEBUG_TSHRSRV_ERROR,
  1069. "TShrSRV: Validation failed on shadow certificate rc=%lx\n",
  1070. status));
  1071. if (status == STATUS_IO_TIMEOUT) {
  1072. status = STATUS_DECRYPTION_FAILED;
  1073. }
  1074. }
  1075. }
  1076. else {
  1077. TRACE((DEBUG_TSHRSRV_ERROR,
  1078. "TShrSRV: Could not initialize shadow client [%lx]\n", status));
  1079. }
  1080. return status;
  1081. }
  1082. //*************************************************************
  1083. //
  1084. // TSrvInitWD()
  1085. //
  1086. // Purpose: Performs WDTshare initialization
  1087. //
  1088. // Parameters: IN [pTSrvInfo] - TShareSrv object
  1089. // IN OUT [ppUserDataInfo] - pointer to generated user data
  1090. //
  1091. // Return: STATUS_SUCCESS - Success
  1092. // other - Failure
  1093. //
  1094. // History: 07-17-97 BrianTa Created
  1095. //
  1096. //*************************************************************
  1097. NTSTATUS
  1098. TSrvInitWD(IN PTSRVINFO pTSrvInfo, IN OUT PUSERDATAINFO *ppUserDataInfo)
  1099. {
  1100. NTSTATUS ntStatus;
  1101. PVOID pSecData;
  1102. TRACE((DEBUG_TSHRSRV_FLOW,
  1103. "TShrSRV: TSrvInitWD entry\n"));
  1104. // Pass on connection information
  1105. TRACE((DEBUG_TSHRSRV_NORMAL,
  1106. "TShrSRV: Performing WDTShare connection info exchange\n"));
  1107. ntStatus = TSrvInitWDConnectInfo(pTSrvInfo->hStack,
  1108. pTSrvInfo,
  1109. ppUserDataInfo,
  1110. IOCTL_TSHARE_CONF_CONNECT,
  1111. NULL, 0, TRUE, &pSecData);
  1112. if (!NT_SUCCESS(ntStatus))
  1113. {
  1114. TRACE((DEBUG_TSHRSRV_DEBUG,
  1115. "TShrSRV: WDTShare connection info exchange unsuccessful - 0x%x\n", ntStatus));
  1116. }
  1117. TRACE((DEBUG_TSHRSRV_FLOW,
  1118. "TShrSRV: TSrvInitWD exit - 0x%x\n", ntStatus));
  1119. return (ntStatus);
  1120. }
  1121. //*************************************************************
  1122. //
  1123. // TSrvCreateGCCDataList()
  1124. //
  1125. // Purpose: Creates a Gcc UserData indirection list and
  1126. // re-bases the UserData data pointers
  1127. //
  1128. // Parameters: IN [pTSrvInfo] - TShareSrv object
  1129. //
  1130. // Return: ppDataList
  1131. //
  1132. // History: 07-17-97 BrianTa Created
  1133. //
  1134. //*************************************************************
  1135. GCCUserData **
  1136. TSrvCreateGCCDataList(IN PTSRVINFO pTSrvInfo, PUSERDATAINFO pUserDataInfo)
  1137. {
  1138. DWORD i;
  1139. GCCUserData **ppDataList;
  1140. GCCUserData *pUserData;
  1141. TRACE((DEBUG_TSHRSRV_FLOW,
  1142. "TShrSRV: TSrvCreateGCCDataList entry\n"));
  1143. ppDataList = NULL;
  1144. TS_ASSERT(pUserDataInfo);
  1145. if (pUserDataInfo)
  1146. {
  1147. TRACE((DEBUG_TSHRSRV_DETAIL, "TShrSRV: Creating UserData list\n"));
  1148. TS_ASSERT(pUserDataInfo->ulUserDataMembers > 0);
  1149. // Allocate UserData list memory
  1150. ppDataList = TSHeapAlloc(HEAP_ZERO_MEMORY,
  1151. sizeof(GCCUserData *) * pUserDataInfo->ulUserDataMembers,
  1152. TS_HTAG_TSS_USERDATA_LIST);
  1153. if (ppDataList)
  1154. {
  1155. TRACE((DEBUG_TSHRSRV_DETAIL,
  1156. "TShrSRV: Allocated 0x%x bytes for 0x%x member UserData array\n",
  1157. sizeof(GCCUserData *) * pUserDataInfo->ulUserDataMembers,
  1158. pUserDataInfo->ulUserDataMembers));
  1159. for (i=0; i<pUserDataInfo->ulUserDataMembers; i++)
  1160. {
  1161. pUserData = &pUserDataInfo->rgUserData[i];
  1162. // Key data rebase
  1163. if (pUserData->key.key_type == GCC_OBJECT_KEY)
  1164. {
  1165. (PUCHAR) pUserData->key.u.object_id.long_string +=
  1166. (ULONG_PTR) pUserDataInfo;
  1167. }
  1168. else
  1169. {
  1170. (PUCHAR) pUserData->key.u.h221_non_standard_id.octet_string +=
  1171. (ULONG_PTR)pUserDataInfo;
  1172. }
  1173. // Client data ptr, and data rebase
  1174. if (pUserData->octet_string)
  1175. {
  1176. (PUCHAR) pUserData->octet_string +=
  1177. (ULONG_PTR)pUserDataInfo;
  1178. if (pUserData->octet_string->octet_string)
  1179. {
  1180. (PUCHAR) pUserData->octet_string->octet_string +=
  1181. (ULONG_PTR) pUserDataInfo;
  1182. }
  1183. }
  1184. // Assign the table list entry
  1185. ppDataList[i] = pUserData;
  1186. }
  1187. }
  1188. else
  1189. {
  1190. TRACE((DEBUG_TSHRSRV_WARN,
  1191. "TShrSRV: Unable to allocate 0x%x bytes for 0x%x member UserData array\n",
  1192. sizeof(GCCUserData *) * pUserDataInfo->ulUserDataMembers,
  1193. pUserDataInfo->ulUserDataMembers));
  1194. }
  1195. }
  1196. else
  1197. {
  1198. TRACE((DEBUG_TSHRSRV_WARN, "TShrSRV: Not creating UserData list - no UserData\n"));
  1199. }
  1200. TRACE((DEBUG_TSHRSRV_FLOW,
  1201. "TShrSRV: TSrvCreateGCCDataList exit = 0x%x\n", ppDataList));
  1202. return (ppDataList);
  1203. }
  1204. //*************************************************************
  1205. //
  1206. // TSrvConfCreateResp()
  1207. //
  1208. // Purpose: Performs GCCConferenceCreateResponse
  1209. //
  1210. // Parameters: IN [pTSrvInfo] - TShareSrv object
  1211. //
  1212. // Return: STATUS_SUCCESS - Success
  1213. // other - Failure
  1214. //
  1215. // History: 07-17-97 BrianTa Created
  1216. //
  1217. //*************************************************************
  1218. NTSTATUS
  1219. TSrvConfCreateResp(IN OUT PTSRVINFO pTSrvInfo)
  1220. {
  1221. NTSTATUS ntStatus;
  1222. GCCError GCCrc;
  1223. GCCUserData **pDataList;
  1224. PUSERDATAINFO pUserDataInfo;
  1225. TRACE((DEBUG_TSHRSRV_FLOW,
  1226. "TShrSRV: TSrvConfCreateResp entry\n"));
  1227. ntStatus = pTSrvInfo->ntStatus;
  1228. pUserDataInfo = NULL;
  1229. if (NT_SUCCESS(ntStatus))
  1230. {
  1231. TRACE((DEBUG_TSHRSRV_DEBUG, "TShrSRV: Attempting ConfCreate response\n"));
  1232. // Perform WDTShare connection initialization
  1233. ntStatus = TSrvInitWD(pTSrvInfo, &pUserDataInfo);
  1234. pTSrvInfo->ntStatus = ntStatus;
  1235. if (NT_SUCCESS(ntStatus))
  1236. {
  1237. // The exchange of info with WDTShare has proceeded successfully,
  1238. // So we can now create a digestable data transfer structure
  1239. // for GCC
  1240. pDataList = TSrvCreateGCCDataList(pTSrvInfo, pUserDataInfo);
  1241. if (pDataList)
  1242. {
  1243. // Accept the conference creation request
  1244. TRACE((DEBUG_TSHRSRV_NORMAL, "TShrSRV: Accepting conference domain %p\n",
  1245. pTSrvInfo->hDomain));
  1246. GCCrc = GCCConferenceCreateResponse(
  1247. NULL, // conference_modifier
  1248. pTSrvInfo->hDomain, // domain handle
  1249. 0, // use_password_in_the_clear
  1250. NULL, // domain_parameters
  1251. 0, // number_of_network_addresses
  1252. NULL, // local_network_address_list
  1253. 1, // number_of_user_data_members
  1254. (GCCUserData**)pDataList, // user_data_list
  1255. GCC_RESULT_SUCCESSFUL); // reason
  1256. TSrvDumpGCCRCDetails(GCCrc,
  1257. "GCCConferenceCreateResponse");
  1258. if (GCCrc == GCC_NO_ERROR)
  1259. ntStatus = STATUS_SUCCESS;
  1260. else
  1261. ntStatus = STATUS_REQUEST_NOT_ACCEPTED;
  1262. TSHeapFree(pDataList);
  1263. }
  1264. else
  1265. {
  1266. ntStatus = STATUS_NO_MEMORY;
  1267. }
  1268. }
  1269. else
  1270. {
  1271. // Conference is being rejected
  1272. TRACE((DEBUG_TSHRSRV_NORMAL, "TShrSRV: Rejecting conference domain %p - 0x%x\n",
  1273. pTSrvInfo->hDomain, pTSrvInfo->ntStatus));
  1274. GCCrc = GCCConferenceCreateResponse(
  1275. NULL, // conference_modifier
  1276. pTSrvInfo->hDomain, // domain
  1277. 0, // use_password_in_the_clear
  1278. NULL, // domain_parameters
  1279. 0, // number_of_network_addresses
  1280. NULL, // local_network_address_list
  1281. 1, // number_of_user_data_members
  1282. NULL, // user_data_list
  1283. GCC_RESULT_USER_REJECTED); // reason
  1284. TSrvDumpGCCRCDetails(GCCrc,
  1285. "TShrSRV: GCCConferenceCreateResponse\n");
  1286. // Return the original failure status back to the caller
  1287. ntStatus = pTSrvInfo->ntStatus;
  1288. }
  1289. }
  1290. else {
  1291. TRACE((DEBUG_TSHRSRV_ERROR,
  1292. "TShrSRV: Connect failure, could not generate response: %lx\n",
  1293. ntStatus));
  1294. }
  1295. if (NT_SUCCESS(ntStatus))
  1296. {
  1297. //
  1298. // if we successfully sent the conference connect response, then
  1299. // check security response (only if we need to).
  1300. //
  1301. if (pTSrvInfo->bSecurityEnabled) {
  1302. NTSTATUS TempStatus;
  1303. // We use the result of GetClientRandom() as the status to
  1304. // determine the CreateSessionKeys() IOCTL type. We ignore the
  1305. // return from CreateSessionKeys() if the client random is
  1306. // not successful.
  1307. ntStatus = GetClientRandom(pTSrvInfo->hStack, pTSrvInfo, 60000,
  1308. FALSE);
  1309. TempStatus = CreateSessionKeys(pTSrvInfo->hStack, pTSrvInfo,
  1310. ntStatus);
  1311. if (NT_SUCCESS(ntStatus))
  1312. ntStatus = TempStatus;
  1313. }
  1314. }
  1315. // If we still have a UserData structure, free it, we no longer need it.
  1316. if (pUserDataInfo)
  1317. {
  1318. TSHeapFree(pUserDataInfo);
  1319. pUserDataInfo = NULL;
  1320. }
  1321. TRACE((DEBUG_TSHRSRV_FLOW,
  1322. "TShrSRV: TSrvConfCreateResp exit = 0x%x\n", ntStatus));
  1323. return (ntStatus);
  1324. }
  1325. //*************************************************************
  1326. //
  1327. // TSrvConfDisconnectReq()
  1328. //
  1329. // Purpose: Performs GCCConferenceTerminateRequest
  1330. //
  1331. // Parameters: IN [pTSrvInfo] - TShareSrv object
  1332. // IN [ulReason] - Reason code
  1333. //
  1334. // Return: STATUS_SUCCESS - Success
  1335. // other - Failure
  1336. //
  1337. // History: 07-17-97 BrianTa Created
  1338. //
  1339. //*************************************************************
  1340. NTSTATUS
  1341. TSrvConfDisconnectReq(IN PTSRVINFO pTSrvInfo,
  1342. IN ULONG ulReason)
  1343. {
  1344. GCCError GCCrc;
  1345. NTSTATUS ntStatus;
  1346. TRACE((DEBUG_TSHRSRV_FLOW,
  1347. "TShrSRV: TSrvConfDisconnectReq entry\n"));
  1348. ntStatus = STATUS_REQUEST_ABORTED;
  1349. TRACE((DEBUG_TSHRSRV_NORMAL,
  1350. "TShrSRV: Conf termination - domain %p - reason 0x%x\n",
  1351. pTSrvInfo->hDomain, ulReason));
  1352. GCCrc = GCCConferenceTerminateRequest(pTSrvInfo->hIca, pTSrvInfo->hDomain,
  1353. pTSrvInfo->hConnection, ulReason);
  1354. TSrvDumpGCCRCDetails(GCCrc,
  1355. "GCCConferenceTerminateRequest");
  1356. if (GCCrc == GCC_NO_ERROR)
  1357. ntStatus = STATUS_SUCCESS;
  1358. TRACE((DEBUG_TSHRSRV_FLOW,
  1359. "TShrSRV: TSrvConfDisconnectReq exit = 0x%x\n", ntStatus));
  1360. return (ntStatus);
  1361. }
  1362. //-----
  1363. #if DBG
  1364. //-----
  1365. //*************************************************************
  1366. //
  1367. // TSrvBuildNameFromGCCConfName()
  1368. //
  1369. // Purpose: Build a traceable conference name from
  1370. // a GCC name
  1371. //
  1372. // Parameters: IN [gccName] - GCCConferenceName
  1373. // OUT [pConfName] - Traceable name
  1374. //
  1375. // Return: STATUS_SUCCESS - Success
  1376. // other - Failure
  1377. //
  1378. // History: 07-17-97 BrianTa Created
  1379. //
  1380. //*************************************************************
  1381. void
  1382. TSrvBuildNameFromGCCConfName(IN GCCConferenceName *gccName,
  1383. OUT PCHAR pConfName)
  1384. {
  1385. int i;
  1386. // The text represenation of a GCC conference name is:
  1387. //
  1388. // <text_string> : (<numeric_string>)
  1389. i = 0;
  1390. while (gccName->text_string[i] != 0x0000)
  1391. {
  1392. pConfName[i] = (CHAR)gccName->text_string[i];
  1393. i++;
  1394. }
  1395. pConfName[i] = '\0';
  1396. }
  1397. //*************************************************************
  1398. //
  1399. // TSrvDumpCreateIndDetails()
  1400. //
  1401. // Purpose: Dumps out GCC_CREATE_IND details
  1402. //
  1403. // Parameters: IN [pCreateMessage] - CreateIndicationMessage
  1404. //
  1405. // Return: void
  1406. //
  1407. // History: 07-17-97 BrianTa Created
  1408. //
  1409. //*************************************************************
  1410. void
  1411. TSrvDumpCreateIndDetails(IN CreateIndicationMessage *pCreateMessage)
  1412. {
  1413. CHAR name[MAX_CONFERENCE_NAME_LEN];
  1414. if (pCreateMessage->conductor_privilege_list == NULL)
  1415. {
  1416. TRACE((DEBUG_TSHRSRV_DETAIL,
  1417. "TShrSRV: Conductor privilege list is NULL\n"));
  1418. }
  1419. else
  1420. {
  1421. TRACE((DEBUG_TSHRSRV_DETAIL,
  1422. "TShrSRV: Conductor priv, terminate allowed 0x%x\n",
  1423. pCreateMessage->conductor_privilege_list->terminate_is_allowed));
  1424. }
  1425. if (pCreateMessage->conducted_mode_privilege_list == NULL)
  1426. {
  1427. TRACE((DEBUG_TSHRSRV_DETAIL,
  1428. "TShrSRV: Conducted mode privilege list is NULL\n"));
  1429. }
  1430. else
  1431. {
  1432. TRACE((DEBUG_TSHRSRV_DETAIL,
  1433. "TShrSRV: Conducted mode priv, terminate allowed 0x%x\n",
  1434. pCreateMessage->conducted_mode_privilege_list->terminate_is_allowed));
  1435. }
  1436. if (pCreateMessage->non_conducted_privilege_list == NULL)
  1437. {
  1438. TRACE((DEBUG_TSHRSRV_DETAIL,
  1439. "TShrSRV: Non-conducted mode privilege list is NULL\n"));
  1440. }
  1441. else
  1442. {
  1443. TRACE((DEBUG_TSHRSRV_DETAIL,
  1444. "TShrSRV: non-conducted priv, terminate allowed 0x%x\n",
  1445. pCreateMessage->non_conducted_privilege_list->terminate_is_allowed));
  1446. }
  1447. if (pCreateMessage->conference_name.text_string == NULL)
  1448. {
  1449. TRACE((DEBUG_TSHRSRV_DETAIL,
  1450. "TShrSRV: NULL conf name\n"));
  1451. }
  1452. else
  1453. {
  1454. TSrvBuildNameFromGCCConfName(&(pCreateMessage->conference_name), name);
  1455. TRACE((DEBUG_TSHRSRV_DETAIL,
  1456. "TShrSRV: Conf name '%s'\n", name));
  1457. }
  1458. }
  1459. //*************************************************************
  1460. //
  1461. // TSrvDumpGCCRCDetails()
  1462. //
  1463. // Purpose: Dumps out GCC return code details
  1464. //
  1465. // Parameters: IN [GCCrc] - GCC return code
  1466. // IN [pszText] - var text
  1467. //
  1468. // Return: void
  1469. //
  1470. // History: 07-17-97 BrianTa Created
  1471. //
  1472. //*************************************************************
  1473. void
  1474. TSrvDumpGCCRCDetails(IN GCCError gccRc,
  1475. IN PCHAR pszText)
  1476. {
  1477. int i;
  1478. PCHAR pszMessageText;
  1479. pszMessageText = "UNKNOWN_GCC_RC";
  1480. for (i=0; i<sizeof(GCCReturnCodeTBL) / sizeof(GCCReturnCodeTBL[0]); i++)
  1481. {
  1482. if (GCCReturnCodeTBL[i].gccRC == gccRc)
  1483. {
  1484. pszMessageText = GCCReturnCodeTBL[i].pszMessageText;
  1485. break;
  1486. }
  1487. }
  1488. TRACE((DEBUG_TSHRSRV_DETAIL,
  1489. "TShrSRV: %s - GCC rc 0x%x (%s)\n",
  1490. pszText, gccRc, pszMessageText));
  1491. }
  1492. //*************************************************************
  1493. //
  1494. // TSrvDumpGCCReasonDetails()
  1495. //
  1496. // Purpose: Dumps out GCC reason code details
  1497. //
  1498. // Parameters: IN [gccReason] - GCC reason code
  1499. // IN [pszText] - var text
  1500. //
  1501. // Return: void
  1502. //
  1503. // History: 07-17-97 BrianTa Created
  1504. //
  1505. //*************************************************************
  1506. void
  1507. TSrvDumpGCCReasonDetails(IN GCCReason gccReason,
  1508. IN PCHAR pszText)
  1509. {
  1510. int i;
  1511. PCHAR pszMessageText;
  1512. pszMessageText = "UNKNOWN_GCC_REASON";
  1513. for (i=0; i<sizeof(GCCReasonTBL) / sizeof(GCCReasonTBL[0]); i++)
  1514. {
  1515. if (GCCReasonTBL[i].gccReason == gccReason)
  1516. {
  1517. pszMessageText = GCCReasonTBL[i].pszMessageText;
  1518. break;
  1519. }
  1520. }
  1521. TRACE((DEBUG_TSHRSRV_DETAIL,
  1522. "TShrSRV: %s - GCC reason 0x%x (%s)\n",
  1523. pszText, gccReason, pszMessageText));
  1524. }
  1525. //*************************************************************
  1526. //
  1527. // TSrvDumpCallBackMessage()
  1528. //
  1529. // Purpose: Dumps out GCC CallBackMessage details
  1530. //
  1531. // Parameters: IN [pGCCMessage] - GCCMessage
  1532. //
  1533. // Return: void
  1534. //
  1535. // History: 07-17-97 BrianTa Created
  1536. //
  1537. //*************************************************************
  1538. void
  1539. TSrvDumpCallBackMessage(IN GCCMessage *pGCCMessage)
  1540. {
  1541. int i;
  1542. PCHAR pszMessageText;
  1543. pszMessageText = "UNKNOWN_GCC_MESSAGE";
  1544. for (i=0; i<sizeof(GCCCallBackTBL) / sizeof(GCCCallBackTBL[0]); i++)
  1545. {
  1546. if (GCCCallBackTBL[i].message_type == pGCCMessage->message_type)
  1547. {
  1548. pszMessageText = GCCCallBackTBL[i].pszMessageText;
  1549. break;
  1550. }
  1551. }
  1552. TRACE((DEBUG_TSHRSRV_DEBUG,
  1553. "TShrSRV: GCCCallback message 0x%x (%s) received\n",
  1554. pGCCMessage->message_type, pszMessageText));
  1555. }
  1556. //*************************************************************
  1557. //
  1558. // TSrvDumpUserData()
  1559. //
  1560. // Purpose: Dumps out GCC UserData details
  1561. //
  1562. // Parameters: IN [pCreateMessage] - GCCMessage
  1563. //
  1564. // Return: void
  1565. //
  1566. // History: 07-17-97 BrianTa Created
  1567. //
  1568. //*************************************************************
  1569. void
  1570. TSrvDumpUserData(IN CreateIndicationMessage *pCreateMessage)
  1571. {
  1572. int i;
  1573. ULONG ulUserDataSize;
  1574. GCCUserData *pClientUserData;
  1575. TRACE((DEBUG_TSHRSRV_DETAIL,
  1576. "TShrSRV: number_of_user_data_members = 0x%x\n",
  1577. pCreateMessage->number_of_user_data_members));
  1578. for (i=0; i<pCreateMessage->number_of_user_data_members; i++)
  1579. {
  1580. pClientUserData = pCreateMessage->user_data_list[i];
  1581. if (pClientUserData != NULL)
  1582. {
  1583. if (pClientUserData->key.key_type == GCC_OBJECT_KEY)
  1584. {
  1585. TRACE((DEBUG_TSHRSRV_DETAIL,
  1586. "TShrSRV: key_type = 0x%x (GCC_OBJECT_KEY)\n",
  1587. pClientUserData->key.key_type));
  1588. TRACE((DEBUG_TSHRSRV_DETAIL,
  1589. "TShrSRV: Key long_string_length = 0x%x\n",
  1590. pClientUserData->key.u.object_id.long_string_length));
  1591. }
  1592. else
  1593. {
  1594. TRACE((DEBUG_TSHRSRV_DETAIL,
  1595. "TShrSRV: Key_type = 0x%x (GCC_H221_NONSTANDARD_KEY)\n",
  1596. pClientUserData->key.key_type));
  1597. TRACE((DEBUG_TSHRSRV_DETAIL,
  1598. "TShrSRV: key long_string_length = 0x%x\n",
  1599. pClientUserData->key.u.h221_non_standard_id.octet_string_length));
  1600. }
  1601. if (pClientUserData->octet_string)
  1602. {
  1603. TRACE((DEBUG_TSHRSRV_DETAIL,
  1604. "TShrSRV: data long_string_length = 0x%x\n",
  1605. pClientUserData->octet_string->octet_string_length));
  1606. }
  1607. else
  1608. {
  1609. TRACE((DEBUG_TSHRSRV_DETAIL, "TShrSRV: No data\n"));
  1610. }
  1611. }
  1612. else
  1613. {
  1614. TRACE((DEBUG_TSHRSRV_DETAIL, "TShrSRV: No key\n"));
  1615. }
  1616. }
  1617. }
  1618. #endif // DBG