Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2645 lines
95 KiB

  1. #include "precomp.h"
  2. DEBUG_FILEZONE(ZONE_T120_MSMCSTCP);
  3. #include <datguids.h>
  4. #include <nmqos.h>
  5. #include <t120qos.h>
  6. #include "tprtsec.h"
  7. #include <tsecctrl.h>
  8. #include <tprtntfy.h>
  9. #include "cnpcoder.h"
  10. #include "plgxprt.h"
  11. // #undef TRACE_OUT
  12. // #define TRACE_OUT WARNING_OUT
  13. /* Tprtctrl.cpp
  14. *
  15. * Copyright (c) 1996 by Microsoft Corporation
  16. *
  17. * Abstract:
  18. * This module maintains the TCP transport and all connections.
  19. *
  20. */
  21. /* External definitions */
  22. extern HINSTANCE g_hDllInst;
  23. extern PTransportInterface g_Transport;
  24. extern SOCKET Listen_Socket;
  25. extern SOCKET Listen_Socket_Secure;
  26. extern CRITICAL_SECTION csQOS;
  27. extern CPluggableTransport *g_pPluggableTransport;
  28. extern PController g_pMCSController;
  29. extern CCNPCoder *g_CNPCoder;
  30. extern HWND TCP_Window_Handle;
  31. BOOL FindSocketNumber(DWORD dwGCCID, SOCKET * socket_number);
  32. /*
  33. * The following array contains a template for the X.224 data header.
  34. * The 5 of the 7 bytes that it initializes are actually sent to the
  35. * wire. Bytes 3 and 4 will be set to contain the size of the PDU.
  36. * The array is only used when we encode a data PDU.
  37. */
  38. extern UChar g_X224Header[];
  39. // The external MCS Controller object
  40. extern PController g_pMCSController;
  41. // plugable transport prototypes
  42. int X224Recv(PSocket pSocket, LPBYTE buffer, int length, PLUGXPRT_RESULT *pnLastError);
  43. int Q922Recv(PSocket pSocket, LPBYTE buffer, int length, PLUGXPRT_RESULT *pnLastError);
  44. /*
  45. * void QoSLock(Void)
  46. *
  47. * Functional Description:
  48. * This function locks the QoS data
  49. * All other reader or writer threads will be blocked.
  50. */
  51. void QoSLock(Void)
  52. {
  53. EnterCriticalSection(&csQOS);
  54. }
  55. /*
  56. * void QoSUnlock(Void)
  57. *
  58. * Functional Description:
  59. * This function unlocks the QoS data
  60. * Waiting reader or writer threads will be unblocked.
  61. */
  62. void QoSUnlock(Void)
  63. {
  64. LeaveCriticalSection(&csQOS);
  65. }
  66. /*
  67. * TransportError ConnectRequest ( TransportAddress transport_address,
  68. * BOOL fSecure
  69. * PTransportConnection pXprtConn)
  70. *
  71. * Functional Description:
  72. * This function initiates a connection. It passes the transport address
  73. * to the TCP transport. It will either deny the request or accept the
  74. * request and call us back when the physical connection is established.
  75. *
  76. * We return the transport connection handle in the transport_connection
  77. * address. Although we return this transport number to the user, it
  78. * is not ready for data transfer until the user receives the
  79. * TRANSPORT_CONNECT_INDICATION and responds with a ConnectResponse() call.
  80. * At that point, the transport connection is up and running.
  81. */
  82. TransportError ConnectRequest (TransportAddress transport_address,
  83. BOOL fSecure,
  84. /* out */ PTransportConnection pXprtConn)
  85. {
  86. TransportError rc = TRANSPORT_NO_ERROR;
  87. PSocket pSocket;
  88. PSecurityContext pSC = NULL;
  89. ULong address;
  90. SOCKADDR_IN sin;
  91. CPluggableConnection *p = NULL;
  92. // initialize transport connection
  93. UINT nPluggableConnID = ::GetPluggableTransportConnID(transport_address);
  94. if (nPluggableConnID)
  95. {
  96. p = ::GetPluggableConnection(nPluggableConnID);
  97. if (NULL != p)
  98. {
  99. pXprtConn->eType = p->GetType();
  100. pXprtConn->nLogicalHandle = nPluggableConnID;
  101. ASSERT(IS_PLUGGABLE(*pXprtConn));
  102. }
  103. else
  104. {
  105. return TRANSPORT_NO_SUCH_CONNECTION;
  106. }
  107. }
  108. else
  109. {
  110. pXprtConn->eType = TRANSPORT_TYPE_WINSOCK;
  111. pXprtConn->nLogicalHandle = INVALID_SOCKET;
  112. }
  113. // we are connecting X224...
  114. ::OnProtocolControl(*pXprtConn, PLUGXPRT_CONNECTING);
  115. // Try to prepare a security context object if we're told to do so.
  116. if ( fSecure )
  117. {
  118. // If we're trying to connect securely but can't, fail
  119. if ( NULL == g_Transport->pSecurityInterface )
  120. {
  121. WARNING_OUT(("Placing secure call failed: no valid security interface"));
  122. return TRANSPORT_SECURITY_FAILED;
  123. }
  124. DBG_SAVE_FILE_LINE
  125. if (NULL != (pSC = new SecurityContext(g_Transport->pSecurityInterface,
  126. transport_address)))
  127. {
  128. if ( TPRTSEC_NOERROR != pSC->Initialize(NULL,0))
  129. {
  130. // If we can't init a security context, fail
  131. delete pSC;
  132. pSC = NULL;
  133. WARNING_OUT(("Placing secure call failed: could not initialize security context"));
  134. return TRANSPORT_SECURITY_FAILED;
  135. }
  136. }
  137. }
  138. /* Create and Initialize the Socket object */
  139. pSocket = newSocket(*pXprtConn, pSC);
  140. if( pSocket == NULL )
  141. return (TRANSPORT_MEMORY_FAILURE);
  142. pSocket->SecState = ( NULL == pSC ) ? SC_NONSECURE : SC_SECURE;
  143. if (IS_SOCKET(*pXprtConn))
  144. {
  145. u_short uPort = TCP_PORT_NUMBER;
  146. TCHAR szAddress[MAXIMUM_IP_ADDRESS_SIZE];
  147. lstrcpyn(szAddress, transport_address, MAXIMUM_IP_ADDRESS_SIZE);
  148. LPTSTR pszSeparator = (LPTSTR)_StrChr(szAddress, _T(':'));
  149. if (NULL != pszSeparator)
  150. {
  151. uPort = (u_short)DecimalStringToUINT(CharNext(pszSeparator));
  152. *pszSeparator = _T('\0');
  153. }
  154. /* Convert the ascii string into an Internet Address */
  155. if ((address = inet_addr(szAddress)) == INADDR_NONE)
  156. {
  157. WARNING_OUT (("ConnectRequest: %s is an invalid host addr", szAddress));
  158. rc = TRANSPORT_CONNECT_REQUEST_FAILED;
  159. goto Bail;
  160. }
  161. lstrcpyn (pSocket->Remote_Address, transport_address, MAXIMUM_IP_ADDRESS_SIZE);
  162. /*
  163. * Load the socket control structure with the parameters necessary.
  164. *
  165. * - Internet socket
  166. * - Let it assign any address to this socket
  167. * - Assign our port number (depending on secure/nonsecure call!)
  168. */
  169. sin.sin_family = AF_INET;
  170. sin.sin_addr.s_addr = address;
  171. sin.sin_port = htons (uPort);
  172. /* Attempt a connection to the remote site */
  173. TRACE_OUT (("ConnectRequest: Issuing connect: address = %s", transport_address));
  174. if (::connect(pSocket->XprtConn.nLogicalHandle, (const struct sockaddr *) &sin, sizeof(sin)) == 0)
  175. {
  176. TRACE_OUT (("ConnectRequest: State = SOCKET_CONNECTED..."));
  177. /* Add socket to connection list */
  178. // bugbug: we may fail to insert.
  179. g_pSocketList->SafeAppend(pSocket);
  180. ::SendX224ConnectRequest(pSocket->XprtConn);
  181. }
  182. else
  183. if (WSAGetLastError() == WSAEWOULDBLOCK)
  184. {
  185. /* If the error message is WSAEWOULDBLOCK, we must wait for the FD_CONNECT. */
  186. TRACE_OUT (("ConnectRequest: State = WAITING_FOR_CONNECTION..."));
  187. pSocket -> State = WAITING_FOR_CONNECTION;
  188. /* Add socket to connection list */
  189. // bugbug: we may fail to insert.
  190. g_pSocketList->SafeAppend(pSocket);
  191. // SendStatusMessage(pSocket -> Remote_Address, TSTATE_CONNECT_PENDING, IDS_NULL_STRING);
  192. }
  193. else
  194. {
  195. WARNING_OUT (("ConnectRequest: Connect Failed error = %d",WSAGetLastError()));
  196. /* The connect() call failed, close the socket and notify the owner */
  197. // SendStatusMessage (pSocket -> Remote_Address, TSTATE_NOT_READY, IDS_NULL_STRING);
  198. ::ShutdownAndClose(pSocket->XprtConn, FALSE, 2);
  199. rc = TRANSPORT_CONNECT_REQUEST_FAILED;
  200. goto Bail;
  201. }
  202. }
  203. else
  204. {
  205. ASSERT(IS_PLUGGABLE(*pXprtConn));
  206. g_pSocketList->SafeAppend(pSocket);
  207. if (IS_PLUGGABLE_X224(*pXprtConn))
  208. {
  209. ::SendX224ConnectRequest(pSocket->XprtConn);
  210. }
  211. else
  212. if (IS_PLUGGABLE_PSTN(*pXprtConn))
  213. {
  214. rc = p->TConnectRequest();
  215. ASSERT(TRANSPORT_NO_ERROR == rc);
  216. }
  217. }
  218. Bail:
  219. ASSERT(NULL != pSocket);
  220. if (TRANSPORT_NO_ERROR == rc)
  221. {
  222. *pXprtConn = pSocket->XprtConn;
  223. }
  224. else
  225. {
  226. ::freeSocket(pSocket, *pXprtConn);
  227. }
  228. return rc;
  229. }
  230. /*
  231. * BOOL ConnectResponse (TransportConnection XprtConn)
  232. *
  233. * Functional Description:
  234. * This function is called by the user in response to a
  235. * TRANSPORT_CONNECT_INDICATION callback from us. By making this call the
  236. * user is accepting the call. If the user does not want to accept the
  237. * call, he should call DisconnectRequest();
  238. */
  239. BOOL ConnectResponse (TransportConnection XprtConn)
  240. {
  241. PSocket pSocket;
  242. TRACE_OUT (("ConnectResponse(%d, %d)", XprtConn.eType, XprtConn.nLogicalHandle));
  243. /* If this is an invalid handle, return error */
  244. if(NULL != (pSocket = g_pSocketList->FindByTransportConnection(XprtConn)))
  245. {
  246. BOOL fRet;
  247. if (pSocket->State == SOCKET_CONNECTED)
  248. {
  249. /* We do not change this state in ANY other place BECAUSE it breaks the connect request*/
  250. pSocket->State = X224_CONNECTED;
  251. fRet = TRUE;
  252. }
  253. else
  254. {
  255. ERROR_OUT(("ConnectResponse: Illegal ConnectResponse packet"));
  256. fRet = FALSE;
  257. }
  258. pSocket->Release();
  259. return fRet;
  260. }
  261. return FALSE;
  262. }
  263. #ifdef TSTATUS_INDICATION
  264. /*
  265. * Void SendStatusMessage ( PChar RemoteAddress,
  266. * TransportState State,
  267. * UInt message_id)
  268. *
  269. * Functional Description:
  270. * This function is called to send a status indication to the user. The
  271. * specific text of the message is contained in a string resource.
  272. */
  273. Void SendStatusMessage( PChar RemoteAddress,
  274. TransportState state,
  275. UInt message_id)
  276. {
  277. TransportStatus transport_status;
  278. char sTransport[80] = "";
  279. char message[80] = "";
  280. if( message_id == IDS_NULL_STRING )
  281. message[0] = '\000';
  282. else
  283. LoadString(
  284. (HINSTANCE) g_hDllInst,
  285. (UINT) message_id,
  286. (LPSTR) message,
  287. (int) sizeof(message) );
  288. /*
  289. ** We issue a callback to the user to notify him of the message
  290. */
  291. transport_status.device_identifier = "";
  292. transport_status.remote_address = RemoteAddress;
  293. transport_status.message = message;
  294. transport_status.state = state;
  295. g_pMCSController->HandleTransportStatusIndication(&transport_status);
  296. }
  297. #endif
  298. /*
  299. * Void SendX224ConnectRequest(TransportConnection XprtConn)
  300. *
  301. * Functional Description:
  302. * This function is called upon receipt of the FD_CONNECT from Winsock.
  303. * It indicates that the physical connection is established, and sends
  304. * the X224 connection request packet.
  305. */
  306. void SendX224ConnectRequest(TransportConnection XprtConn)
  307. {
  308. PSocket pSocket;
  309. static X224_CR_FIXED cr_fixed =
  310. {
  311. { 3, 0, 0, UNK },
  312. UNK,
  313. { CONNECTION_REQUEST_PACKET, UNK, UNK, UNK, UNK, 0 } // common info
  314. };
  315. TRACE_OUT(("SendX224ConnectRequest"));
  316. CNPPDU cnp_pdu;
  317. ConnectRequestPDU_reliableSecurityProtocols_Element cnp_cr_rsp_element;
  318. LPBYTE pbToSendBuf = NULL;
  319. UINT cbToSendBuf = 0;
  320. LPBYTE encoded_pdu;
  321. UINT encoded_pdu_length;
  322. TransportError error;
  323. cnp_pdu.choice = connectRequest_chosen;
  324. cnp_pdu.u.connectRequest.bit_mask = 0;
  325. cnp_pdu.u.connectRequest.protocolIdentifier = t123AnnexBProtocolId;
  326. cnp_pdu.u.connectRequest.reconnectRequested = FALSE;
  327. // Sanity check field sizes... these need to conform to protocol
  328. ASSERT (sizeof(RFC_HEADER) == 4);
  329. ASSERT (sizeof(X224_DATA_PACKET) == 7);
  330. ASSERT (sizeof(X224_CONNECT_COMMON) == 6);
  331. ASSERT (sizeof(X224_TPDU_INFO) == 3);
  332. /* If this is an invalid handle, return */
  333. if (NULL == (pSocket = g_pSocketList->FindByTransportConnection(XprtConn)))
  334. return;
  335. if (IS_SOCKET(pSocket->XprtConn))
  336. {
  337. if (pSocket -> State != WAITING_FOR_CONNECTION)
  338. {
  339. ERROR_OUT (("SendX224ConnectRequest: Illegal Socket State"));
  340. goto MyExit;
  341. }
  342. }
  343. else
  344. {
  345. ASSERT(IS_PLUGGABLE(pSocket->XprtConn));
  346. if (X224_CONNECTED == pSocket->State)
  347. {
  348. // after query remote, we need to reset the state back to socket connected
  349. pSocket->State = SOCKET_CONNECTED;
  350. }
  351. if (SOCKET_CONNECTED != pSocket->State)
  352. {
  353. ERROR_OUT (("SendX224ConnectRequest: Illegal Socket State"));
  354. goto MyExit;
  355. }
  356. }
  357. // If there is a security context associated with this socket, we
  358. // are settting up for a secure call and will indicate that in the CNP
  359. // portion of the packet
  360. if (NULL != pSocket->pSC)
  361. {
  362. TRACE_OUT(("SendX224ConnectRequest: requesting secure connection"));
  363. cnp_pdu.u.connectRequest.bit_mask |= reliableSecurityProtocols_present;
  364. cnp_cr_rsp_element.next = NULL;
  365. cnp_cr_rsp_element.value.choice = gssApiX224_chosen;
  366. cnp_pdu.u.connectRequest.reliableSecurityProtocols = &cnp_cr_rsp_element;
  367. }
  368. else
  369. {
  370. TRACE_OUT(("SendX224ConnectRequest: requesting NON-secure connection"));
  371. }
  372. if (! g_CNPCoder->Encode((LPVOID) &cnp_pdu,
  373. CNPPDU_PDU,
  374. PACKED_ENCODING_RULES,
  375. &encoded_pdu,
  376. &encoded_pdu_length))
  377. {
  378. ERROR_OUT(("SendX224ConnectRequest: Can't encode cnp pdu"));
  379. goto MyExit;
  380. }
  381. pSocket -> State = SOCKET_CONNECTED;
  382. /* X224 header */
  383. cr_fixed.conn.msbSrc = (UChar) (XprtConn.nLogicalHandle >> 8);
  384. cr_fixed.conn.lsbSrc = (UChar) XprtConn.nLogicalHandle;
  385. cbToSendBuf = sizeof(X224_CR_FIXED)+sizeof(X224_TPDU_INFO)+sizeof(X224_VARIABLE_INFO)+encoded_pdu_length;
  386. cr_fixed.rfc.lsbPacketSize = (UChar)cbToSendBuf;
  387. cr_fixed.HeaderSize = (UChar)(sizeof(X224_CONNECT_COMMON)+sizeof(X224_TPDU_INFO)+sizeof(X224_VARIABLE_INFO)+encoded_pdu_length);
  388. ASSERT ( cbToSendBuf <= 128);
  389. DBG_SAVE_FILE_LINE
  390. pbToSendBuf = new BYTE[cbToSendBuf];
  391. if (NULL == pbToSendBuf)
  392. {
  393. ERROR_OUT(("SendX224ConnectRequest: failed to allocate memory"));
  394. goto MyExit;
  395. }
  396. {
  397. LPBYTE pbTemp = pbToSendBuf;
  398. memcpy(pbTemp, (LPBYTE) &cr_fixed, sizeof(cr_fixed));
  399. pbTemp += sizeof(cr_fixed);
  400. {
  401. X224_TPDU_INFO x224_tpdu_info = { TPDU_SIZE, 1, DEFAULT_TPDU_SIZE };
  402. memcpy(pbTemp, (LPBYTE) &x224_tpdu_info, sizeof(x224_tpdu_info));
  403. pbTemp += sizeof(x224_tpdu_info);
  404. }
  405. {
  406. X224_VARIABLE_INFO x224_var_info = { T_SELECTOR, (UChar)encoded_pdu_length };
  407. memcpy(pbTemp, (LPBYTE) &x224_var_info, sizeof(x224_var_info)); // bug: error handling
  408. pbTemp += sizeof(x224_var_info);
  409. memcpy(pbTemp, encoded_pdu, encoded_pdu_length);
  410. }
  411. }
  412. g_CNPCoder->FreeEncoded(encoded_pdu);
  413. /* Attempt to send data out the socket */
  414. error = FlushSendBuffer(pSocket, pbToSendBuf, cbToSendBuf);
  415. ASSERT (TRANSPORT_NO_ERROR == error);
  416. delete [] pbToSendBuf;
  417. MyExit:
  418. pSocket->Release();
  419. }
  420. /*
  421. * Void SendX224ConnectConfirm (PSocket pSocket, unsigned int remote)
  422. *
  423. * Functional Description:
  424. * This function is called upon receipt of the X224 connection request
  425. * packet. It indicates that the remote side wants to establish a
  426. * logical connection, and sends the X224 connection response packet.
  427. *
  428. * Return value:
  429. * TRUE, if everything went ok.
  430. * FALSE, otherwise (this implies a Disconnect will be issued for the socket).
  431. */
  432. // LONCHANC: "remote" is from the X.224 ConnectRequest
  433. BOOL SendX224ConnectConfirm (PSocket pSocket, unsigned int remote)
  434. {
  435. //PUChar ptr;
  436. LPBYTE pbToSendBuf = NULL;
  437. UINT cbToSendBuf = 0;
  438. LPBYTE encoded_pdu = NULL;
  439. UINT encoded_pdu_length = 0;
  440. CNPPDU cnp_pdu;
  441. BOOL fAcceptSecure = FALSE;
  442. BOOL fRequireSecure = FALSE;
  443. TRACE_OUT(("SendX224ConnectConfirm"));
  444. {
  445. RegEntry re(POLICIES_KEY, HKEY_CURRENT_USER);
  446. switch (re.GetNumber(REGVAL_POL_SECURITY, DEFAULT_POL_SECURITY))
  447. {
  448. case DISABLED_POL_SECURITY:
  449. break;
  450. case REQUIRED_POL_SECURITY:
  451. fAcceptSecure = TRUE;
  452. fRequireSecure = TRUE;
  453. break;
  454. default:
  455. fAcceptSecure = TRUE;
  456. break;
  457. }
  458. }
  459. static X224_CC_FIXED cc_fixed =
  460. {
  461. { 3, 0, 0, UNK }, // RFC1006 header
  462. UNK,
  463. { CONNECTION_CONFIRM_PACKET, UNK, UNK, UNK, UNK, 0 } // common info
  464. };
  465. // Sanity check field sizes... these need to conform to protocol
  466. ASSERT (sizeof(RFC_HEADER) == 4);
  467. ASSERT (sizeof(X224_DATA_PACKET) == 7);
  468. ASSERT (sizeof(X224_CONNECT_COMMON) == 6);
  469. ASSERT (sizeof(X224_TPDU_INFO) == 3);
  470. /* X224 header */
  471. cc_fixed.conn.msbDest = (UChar) (remote >> 8);
  472. cc_fixed.conn.lsbDest = (UChar) remote;
  473. cc_fixed.conn.msbSrc = (UChar) (pSocket->XprtConn.nLogicalHandle >> 8);
  474. cc_fixed.conn.lsbSrc = (UChar) pSocket->XprtConn.nLogicalHandle;
  475. cnp_pdu.choice = connectConfirm_chosen;
  476. cnp_pdu.u.connectConfirm.bit_mask = 0;
  477. cnp_pdu.u.connectConfirm.protocolIdentifier = t123AnnexBProtocolId;
  478. if ( pSocket->fExtendedX224 )
  479. {
  480. TRACE_OUT(("SendX224ConnectConfirm reply using extended X224"));
  481. if ( pSocket->fIncomingSecure )
  482. {
  483. TRACE_OUT(("SendX224ConnectConfirm: reply to secure call request"));
  484. // Security not even initialized?
  485. if ( NULL == g_Transport->pSecurityInterface )
  486. {
  487. WARNING_OUT(("Can't accept secure call: no sec interface"));
  488. }
  489. // Registry indicates no secure calls? If we're in the service
  490. // then security is always 'on'.
  491. else if ( !g_Transport->pSecurityInterface->IsInServiceContext() &&
  492. !fAcceptSecure)
  493. {
  494. WARNING_OUT(("Can't accept secure call: security disabled"));
  495. }
  496. else // OK to take secure call
  497. {
  498. TRACE_OUT(("Creating security context for incoming call on socket (%d, %d).", pSocket->XprtConn.eType, pSocket->XprtConn.nLogicalHandle ));
  499. if ( NULL != (pSocket->pSC =
  500. new SecurityContext(g_Transport->pSecurityInterface, "")))
  501. {
  502. // Indicate we're ready for a secure call in the CC packet
  503. cnp_pdu.u.connectConfirm.bit_mask |=
  504. ConnectConfirmPDU_reliableSecurityProtocol_present;
  505. cnp_pdu.u.connectConfirm.reliableSecurityProtocol.choice =
  506. gssApiX224_chosen;
  507. pSocket->SecState = SC_SECURE;
  508. }
  509. else
  510. {
  511. ERROR_OUT(("Error creating sec context on received call"));
  512. // We will report no-support for security in our CC
  513. pSocket->SecState = SC_NONSECURE;
  514. }
  515. }
  516. }
  517. else if ( // Incoming call is not secure, but not downlevel
  518. // Running as a service?
  519. g_Transport->bInServiceContext ||
  520. fRequireSecure)
  521. {
  522. WARNING_OUT(("Can't accept non-secure call in RDS, or if security required"));
  523. return FALSE;
  524. }
  525. else
  526. {
  527. pSocket->SecState = SC_NONSECURE;
  528. }
  529. if (! g_CNPCoder->Encode((LPVOID) &cnp_pdu,
  530. CNPPDU_PDU,
  531. PACKED_ENCODING_RULES,
  532. &encoded_pdu,
  533. &encoded_pdu_length))
  534. {
  535. ERROR_OUT(("SendX224ConnectRequest: Can't encode cnp pdu"));
  536. return FALSE;
  537. }
  538. cbToSendBuf = sizeof(X224_CC_FIXED)+sizeof(X224_VARIABLE_INFO)+encoded_pdu_length;
  539. cc_fixed.rfc.lsbPacketSize = (UChar)cbToSendBuf;
  540. cc_fixed.HeaderSize = (UChar)(sizeof(X224_CONNECT_COMMON) + sizeof(X224_VARIABLE_INFO) + encoded_pdu_length);
  541. ASSERT( cbToSendBuf <= 128 );
  542. pbToSendBuf = new BYTE[cbToSendBuf];
  543. if (NULL == pbToSendBuf)
  544. {
  545. ERROR_OUT(("SendX224ConnectConfirm: failed to allocate memory"));
  546. return FALSE;
  547. }
  548. PBYTE pbTemp = pbToSendBuf;
  549. memcpy(pbTemp, (LPBYTE) &cc_fixed, sizeof(cc_fixed));
  550. pbTemp += sizeof(cc_fixed);
  551. X224_VARIABLE_INFO x224_var_info = { T_SELECTOR_2 /*0xc2*/, (UChar)encoded_pdu_length };
  552. memcpy(pbTemp, (LPBYTE) &x224_var_info, sizeof(x224_var_info));
  553. pbTemp += sizeof(x224_var_info);
  554. memcpy(pbTemp, encoded_pdu, encoded_pdu_length);
  555. g_CNPCoder->FreeEncoded(encoded_pdu);
  556. }
  557. else // Incoming call is downlevel
  558. {
  559. if ( g_Transport->bInServiceContext || fRequireSecure)
  560. {
  561. WARNING_OUT(("Can't accept downlevel call in RDS or if security required"));
  562. return FALSE;
  563. }
  564. pSocket->SecState = SC_NONSECURE;
  565. // Downlevel: send packet w/out TSELECTOR variable portion
  566. cc_fixed.rfc.lsbPacketSize = sizeof(X224_CC_FIXED);
  567. cc_fixed.HeaderSize = sizeof(X224_CONNECT_COMMON);
  568. cbToSendBuf = sizeof(X224_CC_FIXED);
  569. pbToSendBuf = new BYTE[cbToSendBuf];
  570. memcpy(pbToSendBuf, (LPBYTE) &cc_fixed, sizeof(cc_fixed));
  571. }
  572. /* Attempt to send data out the socket */
  573. #ifdef DEBUG
  574. TransportError error =
  575. #endif // DEBUG
  576. FlushSendBuffer(pSocket, pbToSendBuf, cbToSendBuf);
  577. #ifdef DEBUG
  578. ASSERT (TRANSPORT_NO_ERROR == error);
  579. #endif // DEBUG
  580. delete [] pbToSendBuf;
  581. return TRUE;
  582. }
  583. BOOL SendX224DisconnectRequest(PSocket pSocket, unsigned int remote, USHORT usReason)
  584. {
  585. LPBYTE pbToSendBuf = NULL;
  586. UINT cbToSendBuf = 0;
  587. RegEntry re(CONFERENCING_KEY, HKEY_CURRENT_USER);
  588. CNPPDU cnp_pdu;
  589. LPBYTE encoded_pdu = NULL;
  590. UINT encoded_pdu_length = 0;
  591. TRACE_OUT(("SendX224DisconnectRequest"));
  592. static X224_DR_FIXED dr_fixed =
  593. {
  594. { 3, 0, 0, UNK }, // RFC1006 header
  595. UNK,
  596. { DISCONNECT_REQUEST_PACKET, UNK, UNK, UNK, UNK, 0 },
  597. };
  598. ASSERT (pSocket->fExtendedX224);
  599. ASSERT (sizeof(RFC_HEADER) == 4);
  600. ASSERT (sizeof(X224_DATA_PACKET) == 7);
  601. ::OnProtocolControl(pSocket->XprtConn, PLUGXPRT_DISCONNECTING);
  602. dr_fixed.disconn.msbDest = (UChar) (remote >> 8);
  603. dr_fixed.disconn.lsbDest = (UChar) remote;
  604. dr_fixed.disconn.msbSrc = (UChar) (pSocket->XprtConn.nLogicalHandle >> 8);
  605. dr_fixed.disconn.lsbSrc = (UChar) pSocket->XprtConn.nLogicalHandle;
  606. cnp_pdu.choice = disconnectRequest_chosen;
  607. cnp_pdu.u.disconnectRequest.bit_mask = 0;
  608. cnp_pdu.u.disconnectRequest.disconnectReason.choice = usReason;
  609. if (! g_CNPCoder->Encode((LPVOID) &cnp_pdu,
  610. CNPPDU_PDU,
  611. PACKED_ENCODING_RULES,
  612. &encoded_pdu,
  613. &encoded_pdu_length))
  614. {
  615. ERROR_OUT(("SendX224DisconnectRequest: Can't encode cnp pdu"));
  616. return FALSE;
  617. }
  618. cbToSendBuf = sizeof(X224_DR_FIXED) + sizeof(X224_VARIABLE_INFO) + encoded_pdu_length;
  619. dr_fixed.rfc.lsbPacketSize = (UChar)cbToSendBuf;
  620. dr_fixed.HeaderSize = (UChar)(sizeof(X224_DISCONN) + sizeof(X224_VARIABLE_INFO) + encoded_pdu_length);
  621. ASSERT( cbToSendBuf <= 128 );
  622. pbToSendBuf = new BYTE[cbToSendBuf];
  623. if (NULL == pbToSendBuf)
  624. {
  625. ERROR_OUT(("SendX224DisconnectRequest: failed to allocate memory"));
  626. return FALSE;
  627. }
  628. LPBYTE pbTemp = pbToSendBuf;
  629. memcpy(pbTemp, (LPBYTE) &dr_fixed, sizeof(dr_fixed));
  630. pbTemp += sizeof(dr_fixed);
  631. X224_VARIABLE_INFO x224_var_info = { 0xe0, (UChar)encoded_pdu_length };
  632. memcpy(pbTemp, (LPBYTE) &x224_var_info, sizeof(x224_var_info));
  633. pbTemp += sizeof(x224_var_info);
  634. memcpy(pbTemp, encoded_pdu, encoded_pdu_length);
  635. g_CNPCoder->FreeEncoded(encoded_pdu);
  636. /* Attempt to send data out the socket */
  637. #ifdef DEBUG
  638. TransportError error =
  639. #endif // DEBUG
  640. FlushSendBuffer(pSocket, pbToSendBuf, cbToSendBuf);
  641. #ifdef DEBUG
  642. ASSERT (TRANSPORT_NO_ERROR == error);
  643. #endif // DEBUG
  644. return TRUE;
  645. }
  646. /*
  647. * void ContinueAuthentication (PSocket pSocket)
  648. *
  649. * Functional Description:
  650. */
  651. void ContinueAuthentication (PSocket pSocket)
  652. {
  653. ULong packet_size;
  654. PUChar Buffer;
  655. PSecurityContext pSC = pSocket->pSC;
  656. if (NULL != pSC) {
  657. TRACE_OUT(("ContinueAuthentication: sending data packet"));
  658. ASSERT(NULL != pSC->GetTokenBuf());
  659. ASSERT(0 != pSC->GetTokenSiz());
  660. /* We send an X224 data */
  661. packet_size = sizeof(X224_DATA_PACKET) + pSC->GetTokenSiz();
  662. DBG_SAVE_FILE_LINE
  663. Buffer = new UChar[packet_size];
  664. if (NULL != Buffer)
  665. {
  666. memcpy(Buffer + sizeof(X224_DATA_PACKET),
  667. pSC->GetTokenBuf(),
  668. pSC->GetTokenSiz());
  669. /* X224 header */
  670. memcpy (Buffer, g_X224Header, sizeof(X224_DATA_PACKET));
  671. AddRFCSize (Buffer, packet_size);
  672. /* Attempt to send data out the socket */
  673. #ifdef DEBUG
  674. TransportError error = FlushSendBuffer(pSocket, (LPBYTE) Buffer, packet_size);
  675. ASSERT (TRANSPORT_NO_ERROR == error);
  676. #else // DEBUG
  677. FlushSendBuffer(pSocket, (LPBYTE) Buffer, packet_size);
  678. #endif // DEBUG
  679. delete [] Buffer;
  680. }
  681. else {
  682. // bugbug: what do we need to do in case of a mem alloc failure?
  683. WARNING_OUT (("ContinueAuthentication: memory allocation failure."));
  684. }
  685. }
  686. else {
  687. ERROR_OUT(("ContinueAuthentication called w/ bad socket"));
  688. }
  689. }
  690. /*
  691. * The following function processes the variable part of incoming X.224
  692. * CONNECT_REQUEST and CONNECT_CONFIRM PDUs.
  693. * For now, it can only process Max PDU size and security T_SELECTOR requests.
  694. */
  695. BOOL ProcessX224ConnectPDU (PSocket pSocket, PUChar CP_ptr, UINT CP_length, ULONG *pNotify)
  696. {
  697. UChar length;
  698. BOOL bSecurityInfoFound = FALSE;
  699. PSecurityContext pSC = pSocket->pSC;
  700. /* This structure must be accessed using byte-alignment */
  701. #pragma pack(1)
  702. X224_VARIABLE_INFO *pX224VarInfo;
  703. /* return to normal alignment */
  704. #pragma pack()
  705. while (CP_length > 0) {
  706. pX224VarInfo = (X224_VARIABLE_INFO *) CP_ptr;
  707. /*
  708. * Check the packet to see if it contains a valid TPDU_SIZE part. If it
  709. * does, we need to reset the max packet size for this socket.
  710. */
  711. if (TPDU_SIZE == pX224VarInfo->InfoType) {
  712. /* This structure must be accessed using byte-alignment */
  713. #pragma pack(1)
  714. X224_TPDU_INFO *pX224TpduSize;
  715. /* return to normal alignment */
  716. #pragma pack()
  717. pX224TpduSize = (X224_TPDU_INFO *) CP_ptr;
  718. ASSERT (pX224TpduSize->InfoSize == 1);
  719. if (pX224TpduSize->Info != DEFAULT_TPDU_SIZE) {
  720. // We do not accept too small PDU sizes
  721. if ((pX224TpduSize->Info < LOWEST_TPDU_SIZE) && (pX224TpduSize->Info < HIGHEST_TPDU_SIZE))
  722. {
  723. if (NULL != pNotify)
  724. *pNotify = TPRT_NOTIFY_INCOMPATIBLE_T120_TPDU;
  725. return FALSE;
  726. }
  727. pSocket->Max_Packet_Length = (1 << pX224TpduSize->Info);
  728. }
  729. }
  730. /*
  731. * Check the packet to see if it contains a valid
  732. * TSELECTOR variable portion. If so, make sure it's security related
  733. * and include one in the reply
  734. */
  735. else if (T_SELECTOR == pX224VarInfo->InfoType || T_SELECTOR_2 == pX224VarInfo->InfoType)
  736. {
  737. // Try to decode
  738. LPVOID pdecoding_buf = NULL;
  739. UINT decoding_len = 0;
  740. LPBYTE pbEncoded_data = CP_ptr + sizeof(X224_VARIABLE_INFO);
  741. if ( g_CNPCoder->Decode (pbEncoded_data,
  742. pX224VarInfo->InfoSize,
  743. CNPPDU_PDU, PACKED_ENCODING_RULES,
  744. (LPVOID *) &pdecoding_buf, &decoding_len))
  745. {
  746. bSecurityInfoFound = TRUE;
  747. /* This structure must be accessed using byte-alignment */
  748. #pragma pack(1)
  749. CNPPDU *pCnp_pdu;
  750. /* return to normal alignment */
  751. #pragma pack()
  752. pCnp_pdu = (CNPPDU *) pdecoding_buf;
  753. if (pSocket->Read_State == CONNECTION_REQUEST) {
  754. TRACE_OUT(("CR packet using TSELECTOR extension"));
  755. pSocket->fExtendedX224 = TRUE;
  756. if (pCnp_pdu->u.connectRequest.bit_mask & reliableSecurityProtocols_present)
  757. {
  758. PConnectRequestPDU_reliableSecurityProtocols pRSP = pCnp_pdu->u.connectRequest.reliableSecurityProtocols;
  759. if (gssApiX224_chosen == pRSP->value.choice)
  760. {
  761. pSocket->fIncomingSecure = TRUE;
  762. }
  763. }
  764. }
  765. else {
  766. ASSERT (pSocket->Read_State == CONNECTION_CONFIRM);
  767. if ((NULL != pSC) && (pSC->ContinueNeeded())) {
  768. ConnectConfirmPDU *pCnpCc = &pCnp_pdu->u.connectConfirm;
  769. if ((pCnpCc->bit_mask & ConnectConfirmPDU_reliableSecurityProtocol_present )
  770. && gssApiX224_chosen == pCnpCc->reliableSecurityProtocol.choice)
  771. {
  772. // Everything is OK, we got an extended X224 response
  773. // to our secure CR.
  774. ContinueAuthentication(pSocket);
  775. }
  776. else {
  777. WARNING_OUT(("No-support response to secure call attempt"));
  778. if (NULL != pNotify)
  779. *pNotify = TPRT_NOTIFY_REMOTE_NO_SECURITY;
  780. return FALSE;
  781. }
  782. }
  783. }
  784. }
  785. g_CNPCoder->FreeDecoded(CNPPDU_PDU, pdecoding_buf);
  786. }
  787. else {
  788. ERROR_OUT (("ProcessX224ConnectPDU: Received X.224 Connect packet with unrecognizable parts."));
  789. }
  790. // Adjust the pointer and length and the X.224 CR packet.
  791. length = pX224VarInfo->InfoSize + sizeof(X224_VARIABLE_INFO);
  792. CP_ptr += length;
  793. CP_length -= length;
  794. }
  795. if (bSecurityInfoFound == FALSE) {
  796. if ((pSocket->Read_State == CONNECTION_CONFIRM) && (pSC != NULL) && pSC->ContinueNeeded()) {
  797. WARNING_OUT(("Downlevel response to secure call attempt"));
  798. if (NULL != pNotify)
  799. *pNotify = TPRT_NOTIFY_REMOTE_DOWNLEVEL_SECURITY;
  800. return FALSE;
  801. }
  802. }
  803. return TRUE;
  804. }
  805. void ProcessX224DisconnectPDU(PSocket pSocket, PUChar CP_ptr, UINT CP_length, ULONG *pNotify)
  806. {
  807. UChar length;
  808. BOOL bSecurityInfoFound = FALSE;
  809. PSecurityContext pSC = pSocket->pSC;
  810. /* This structure must be accessed using byte-alignment */
  811. #pragma pack(1)
  812. X224_VARIABLE_INFO *pX224VarInfo;
  813. /* return to normal alignment */
  814. #pragma pack()
  815. while (CP_length > 0) {
  816. pX224VarInfo = (X224_VARIABLE_INFO *) CP_ptr;
  817. if ( 0xe0 == pX224VarInfo->InfoType) {
  818. LPVOID pdecoding_buf = NULL;
  819. UINT decoding_len = 0;
  820. LPBYTE pbEncoded_data = CP_ptr + sizeof(X224_VARIABLE_INFO);
  821. if ( g_CNPCoder->Decode (pbEncoded_data,
  822. pX224VarInfo->InfoSize,
  823. CNPPDU_PDU, PACKED_ENCODING_RULES,
  824. (LPVOID *) &pdecoding_buf, &decoding_len))
  825. {
  826. #pragma pack(1)
  827. CNPPDU *pCnp_pdu;
  828. /* return to normal alignment */
  829. #pragma pack()
  830. pCnp_pdu = (CNPPDU *) pdecoding_buf;
  831. if (disconnectRequest_chosen == pCnp_pdu->choice)
  832. {
  833. switch (pCnp_pdu->u.disconnectRequest.disconnectReason.choice)
  834. {
  835. case securityDenied_chosen:
  836. *pNotify = TPRT_NOTIFY_REMOTE_REQUIRE_SECURITY;
  837. break;
  838. default:
  839. *pNotify = TPRT_NOTIFY_OTHER_REASON;
  840. break;
  841. }
  842. }
  843. }
  844. g_CNPCoder->FreeDecoded(decoding_len, pdecoding_buf);
  845. }
  846. length = pX224VarInfo->InfoSize + sizeof(X224_VARIABLE_INFO);
  847. CP_ptr += length;
  848. CP_length -= length;
  849. }
  850. }
  851. /*
  852. * void DisconnectRequest (TransportConnection XprtConn)
  853. *
  854. * Functional Description:
  855. * This function closes the socket and deletes its connection node.
  856. */
  857. void DisconnectRequest (TransportConnection XprtConn,
  858. ULONG ulNotify)
  859. {
  860. PSocket pSocket;
  861. TRACE_OUT(("DisconnectRequest"));
  862. /* If the transport connection handle is not registered, return error */
  863. if (NULL != (pSocket = g_pSocketList->FindByTransportConnection(XprtConn, TRUE)))
  864. {
  865. // LONCHANC: cannot do Remove in the above line because PurgeRequest() uses it again.
  866. ::PurgeRequest(XprtConn);
  867. // SendStatusMessage (pSocket -> Remote_Address, TSTATE_NOT_CONNECTED, IDS_NULL_STRING);
  868. if (IS_PLUGGABLE_PSTN(XprtConn))
  869. {
  870. CPluggableConnection *p = ::GetPluggableConnection(XprtConn.nLogicalHandle);
  871. if (NULL != p)
  872. {
  873. p->TDisconnectRequest();
  874. }
  875. }
  876. /* Free the structures and close the socket */
  877. TransportConnection XprtConn2 = XprtConn;
  878. if (IS_SOCKET(XprtConn2))
  879. {
  880. XprtConn2.nLogicalHandle = INVALID_SOCKET;
  881. }
  882. ::freeSocket(pSocket, XprtConn2);
  883. // Free up QoS resources if this disconnect was the
  884. // last connected socket.
  885. MaybeReleaseQoSResources();
  886. // Notify the user
  887. if (TPRT_NOTIFY_NONE != ulNotify)
  888. {
  889. TRACE_OUT (("TCP Callback: g_Transport->DisconnectIndication (%d, %d)", XprtConn.eType, XprtConn.nLogicalHandle));
  890. /* We issue a callback to the user to notify him of the message */
  891. g_Transport->DisconnectIndication(XprtConn, ulNotify);
  892. }
  893. }
  894. else
  895. {
  896. WARNING_OUT(("DisconnectRequest: logical handle (%d, %d) not found",
  897. XprtConn.eType, XprtConn.nLogicalHandle));
  898. }
  899. ::OnProtocolControl(XprtConn, PLUGXPRT_DISCONNECTED);
  900. }
  901. typedef enum {
  902. RECVRET_CONTINUE = 0,
  903. RECVRET_NON_FATAL_ERROR,
  904. RECVRET_DISCONNECT,
  905. RECVRET_NO_PLUGGABLE_CONNECTION,
  906. } RecvReturn;
  907. /* RecvReturn Call_recv (PSocket pSocket)
  908. *
  909. * Functional Description:
  910. * This function calls recv once and checks for errors coming from the
  911. * recv call. It knows about the socket's state from the "pSocket" argument
  912. * and uses this info to create the arguments for the recv call.
  913. *
  914. * Return value:
  915. * Continue, if everything went ok and we have new data
  916. * Non_Fatal_Error, if no real error has happenned, but we did not recv all data we asked for
  917. * Disconnect, if a real error has occurred, or the other side has disconnected.
  918. */
  919. RecvReturn Call_recv (PSocket pSocket)
  920. {
  921. PUChar buffer;
  922. int length;
  923. int bytes_received;
  924. BOOL bAllocationOK;
  925. RecvReturn rrCode = RECVRET_NON_FATAL_ERROR;
  926. PLUGXPRT_RESULT plug_rc = PLUGXPRT_RESULT_SUCCESSFUL;
  927. TRACE_OUT(("Call_recv"));
  928. if (READ_HEADER != pSocket->Read_State)
  929. {
  930. ASSERT ((pSocket->X224_Length) > 0 && (pSocket->X224_Length <= 8192));
  931. // Compute how much data we have to read from this X.224 pkt.
  932. length = pSocket->X224_Length - sizeof(X224_DATA_PACKET);
  933. // Space allocation
  934. if (! pSocket->bSpaceAllocated)
  935. {
  936. // We need to allocate the space for the recv call.
  937. if (NULL == pSocket->Data_Indication_Buffer)
  938. {
  939. DBG_SAVE_FILE_LINE
  940. pSocket->Data_Memory = AllocateMemory (
  941. NULL, pSocket->X224_Length,
  942. ((READ_DATA == pSocket->Read_State) ?
  943. RECV_PRIORITY : HIGHEST_PRIORITY));
  944. // Leave space for the X.224 header in the newly allocated data buffer
  945. pSocket->Data_Indication_Length = sizeof (X224_DATA_PACKET);
  946. bAllocationOK = (pSocket->Data_Memory != NULL);
  947. }
  948. else
  949. {
  950. // This is an MCS PDU broken up in many X.224 packets.
  951. ASSERT (READ_DATA == pSocket->Read_State);
  952. bAllocationOK = ReAllocateMemory (&(pSocket->Data_Memory), length);
  953. }
  954. // Check whether the allocations were successful.
  955. if (bAllocationOK)
  956. {
  957. pSocket->bSpaceAllocated = TRUE;
  958. pSocket->Data_Indication_Buffer = pSocket->Data_Memory->GetPointer();
  959. /*
  960. * If this is an X.224 CONNECT_REQUEST or CONNECT_CONFIRM packet,
  961. * we need to copy the first 7 bytes into the buffer for the whole
  962. * packet.
  963. */
  964. if (READ_DATA != pSocket->Read_State)
  965. {
  966. memcpy ((void *) pSocket->Data_Indication_Buffer,
  967. (void *) &(pSocket->X224_Header),
  968. sizeof(X224_DATA_PACKET));
  969. }
  970. }
  971. else
  972. {
  973. /*
  974. * We will retry the operation later.
  975. */
  976. WARNING_OUT (("Call_recv: Buffer allocation failed."));
  977. g_pMCSController->HandleTransportWaitUpdateIndication(TRUE);
  978. goto ExitLabel;
  979. }
  980. }
  981. buffer = pSocket->Data_Indication_Buffer + pSocket->Data_Indication_Length;
  982. }
  983. else
  984. {
  985. buffer = (PUChar) &(pSocket->X224_Header);
  986. length = sizeof(X224_DATA_PACKET);
  987. }
  988. // Adjust "buffer" and "length" for data already read from the current X.224 pkt.
  989. buffer += pSocket->Current_Length;
  990. length -= pSocket->Current_Length;
  991. ASSERT (length > 0);
  992. if (IS_SOCKET(pSocket->XprtConn))
  993. {
  994. // Issue the recv call.
  995. bytes_received = recv (pSocket->XprtConn.nLogicalHandle, (char *) buffer, length, 0);
  996. }
  997. else
  998. {
  999. bytes_received = ::X224Recv(pSocket, buffer, length, &plug_rc);
  1000. }
  1001. if (bytes_received == length)
  1002. {
  1003. TRACE_OUT (("Call_recv: Received %d bytes on socket (%d, %d).", bytes_received,
  1004. pSocket->XprtConn.eType, pSocket->XprtConn.nLogicalHandle));
  1005. // We have received the whole X.224 packet.
  1006. if (READ_HEADER != pSocket->Read_State)
  1007. {
  1008. pSocket->Data_Indication_Length += pSocket->X224_Length - sizeof(X224_DATA_PACKET);
  1009. }
  1010. // Reset the current length variable for the next Call_recv().
  1011. pSocket->Current_Length = 0;
  1012. rrCode = RECVRET_CONTINUE;
  1013. }
  1014. // Handle errors
  1015. else
  1016. if (bytes_received == SOCKET_ERROR)
  1017. {
  1018. if (IS_SOCKET(pSocket->XprtConn))
  1019. {
  1020. if(WSAGetLastError() == WSAEWOULDBLOCK)
  1021. {
  1022. TRACE_OUT(("Call_recv: recv blocked on socket (%d, %d).",
  1023. pSocket->XprtConn.eType, pSocket->XprtConn.nLogicalHandle));
  1024. }
  1025. else
  1026. {
  1027. /* If the error is not WOULD BLOCK, we have a real error. */
  1028. WARNING_OUT (("Call_recv: Error %d on recv. Socket: (%d, %d). Disconnecting...",
  1029. WSAGetLastError(), pSocket->XprtConn.eType, pSocket->XprtConn.nLogicalHandle));
  1030. rrCode = RECVRET_DISCONNECT;
  1031. }
  1032. }
  1033. else
  1034. {
  1035. if (PLUGXPRT_RESULT_SUCCESSFUL == plug_rc)
  1036. {
  1037. // do nothing, treat it as WSAEWOULDBLOCK
  1038. }
  1039. else
  1040. {
  1041. /* If the error is not WOULD BLOCK, we have a real error. */
  1042. WARNING_OUT (("Call_recv: Error %d on recv. Socket: (%d, %d). Disconnecting...",
  1043. WSAGetLastError(), pSocket->XprtConn.eType, pSocket->XprtConn.nLogicalHandle));
  1044. rrCode = RECVRET_DISCONNECT;
  1045. }
  1046. }
  1047. }
  1048. else
  1049. if (bytes_received > 0)
  1050. {
  1051. TRACE_OUT(("Call_recv: Received %d bytes out of %d bytes requested on socket (%d, %d).",
  1052. bytes_received, length, pSocket->XprtConn.eType, pSocket->XprtConn.nLogicalHandle));
  1053. // We received only part of what we wanted. We retry later.
  1054. pSocket->Current_Length += bytes_received;
  1055. }
  1056. else
  1057. {
  1058. WARNING_OUT(("Call_recv: Socket (%d, %d) has been gracefully closed.",
  1059. pSocket->XprtConn.eType, pSocket->XprtConn.nLogicalHandle));
  1060. rrCode = RECVRET_DISCONNECT;
  1061. }
  1062. ExitLabel:
  1063. return rrCode;
  1064. }
  1065. int X224Recv(PSocket pSocket, LPBYTE buffer, int length, PLUGXPRT_RESULT *plug_rc)
  1066. {
  1067. TRACE_OUT(("X224Recv"));
  1068. if (IS_PLUGGABLE_X224(pSocket->XprtConn))
  1069. {
  1070. return ::SubmitPluggableRead(pSocket, buffer, length, plug_rc);
  1071. }
  1072. if (IS_PLUGGABLE_PSTN(pSocket->XprtConn))
  1073. {
  1074. return Q922Recv(pSocket, buffer, length, plug_rc);
  1075. }
  1076. ERROR_OUT(("X224Recv: invalid plugable type (%d, %d)",
  1077. pSocket->XprtConn.eType, pSocket->XprtConn.nLogicalHandle));
  1078. return SOCKET_ERROR;
  1079. }
  1080. int Q922Recv(PSocket pSocket, LPBYTE buffer, int length, PLUGXPRT_RESULT *plug_rc)
  1081. {
  1082. ERROR_OUT(("Q922Recv: NYI (%d, %d)",
  1083. pSocket->XprtConn.eType, pSocket->XprtConn.nLogicalHandle));
  1084. return SOCKET_ERROR;
  1085. }
  1086. typedef enum {
  1087. FreeX224AndExit,
  1088. ErrorExit,
  1089. ImmediateExit
  1090. } ExitWay;
  1091. /*
  1092. * void ReadRequest ( TransportConnection )
  1093. *
  1094. * Functional Description:
  1095. * This function will attempt to read and process a full X.224 packet.
  1096. * However, it may only be able to read part of a packet or fail to
  1097. * process it at this time. In this case, it must keep enough state
  1098. * info for the next entrance into this function, to be able to handle
  1099. * the partly-received or unprocessed X.224 packet.
  1100. */
  1101. void ReadRequest (TransportConnection XprtConn)
  1102. {
  1103. PSocket pSocket;
  1104. ExitWay ew = ImmediateExit;
  1105. RecvReturn rrCode;
  1106. ULONG ulNotify = TPRT_NOTIFY_OTHER_REASON;
  1107. TRACE_OUT(("ReadRequest"));
  1108. if (IS_PLUGGABLE_PSTN(XprtConn))
  1109. {
  1110. ERROR_OUT(("ReadRequest: PSTN should not be here"));
  1111. return;
  1112. }
  1113. /* If the transport connection handle is not registered, return */
  1114. if (NULL != (pSocket = g_pSocketList->FindByTransportConnection(XprtConn)))
  1115. {
  1116. if (pSocket->State != WAITING_FOR_CONNECTION)
  1117. {
  1118. PSecurityContext pSC = pSocket->pSC;
  1119. /*
  1120. * If we haven't read the header of the incoming packet yet,
  1121. * we need to read it into the header space
  1122. */
  1123. if (READ_HEADER == pSocket->Read_State)
  1124. {
  1125. rrCode = Call_recv (pSocket);
  1126. if (RECVRET_CONTINUE == rrCode)
  1127. {
  1128. // We need to allocate the space for the rest of the X.224 packet.
  1129. pSocket->bSpaceAllocated = FALSE;
  1130. // Find the length of the X.224 packet.
  1131. pSocket->X224_Length = (pSocket->X224_Header.rfc.msbPacketSize << 8) +
  1132. pSocket->X224_Header.rfc.lsbPacketSize;
  1133. /*
  1134. * We have the whole X.224 header. Compute the next state,
  1135. * based on the packet type.
  1136. */
  1137. switch (pSocket->X224_Header.PacketType)
  1138. {
  1139. case DATA_PACKET:
  1140. pSocket->Read_State = READ_DATA;
  1141. break;
  1142. case CONNECTION_CONFIRM_PACKET:
  1143. if (pSocket->State != X224_CONNECTED)
  1144. {
  1145. pSocket->Read_State = CONNECTION_CONFIRM;
  1146. }
  1147. else
  1148. {
  1149. ERROR_OUT (("ReadRequest: Received X.224 CONNECTION_CONFIRM packet while already connected!! Socket: (%d, %d).",
  1150. XprtConn.eType, XprtConn.nLogicalHandle));
  1151. ew = ErrorExit;
  1152. }
  1153. break;
  1154. case CONNECTION_REQUEST_PACKET:
  1155. // we just received a X224 Connect request
  1156. pSocket->Read_State = CONNECTION_REQUEST;
  1157. ::OnProtocolControl(XprtConn, PLUGXPRT_CONNECTING);
  1158. break;
  1159. case DISCONNECT_REQUEST_PACKET:
  1160. // we just received a X224 Disconnect request
  1161. pSocket->Read_State = DISCONNECT_REQUEST;
  1162. ::OnProtocolControl(XprtConn, PLUGXPRT_DISCONNECTING);
  1163. break;
  1164. default:
  1165. // We have lost sync with the remote side.
  1166. ERROR_OUT (("ReadRequest: Bad X.224 packet on socket (%d, %d). Disconnecting...", XprtConn.eType, XprtConn.nLogicalHandle));
  1167. ew = ErrorExit;
  1168. break;
  1169. }
  1170. }
  1171. else
  1172. if (RECVRET_DISCONNECT == rrCode)
  1173. {
  1174. ew = ErrorExit;
  1175. }
  1176. }
  1177. if ((READ_DATA <= pSocket->Read_State) &&
  1178. (CONNECTION_REQUEST >= pSocket->Read_State))
  1179. {
  1180. rrCode = Call_recv (pSocket);
  1181. if (RECVRET_CONTINUE == rrCode)
  1182. {
  1183. // We now have the whole X.224 packet.
  1184. switch (pSocket->Read_State)
  1185. {
  1186. case READ_DATA:
  1187. // Check whether this is the final X.224 packet
  1188. if (pSocket->X224_Header.FinalPacket & EOT_BIT)
  1189. {
  1190. // If we're waiting for a security data packet we will process
  1191. // this internally without passing it up to the transport
  1192. // client.
  1193. if (NULL != pSC)
  1194. {
  1195. if (pSC->WaitingForPacket())
  1196. {
  1197. TransportSecurityError SecErr;
  1198. SecErr = pSC->AdvanceState((PBYTE) pSocket->Data_Indication_Buffer +
  1199. sizeof(X224_DATA_PACKET),
  1200. pSocket->Data_Indication_Length -
  1201. sizeof(X224_DATA_PACKET));
  1202. if (TPRTSEC_NOERROR != SecErr)
  1203. {
  1204. // Something has gone wrong. Need to disconnect
  1205. delete pSC;
  1206. pSocket->pSC = NULL;
  1207. ulNotify = TPRT_NOTIFY_AUTHENTICATION_FAILED;
  1208. ew = ErrorExit;
  1209. break;
  1210. }
  1211. if (pSC->ContinueNeeded())
  1212. {
  1213. // We need to send out another token
  1214. // bugbug: what should we do if this fails?
  1215. ContinueAuthentication(pSocket);
  1216. }
  1217. if (pSC->StateComplete())
  1218. {
  1219. // We're connected... inform the client
  1220. TRACE_OUT(("deferred g_Transport->ConnectConfirm"));
  1221. g_Transport->ConnectConfirm(XprtConn);
  1222. }
  1223. ew = FreeX224AndExit;
  1224. break;
  1225. }
  1226. // We must decrypt the data (in place)
  1227. TRACE_OUT(("Decrypting received data"));
  1228. if (! pSC->Decrypt(pSocket->Data_Indication_Buffer +
  1229. sizeof(X224_DATA_PACKET),
  1230. pSocket->Data_Indication_Length -
  1231. sizeof(X224_DATA_PACKET)))
  1232. {
  1233. TRACE_OUT(("Sending %d bytes to application",
  1234. pSocket->Data_Indication_Length - sizeof(X224_DATA_PACKET)));
  1235. }
  1236. else
  1237. {
  1238. ERROR_OUT(("Error decrypting packet"));
  1239. ew = ErrorExit;
  1240. break;
  1241. }
  1242. }
  1243. pSocket->Read_State = DATA_READY;
  1244. }
  1245. else
  1246. {
  1247. // This and the next X.224 packets are part of a bigger MCS data PDU.
  1248. ASSERT (NULL == pSC);
  1249. pSocket->Read_State = READ_HEADER;
  1250. }
  1251. break;
  1252. case CONNECTION_CONFIRM:
  1253. {
  1254. TRACE_OUT(("ReadRequest: X224 CONNECTION_CONFIRM_PACKET received"));
  1255. BOOL bCallback = ((NULL == pSC) || (! pSC->ContinueNeeded()));
  1256. // Process the CC packet.
  1257. if (FALSE == ProcessX224ConnectPDU (pSocket,
  1258. pSocket->Data_Indication_Buffer + sizeof(X224_CONNECT),
  1259. pSocket->X224_Length - sizeof (X224_CONNECT), &ulNotify))
  1260. {
  1261. ew = ErrorExit;
  1262. break;
  1263. }
  1264. // Issue the callback if the CC was not on a secure connection
  1265. // Otherwise, we don't notify the transport client yet... still need to
  1266. // exchange security information. TRANSPORT_CONNECT_CONFIRM will
  1267. // be sent when the final security data token is received and
  1268. // processed.
  1269. if (bCallback)
  1270. {
  1271. TRACE_OUT (("TCP Callback: g_Transport->ConnectConfirm (%d, %d)", XprtConn.eType, XprtConn.nLogicalHandle));
  1272. /* We issue a callback to the user to notify him of the message */
  1273. g_Transport->ConnectConfirm(XprtConn);
  1274. }
  1275. pSocket->State = X224_CONNECTED;
  1276. ::OnProtocolControl(XprtConn, PLUGXPRT_CONNECTED);
  1277. ew = FreeX224AndExit;
  1278. }
  1279. break;
  1280. case CONNECTION_REQUEST:
  1281. {
  1282. UINT remote;
  1283. /* This structure must be accessed using byte-alignment */
  1284. #pragma pack(1)
  1285. X224_CONNECT *pConnectRequest;
  1286. /* return to normal alignment */
  1287. #pragma pack()
  1288. /* Grab the remote connection ID */
  1289. TRACE_OUT (("ReadRequest: X224 CONNECTION_REQUEST_PACKET received"));
  1290. pConnectRequest = (X224_CONNECT *) pSocket->Data_Indication_Buffer;
  1291. remote = ((unsigned int) pConnectRequest->conn.msbSrc) << 8;
  1292. remote |= pConnectRequest->conn.lsbSrc;
  1293. if (FALSE == ProcessX224ConnectPDU (pSocket, (PUChar) (pConnectRequest + 1),
  1294. pSocket->X224_Length - sizeof (X224_CONNECT), &ulNotify))
  1295. {
  1296. ew = ErrorExit;
  1297. break;
  1298. }
  1299. if (::SendX224ConnectConfirm(pSocket, remote))
  1300. {
  1301. // success
  1302. if (IS_PLUGGABLE(pSocket->XprtConn))
  1303. {
  1304. pSocket->State = SOCKET_CONNECTED;
  1305. g_Transport->ConnectIndication(XprtConn);
  1306. ASSERT(X224_CONNECTED == pSocket->State);
  1307. }
  1308. ::OnProtocolControl(XprtConn, PLUGXPRT_CONNECTED);
  1309. ew = FreeX224AndExit;
  1310. }
  1311. else
  1312. {
  1313. if (pSocket->fExtendedX224)
  1314. {
  1315. ::SendX224DisconnectRequest(pSocket, remote, securityDenied_chosen);
  1316. }
  1317. ew = ErrorExit;
  1318. }
  1319. }
  1320. break;
  1321. case DISCONNECT_REQUEST:
  1322. {
  1323. UINT remote;
  1324. X224_DR_FIXED *pX224_DR_fixed;
  1325. TRACE_OUT(("ReadRequest: X224 DISCONNECT_REQUEST_PACKET received"));
  1326. pX224_DR_fixed = (X224_DR_FIXED *) pSocket->Data_Indication_Buffer;
  1327. remote = ((unsigned int) pX224_DR_fixed->disconn.msbSrc) << 8;
  1328. remote |= pX224_DR_fixed->disconn.lsbSrc;
  1329. ProcessX224DisconnectPDU(pSocket, pSocket->Data_Indication_Buffer + sizeof(X224_DR_FIXED),
  1330. pSocket->X224_Length - sizeof(X224_DR_FIXED), &ulNotify);
  1331. ew = ErrorExit;
  1332. }
  1333. break;
  1334. }
  1335. }
  1336. else if (RECVRET_DISCONNECT == rrCode)
  1337. {
  1338. ew = ErrorExit;
  1339. }
  1340. }
  1341. if (DATA_READY == pSocket->Read_State)
  1342. {
  1343. TransportData transport_data;
  1344. // Fill in the callback structure.
  1345. transport_data.transport_connection = XprtConn;
  1346. transport_data.user_data = pSocket->Data_Indication_Buffer;
  1347. transport_data.user_data_length = pSocket->Data_Indication_Length;
  1348. transport_data.memory = pSocket->Data_Memory;
  1349. /*
  1350. * If there is an incoming security context associated with this
  1351. * socket, we must adjust pointer by header and overall size by header and
  1352. * trailer.
  1353. */
  1354. if (NULL != pSC)
  1355. {
  1356. transport_data.user_data += pSC->GetStreamHeaderSize();
  1357. transport_data.user_data_length -= (pSC->GetStreamHeaderSize() +
  1358. pSC->GetStreamTrailerSize());
  1359. }
  1360. if (TRANSPORT_NO_ERROR == g_Transport->DataIndication(&transport_data))
  1361. {
  1362. TRACE_OUT (("ReadRequest: %d bytes were accepted from socket (%d, %d)",
  1363. transport_data.user_data_length, XprtConn.eType, XprtConn.nLogicalHandle));
  1364. // Prepare for the next X.224 packet
  1365. pSocket->Read_State = READ_HEADER;
  1366. pSocket->Data_Indication_Buffer = NULL;
  1367. pSocket->Data_Memory = NULL;
  1368. }
  1369. else
  1370. {
  1371. WARNING_OUT(("ReadRequest: Error on g_Transport->DataIndication from socket (%d, %d)",
  1372. XprtConn.eType, XprtConn.nLogicalHandle));
  1373. }
  1374. }
  1375. }
  1376. else
  1377. {
  1378. WARNING_OUT (("ReadRequest: socket (%d, %d) is in WAITING_FOR_CONNECTION state.", XprtConn.eType, XprtConn.nLogicalHandle));
  1379. }
  1380. }
  1381. else
  1382. {
  1383. WARNING_OUT (("ReadRequest: socket (%d, %d) can not be found.", XprtConn.eType, XprtConn.nLogicalHandle));
  1384. }
  1385. switch (ew)
  1386. {
  1387. case FreeX224AndExit:
  1388. if (NULL != pSocket)
  1389. {
  1390. // Free the buffers we have allocated.
  1391. pSocket->FreeTransportBuffer();
  1392. // Prepare for the next X.224 packet
  1393. pSocket->Read_State = READ_HEADER;
  1394. }
  1395. break;
  1396. case ErrorExit:
  1397. // We get here only if we need to disconnect the socket (because of an error)
  1398. ASSERT(TPRT_NOTIFY_NONE != ulNotify);
  1399. ::DisconnectRequest(XprtConn, ulNotify);
  1400. break;
  1401. }
  1402. if (NULL != pSocket)
  1403. {
  1404. pSocket->Release(); // offset the previous AddRef.
  1405. }
  1406. }
  1407. /*
  1408. * TransportError FlushSendBuffer ( PSocket pSocket )
  1409. *
  1410. * Functional Description:
  1411. * This function sends any pending data through the transport.
  1412. */
  1413. TransportError FlushSendBuffer(PSocket pSocket, LPBYTE buffer, UINT length)
  1414. {
  1415. int bytes_sent = SOCKET_ERROR;
  1416. PLUGXPRT_RESULT plug_rc = PLUGXPRT_RESULT_SUCCESSFUL;
  1417. TRACE_OUT(("FlushSendBuffer"));
  1418. /* send the data */
  1419. if (IS_SOCKET(pSocket->XprtConn))
  1420. {
  1421. bytes_sent = ::send(pSocket->XprtConn.nLogicalHandle, (PChar) buffer,
  1422. (int) length, 0);
  1423. }
  1424. else
  1425. if (IS_PLUGGABLE_X224(pSocket->XprtConn))
  1426. {
  1427. bytes_sent = ::SubmitPluggableWrite(pSocket, buffer, length, &plug_rc);
  1428. }
  1429. else
  1430. if (IS_PLUGGABLE_PSTN(pSocket->XprtConn))
  1431. {
  1432. CPluggableConnection *p = ::GetPluggableConnection(pSocket);
  1433. if (NULL != p)
  1434. {
  1435. bytes_sent = p->TDataRequest(buffer, length, &plug_rc);
  1436. }
  1437. else
  1438. {
  1439. plug_rc = PLUGXPRT_RESULT_WRITE_FAILED;
  1440. }
  1441. }
  1442. if (bytes_sent == SOCKET_ERROR)
  1443. {
  1444. if (IS_SOCKET(pSocket->XprtConn))
  1445. {
  1446. /* If the error is not WOULD BLOCK, it is a real error! */
  1447. if (::WSAGetLastError() != WSAEWOULDBLOCK)
  1448. {
  1449. WARNING_OUT (("FlushSendBuffer: Error %d on write", ::WSAGetLastError()));
  1450. /* Notify the owner of the broken connection */
  1451. WARNING_OUT (("FlushSendBuffer: Sending up DISCONNECT_INDICATION"));
  1452. // SendStatusMessage (pSocket -> Remote_Address, TSTATE_REMOVED, IDS_NULL_STRING);
  1453. ::DisconnectRequest(pSocket->XprtConn, TPRT_NOTIFY_OTHER_REASON);
  1454. return (TRANSPORT_WRITE_QUEUE_FULL);
  1455. }
  1456. }
  1457. else
  1458. {
  1459. // do nothing if it is WSAEWOULDBLOCK
  1460. if (PLUGXPRT_RESULT_SUCCESSFUL != plug_rc)
  1461. {
  1462. /* Notify the owner of the broken connection */
  1463. WARNING_OUT (("FlushSendBuffer: Sending up DISCONNECT_INDICATION"));
  1464. // SendStatusMessage (pSocket -> Remote_Address, TSTATE_REMOVED, IDS_NULL_STRING);
  1465. ::DisconnectRequest(pSocket->XprtConn, TPRT_NOTIFY_OTHER_REASON);
  1466. return (TRANSPORT_WRITE_QUEUE_FULL);
  1467. }
  1468. }
  1469. bytes_sent = 0;
  1470. }
  1471. /* If the transport layer did not accept the data, its write buffers are full */
  1472. if (bytes_sent != (int) length)
  1473. {
  1474. ASSERT (bytes_sent == 0);
  1475. TRACE_OUT(("FlushSendBuffer: returning TRANSPORT_WRITE_QUEUE_FULL"));
  1476. return (TRANSPORT_WRITE_QUEUE_FULL);
  1477. }
  1478. // Increment our counter of bytes sent since last QoS notification
  1479. if (bytes_sent)
  1480. {
  1481. QoSLock();
  1482. g_dwSentSinceLastQoS += bytes_sent;
  1483. QoSUnlock();
  1484. }
  1485. TRACE_OUT (("FlushSendBuffer: %d bytes sent on Socket (%d, %d).",
  1486. length, pSocket->XprtConn.eType, pSocket->XprtConn.nLogicalHandle));
  1487. return (TRANSPORT_NO_ERROR);
  1488. }
  1489. /*
  1490. * SegmentX224Data
  1491. *
  1492. * This function segments outgoing data into X.224 packets of the appropriate size.
  1493. * It should not be called in a NM to NM call or in a call when we have negotiated an
  1494. * X.224 max PDU size of at least the size of a max MCS PDU. NM attempts to negotiate
  1495. * X.224 sizes of 8K, but will accept anything the other side proposes.
  1496. * This function does memcpy's so it will slow us down sending data.
  1497. *
  1498. * The 2 buffers specified by "ptr1" and "ptr2" and their lengths are used to create
  1499. * one stream of X.224 bytes. The function will return TRANSPORT_WRITE_QUEUE_FULL if
  1500. * it fails to allocate the necessary amount of memory.
  1501. */
  1502. TransportError SegmentX224Data (PSocket pSocket,
  1503. LPBYTE *pPtr1, UINT *pLength1,
  1504. LPBYTE Ptr2, UINT Length2)
  1505. {
  1506. TransportError TransError;
  1507. UINT length;
  1508. LPBYTE ptr1 = *pPtr1 + sizeof (X224_DATA_PACKET);
  1509. UINT length1 = *pLength1 - sizeof (X224_DATA_PACKET);
  1510. LPBYTE ptr;
  1511. UINT max_pdu_length = pSocket->Max_Packet_Length;
  1512. X224_DATA_PACKET l_X224Header = {3, 0, (UChar) (max_pdu_length >> 8), (UChar) (max_pdu_length & 0xFF),
  1513. 2, DATA_PACKET, 0};
  1514. UINT last_length;
  1515. /* This structure must be accessed using byte-alignment */
  1516. #pragma pack(1)
  1517. X224_DATA_PACKET *pX224Data;
  1518. /* return to normal alignment */
  1519. #pragma pack()
  1520. ASSERT(! IS_PLUGGABLE_PSTN(pSocket->XprtConn));
  1521. // Calculate how much space we need.
  1522. length = *pLength1 + Length2;
  1523. ASSERT (pSocket->Max_Packet_Length < length);
  1524. ASSERT (pSocket->Max_Packet_Length > sizeof(X224_DATA_PACKET));
  1525. max_pdu_length -= sizeof (X224_DATA_PACKET);
  1526. /*
  1527. * Calculate the space we need to allocate. Notice that the data already
  1528. * contains one X.224 header.
  1529. */
  1530. length += (length / max_pdu_length) * sizeof (X224_DATA_PACKET);
  1531. *pPtr1 = Allocate (length);
  1532. if (*pPtr1 != NULL) {
  1533. TransError = TRANSPORT_NO_ERROR;
  1534. ptr = *pPtr1;
  1535. // Go through the 1st buffer.
  1536. while (length1 > 0) {
  1537. // Copy the X.224 header.
  1538. memcpy (ptr, &l_X224Header, sizeof(X224_DATA_PACKET));
  1539. pX224Data = (X224_DATA_PACKET *) ptr;
  1540. ptr += sizeof (X224_DATA_PACKET);
  1541. // Copy data
  1542. length = ((max_pdu_length > length1) ? length1 : max_pdu_length);
  1543. memcpy (ptr, ptr1, length);
  1544. last_length = length;
  1545. // Advance pointers
  1546. ptr1 += length;
  1547. ptr += length;
  1548. length1 -= length;
  1549. }
  1550. // If there is space in the current X.224 PDU, we need to use it.
  1551. length = max_pdu_length - length;
  1552. if (length > 0 && Length2 > 0) {
  1553. if (length > Length2)
  1554. length = Length2;
  1555. memcpy (ptr, Ptr2, length);
  1556. last_length += length;
  1557. Ptr2 += length;
  1558. ptr += length;
  1559. Length2 -= length;
  1560. }
  1561. // Go through the 2nd buffer.
  1562. while (Length2 > 0) {
  1563. // Copy the X.224 header.
  1564. memcpy (ptr, &l_X224Header, sizeof(X224_DATA_PACKET));
  1565. pX224Data = (X224_DATA_PACKET *) ptr;
  1566. ptr += sizeof (X224_DATA_PACKET);
  1567. // Copy data
  1568. length = ((max_pdu_length > Length2) ? Length2 : max_pdu_length);
  1569. memcpy (ptr, Ptr2, length);
  1570. last_length = length;
  1571. // Advance pointers
  1572. Ptr2 += length;
  1573. ptr += length;
  1574. Length2 -= length;
  1575. }
  1576. // Prepare for return
  1577. *pLength1 = (UINT)(ptr - *pPtr1);
  1578. // Set the last X.224 header
  1579. last_length += sizeof(X224_DATA_PACKET);
  1580. pX224Data->FinalPacket = EOT_BIT;
  1581. pX224Data->rfc.msbPacketSize = (UChar) (last_length >> 8);
  1582. pX224Data->rfc.lsbPacketSize = (UChar) (last_length & 0xFF);
  1583. }
  1584. else {
  1585. ERROR_OUT (("SegmentX224Data: Failed to allocate memory of length %d.", length));
  1586. TransError = TRANSPORT_WRITE_QUEUE_FULL;
  1587. }
  1588. return TransError;
  1589. }
  1590. /*
  1591. * SendSecureData
  1592. *
  1593. * This function segments secure data into X.224 packets, if needed, and flushes them through
  1594. * the transport. "pBuf" and "cbBuf" provide the encrypted data buffer and length.
  1595. */
  1596. TransportError SendSecureData (PSocket pSocket, LPBYTE pBuf, UINT cbBuf)
  1597. {
  1598. TransportError TransError;
  1599. LPBYTE pBuf_Copy = pBuf;
  1600. UINT cbBuf_Copy = cbBuf;
  1601. // Do we need to segment the data into X.224 packets?
  1602. if (pSocket->Max_Packet_Length >= cbBuf) {
  1603. TransError = TRANSPORT_NO_ERROR;
  1604. }
  1605. else {
  1606. TransError = SegmentX224Data (pSocket, &pBuf, &cbBuf, NULL, 0);
  1607. }
  1608. // Flush the data, if everything OK so far.
  1609. if (TRANSPORT_NO_ERROR == TransError)
  1610. TransError = FlushSendBuffer (pSocket, pBuf, cbBuf);
  1611. // If we segmented the data, we need to free the segmented buffer.
  1612. if (pBuf != pBuf_Copy)
  1613. Free(pBuf);
  1614. // If there are errors, we need to store the decrypted data for the next time, so don't free it.
  1615. if (TRANSPORT_NO_ERROR == TransError) {
  1616. LocalFree(pBuf_Copy);
  1617. }
  1618. return TransError;
  1619. }
  1620. /*
  1621. * TransportError DataRequest ( TransportConnection XprtConn,
  1622. * PSimplePacket packet)
  1623. *
  1624. * Functional Description:
  1625. * This function is used to send a data packet to the remote site.
  1626. * If the user_data_length is zero, and we have no pending data,
  1627. * it sends a keep-alive (zero-length) packet.
  1628. */
  1629. TransportError DataRequest (TransportConnection XprtConn,
  1630. PSimplePacket packet)
  1631. {
  1632. PSocket pSocket;
  1633. LPBYTE ptr1, ptr2;
  1634. UINT length1, length2;
  1635. TransportError TransError = TRANSPORT_NO_ERROR;
  1636. TRACE_OUT(("DataRequest: packet=0x%x", packet));
  1637. if (NULL != (pSocket = g_pSocketList->FindByTransportConnection(XprtConn)))
  1638. {
  1639. // First, we need to handle the retry operations.
  1640. if (NULL != pSocket->pSC) {
  1641. LPBYTE lpBuf;
  1642. /*
  1643. * Check to see whether we have already encrypted, but not sent
  1644. * the last piece of data.
  1645. */
  1646. lpBuf = pSocket->Retry_Info.sbiBufferInfo.lpBuffer;
  1647. if (NULL != lpBuf) {
  1648. TransError = SendSecureData (pSocket, lpBuf,
  1649. pSocket->Retry_Info.sbiBufferInfo.uiLength);
  1650. if (TransError == TRANSPORT_NO_ERROR) {
  1651. TRACE_OUT(("DataRequest: Sent previously-encrypted piece of data."));
  1652. pSocket->Retry_Info.sbiBufferInfo.lpBuffer = NULL;
  1653. }
  1654. }
  1655. }
  1656. else {
  1657. PDataPacket pdpPacket = pSocket->Retry_Info.pUnfinishedPacket;
  1658. // Check to see whether we have half-sent the last packet.
  1659. if (NULL != pdpPacket) {
  1660. /*
  1661. * We need to send the rest of the unfinished packet,
  1662. * before we can go on. The 1st part of the packet
  1663. * must have already been sent.
  1664. */
  1665. // The packet's encoded data must be in 2 buffers.
  1666. ASSERT (TRUE == pdpPacket->IsEncodedDataBroken());
  1667. TransError = FlushSendBuffer (pSocket, pdpPacket->GetUserData(),
  1668. pdpPacket->GetUserDataLength());
  1669. if (TransError == TRANSPORT_NO_ERROR) {
  1670. pdpPacket->Unlock();
  1671. TRACE_OUT(("DataRequest: 2nd part of data packet was sent out in separate request"));
  1672. pSocket->Retry_Info.pUnfinishedPacket = NULL;
  1673. }
  1674. }
  1675. }
  1676. if ((TransError == TRANSPORT_NO_ERROR) && (packet != NULL)) {
  1677. // Now, let's try to send this new packet.
  1678. ptr1 = packet->GetEncodedData();
  1679. length1 = packet->GetEncodedDataLength();
  1680. /*
  1681. * We need to find out whether the packet to send is a
  1682. * DataPacket or a Packet object. If it's a DataPacket, the
  1683. * encoded data may not be contiguous (may be broken in 2 parts)
  1684. */
  1685. if ((packet->IsDataPacket()) &&
  1686. ((PDataPacket) packet)->IsEncodedDataBroken()) {
  1687. // the data to send is broken into 2 parts.
  1688. ptr2 = ((PDataPacket) packet)->GetUserData();
  1689. length2 = ((PDataPacket) packet)->GetUserDataLength();
  1690. }
  1691. else {
  1692. // the data to send is contiguous.
  1693. ptr2 = NULL;
  1694. length2 = 0;
  1695. }
  1696. if (NULL != pSocket->pSC) {
  1697. LPBYTE pBuf;
  1698. UINT cbBuf;
  1699. TRACE_OUT(("Encrypting %d bytes of outgoing data",
  1700. (length1 + length2) - sizeof(X224_DATA_PACKET)));
  1701. if (!pSocket->pSC->Encrypt(ptr1 + sizeof(X224_DATA_PACKET),
  1702. length1 - sizeof(X224_DATA_PACKET),
  1703. ptr2, length2, &pBuf, &cbBuf))
  1704. {
  1705. ASSERT (TransError == TRANSPORT_NO_ERROR);
  1706. TransError = SendSecureData (pSocket, pBuf, cbBuf);
  1707. if (TRANSPORT_NO_ERROR != TransError) {
  1708. TRACE_OUT(("DataRequest: Failed to send encrypted data. Keeping buffer for retry."));
  1709. pSocket->Retry_Info.sbiBufferInfo.lpBuffer = pBuf;
  1710. pSocket->Retry_Info.sbiBufferInfo.uiLength = cbBuf;
  1711. // The caller needs to remove the packet from its queue.
  1712. TransError = TRANSPORT_NO_ERROR;
  1713. }
  1714. }
  1715. else
  1716. {
  1717. WARNING_OUT (("DataRequest: Encryption failed. Disconnecting..."));
  1718. ::DisconnectRequest(pSocket->XprtConn, TPRT_NOTIFY_OTHER_REASON);
  1719. TransError = TRANSPORT_MEMORY_FAILURE;
  1720. }
  1721. }
  1722. else {
  1723. BOOL bNeedToFree = FALSE;
  1724. // Do we need to segment the data into X.224 packets?
  1725. if (pSocket->Max_Packet_Length >= length1 + length2)
  1726. ;
  1727. else {
  1728. TransError = SegmentX224Data (pSocket, &ptr1, &length1, ptr2, length2);
  1729. if (TRANSPORT_NO_ERROR == TransError) {
  1730. // The data is now contiguous
  1731. ptr2 = NULL;
  1732. bNeedToFree = TRUE;
  1733. }
  1734. }
  1735. // Flush the data, if everything OK so far.
  1736. if (TRANSPORT_NO_ERROR == TransError)
  1737. TransError = FlushSendBuffer (pSocket, ptr1, length1);
  1738. // Free the temporary X.224 buffer if we need to.
  1739. if (bNeedToFree)
  1740. Free(ptr1);
  1741. if (TRANSPORT_NO_ERROR == TransError) {
  1742. // If there is more, send it, too.
  1743. if (NULL != ptr2) {
  1744. TransError = FlushSendBuffer (pSocket, ptr2, length2);
  1745. if (TRANSPORT_NO_ERROR != TransError) {
  1746. /*
  1747. * We need to keep the partial packet to send it later.
  1748. * Notice we have already sent a part of this packet.
  1749. */
  1750. ASSERT (pSocket->Retry_Info.pUnfinishedPacket == NULL);
  1751. pSocket->Retry_Info.pUnfinishedPacket = (PDataPacket) packet;
  1752. packet->Lock();
  1753. // Return success.
  1754. TransError = TRANSPORT_NO_ERROR;
  1755. }
  1756. }
  1757. }
  1758. }
  1759. }
  1760. pSocket->Release();
  1761. }
  1762. else {
  1763. TransError = TRANSPORT_NO_SUCH_CONNECTION;
  1764. WARNING_OUT (("DataRequest: Attempt to send to unknown transport connection (%d, %d)",
  1765. XprtConn.eType, XprtConn.nLogicalHandle));
  1766. }
  1767. return TransError;
  1768. }
  1769. /*
  1770. * void PurgeRequest (TransportConnection XprtConn)
  1771. *
  1772. * Functional Description:
  1773. * This function purges the outbound packets for the given transport
  1774. * connection.
  1775. */
  1776. void PurgeRequest (TransportConnection XprtConn)
  1777. {
  1778. PSocket pSocket;
  1779. TRACE_OUT (("In PurgeRequest for transport connection (%d, %d)", XprtConn.eType, XprtConn.nLogicalHandle));
  1780. if (IS_PLUGGABLE_PSTN(XprtConn))
  1781. {
  1782. CPluggableConnection *p = ::GetPluggableConnection(XprtConn.nLogicalHandle);
  1783. if (NULL != p)
  1784. {
  1785. p->TPurgeRequest();
  1786. }
  1787. }
  1788. else
  1789. /* If the logical connection handle is not registered, return error */
  1790. if (NULL != (pSocket = g_pSocketList->FindByTransportConnection(XprtConn)))
  1791. {
  1792. /* Purge the pending data stored in the socket struct */
  1793. if (NULL != pSocket->pSC) {
  1794. if (NULL != pSocket->Retry_Info.sbiBufferInfo.lpBuffer) {
  1795. TRACE_OUT (("PurgeRequest: Purging data packet for secure connection"));
  1796. LocalFree (pSocket->Retry_Info.sbiBufferInfo.lpBuffer);
  1797. pSocket->Retry_Info.sbiBufferInfo.lpBuffer = NULL;
  1798. }
  1799. }
  1800. pSocket->Release();
  1801. }
  1802. }
  1803. /*
  1804. * void EnableReceiver (Void)
  1805. *
  1806. * Functional Description:
  1807. * This function allows packets to be sent to the user application.
  1808. */
  1809. void EnableReceiver (void)
  1810. {
  1811. PSocket pSocket;
  1812. ::EnterCriticalSection(&g_csTransport);
  1813. CSocketList Connection_List_Copy (*g_pSocketList);
  1814. ::LeaveCriticalSection(&g_csTransport);
  1815. TRACE_OUT(("EnableReceiver"));
  1816. if (NULL != g_pLegacyTransport)
  1817. {
  1818. g_pLegacyTransport->TEnableReceiver();
  1819. }
  1820. /* Go thru all the sockets and enable receiving */
  1821. while (NULL != (pSocket = Connection_List_Copy.Get()))
  1822. {
  1823. /*
  1824. * If we had failed to deliver a data pkt to MCS before, we need
  1825. * an extra ReadRequest to recv and keep the FD_READ msgs coming.
  1826. */
  1827. if (DATA_READY == pSocket->Read_State)
  1828. {
  1829. ::ReadRequest(pSocket->XprtConn);
  1830. }
  1831. TRACE_OUT (("EnableReceiver: Calling ReadRequestEx on socket (%d, %d)",
  1832. pSocket->XprtConn.eType, pSocket->XprtConn.nLogicalHandle));
  1833. ::ReadRequestEx(pSocket->XprtConn);
  1834. }
  1835. }
  1836. /*
  1837. * TransportError ShutdownAndClose (TransportConnection , BOOL fShutdown, int how)
  1838. *
  1839. * Functional Description
  1840. * This function shuts down the socket and closes it.
  1841. *
  1842. */
  1843. void ShutdownAndClose (TransportConnection XprtConn, BOOL fShutdown, int how)
  1844. {
  1845. if (IS_SOCKET(XprtConn))
  1846. {
  1847. int error;
  1848. if (fShutdown)
  1849. {
  1850. error = ::shutdown(XprtConn.nLogicalHandle, how);
  1851. ASSERT(error != SOCKET_ERROR);
  1852. #ifdef DEBUG
  1853. if(error == SOCKET_ERROR)
  1854. {
  1855. error = WSAGetLastError();
  1856. WARNING_OUT (("ShutdownAndClose: shutdown returned %d", error));
  1857. }
  1858. #endif // DEBUG
  1859. }
  1860. error = ::closesocket(XprtConn.nLogicalHandle);
  1861. #ifdef DEBUG
  1862. if(error == SOCKET_ERROR)
  1863. {
  1864. WARNING_OUT(("ShutdownAndClose: closesocket returned %d", WSAGetLastError()));
  1865. }
  1866. #endif // DEBUG
  1867. }
  1868. }
  1869. /*
  1870. * TransportError GetLocalAddress (TransportConnection XprtConn,
  1871. * TransportAddress address,
  1872. * int * size)
  1873. *
  1874. * Functional Description:
  1875. * This function retrieves the local IP address associated with the given
  1876. * connection. It returns TRANSPORT_NO_SUCH_CONNECTION if the address is
  1877. * not available. If the address is available, the size parameter specifies
  1878. * the size of the address buffer on entry, and it is filled in with the size
  1879. * used for the address on exit.
  1880. */
  1881. TransportError GetLocalAddress( TransportConnection XprtConn,
  1882. TransportAddress address,
  1883. int * size)
  1884. {
  1885. SOCKADDR_IN socket_control;
  1886. PChar szTemp;
  1887. int Length;
  1888. TransportError error = TRANSPORT_NO_SUCH_CONNECTION;
  1889. if (NULL != g_pSocketList->FindByTransportConnection(XprtConn, TRUE))
  1890. {
  1891. if (IS_SOCKET(XprtConn))
  1892. {
  1893. /* Get the local name for the socket */
  1894. Length = sizeof(socket_control);
  1895. if (getsockname(XprtConn.nLogicalHandle, (LPSOCKADDR) &socket_control, &Length) == 0) {
  1896. /* Convert it to an IP address string */
  1897. szTemp = inet_ntoa(socket_control.sin_addr);
  1898. ASSERT (szTemp);
  1899. Length = (int) strlen(szTemp) + 1;
  1900. ASSERT (*size >= Length);
  1901. ASSERT (address);
  1902. /* Copy it to the buffer */
  1903. lstrcpyn((PChar)address, szTemp, Length);
  1904. *size = Length;
  1905. error = TRANSPORT_NO_ERROR;
  1906. }
  1907. }
  1908. else
  1909. {
  1910. ASSERT(IS_PLUGGABLE(XprtConn));
  1911. // string should look like "xprt: 1"
  1912. char szConnStr[T120_CONNECTION_ID_LENGTH];
  1913. Length = ::CreateConnString((UINT)XprtConn.nLogicalHandle, szConnStr);
  1914. if (*size > ++Length)
  1915. {
  1916. ::lstrcpyn(address, szConnStr, Length+1);
  1917. *size = Length;
  1918. error = TRANSPORT_NO_ERROR;
  1919. TRACE_OUT (("GetLocalAddress: plugable connection local address (%s)", address));
  1920. }
  1921. else
  1922. {
  1923. ERROR_OUT(("GetLocalAddress: buffer too small, given=%d, required=%d", *size, Length));
  1924. error = TRANSPORT_BUFFER_TOO_SMALL;
  1925. }
  1926. }
  1927. }
  1928. #ifdef DEBUG
  1929. if (error != TRANSPORT_NO_ERROR)
  1930. WARNING_OUT (("GetLocalAddress: Failure to obtain local address (%d)", WSAGetLastError()));
  1931. #endif // DEBUG
  1932. return (error);
  1933. }
  1934. /*
  1935. * void AcceptCall (BOOL fSecure)
  1936. *
  1937. * Functional Description:
  1938. * This function calls Winsock to answer an incoming call.
  1939. */
  1940. void AcceptCall (TransportConnection XprtConn)
  1941. {
  1942. PSocket pSocket;
  1943. PSecurityContext pSC = NULL;
  1944. SOCKADDR_IN socket_control;
  1945. int size;
  1946. TRACE_OUT(("AcceptCall"));
  1947. if (IS_SOCKET(XprtConn))
  1948. {
  1949. ASSERT(XprtConn.nLogicalHandle == Listen_Socket);
  1950. ASSERT (Listen_Socket != INVALID_SOCKET);
  1951. /* Call accept() to see if anyone is calling us */
  1952. size = sizeof (socket_control);
  1953. XprtConn.nLogicalHandle = ::accept ( Listen_Socket,
  1954. (struct sockaddr *) &socket_control, &size);
  1955. /* Note that we expect accept to complete immediately */
  1956. if (XprtConn.nLogicalHandle == INVALID_SOCKET)
  1957. {
  1958. ERROR_OUT (("AcceptCall: Error on accept = %d", WSAGetLastError()));
  1959. // SendStatusMessage ("", TSTATE_NOT_READY, IDS_NULL_STRING);
  1960. return;
  1961. }
  1962. }
  1963. /* If the accept() received an incoming call, create a connection and notify our owner object. */
  1964. pSocket = newSocket(XprtConn, NULL);
  1965. if( pSocket == NULL )
  1966. {
  1967. /* Close the socket */
  1968. ::ShutdownAndClose(XprtConn, TRUE, 2);
  1969. return;
  1970. }
  1971. pSocket -> State = SOCKET_CONNECTED;
  1972. if (IS_SOCKET(XprtConn))
  1973. {
  1974. /* Issue the getpeername() function to get the remote user's address */
  1975. size = sizeof (socket_control);
  1976. if (::getpeername(XprtConn.nLogicalHandle, (LPSOCKADDR) &socket_control, &size) == 0)
  1977. {
  1978. lstrcpyn (
  1979. pSocket -> Remote_Address,
  1980. inet_ntoa (socket_control.sin_addr),
  1981. MAXIMUM_IP_ADDRESS_SIZE-1);
  1982. pSocket -> Remote_Address[MAXIMUM_IP_ADDRESS_SIZE - 1] = NULL;
  1983. }
  1984. // SendStatusMessage(pSocket -> Remote_Address, TSTATE_CONNECTED, IDS_NULL_STRING);
  1985. }
  1986. /* Add to connection list */
  1987. // bugbug: we fail to insert.
  1988. g_pSocketList->SafeAppend(pSocket);
  1989. /* Notify the user */
  1990. TRACE_OUT (("TCP Callback: g_Transport->ConnectIndication (%d, %d)", XprtConn.eType, XprtConn.nLogicalHandle));
  1991. /* We issue a callback to the user to notify him of the message */
  1992. g_Transport->ConnectIndication(XprtConn);
  1993. }
  1994. //
  1995. // ReadRequestEx() is for the plugable transport.
  1996. // Since we do not have the FD_ACCEPT notifcation, we try to make sure
  1997. // we have a valid transport connection for every read...
  1998. // The following piece of code is derived from AcceptCall().
  1999. //
  2000. void ReadRequestEx(TransportConnection XprtConn)
  2001. {
  2002. if (! IS_PLUGGABLE_PSTN(XprtConn))
  2003. {
  2004. ::ReadRequest(XprtConn);
  2005. }
  2006. }
  2007. /*
  2008. * LRESULT WindowProcedure (
  2009. * HWND window_handle,
  2010. * UINT message,
  2011. * WPARAM wParam,
  2012. * LPARAM lParam)
  2013. *
  2014. * Public
  2015. *
  2016. * Functional Description:
  2017. * This function is called by Windows when we dispatch a TCP message from the
  2018. * event loop above. It gives us a chance to process the incoming socket messages.
  2019. */
  2020. LRESULT WindowProcedure (HWND window_handle,
  2021. UINT message,
  2022. WPARAM wParam,
  2023. LPARAM lParam)
  2024. {
  2025. TransportConnection XprtConn;
  2026. UShort error;
  2027. UShort event;
  2028. //PSocket pSocket;
  2029. switch (message)
  2030. {
  2031. #ifndef NO_TCP_TIMER
  2032. case WM_TIMER:
  2033. {
  2034. /*
  2035. ** We are currently using a slow timer to keep reading even when
  2036. ** FD_READ msgs get lost (this happens on Win95).
  2037. **
  2038. */
  2039. if (NULL != g_Transport) {
  2040. TRACE_OUT(("MSMCSTCP: WM_TIMER"));
  2041. EnableReceiver ();
  2042. }
  2043. }
  2044. break;
  2045. #endif /* NO_TCP_TIMER */
  2046. case WM_SOCKET_NOTIFICATION:
  2047. {
  2048. /* This message is generated by WinSock */
  2049. event = WSAGETSELECTEVENT (lParam);
  2050. error = WSAGETSELECTERROR (lParam);
  2051. SET_SOCKET_CONNECTION(XprtConn, wParam);
  2052. /* We disconnect whenever a socket command generates an error message */
  2053. if (error)
  2054. {
  2055. WARNING_OUT (("TCP: error %d on socket (%d). Event: %d", error, XprtConn.nLogicalHandle, event));
  2056. ::DisconnectRequest(XprtConn, TPRT_NOTIFY_OTHER_REASON);
  2057. break;
  2058. }
  2059. /* We get FD_CLOSE when the socket is closed by the remote site. */
  2060. if (event & FD_CLOSE)
  2061. {
  2062. TRACE_OUT (("TCP: FD_CLOSE(%d)", XprtConn.nLogicalHandle));
  2063. ::DisconnectRequest(XprtConn, TPRT_NOTIFY_OTHER_REASON);
  2064. break;
  2065. }
  2066. /* We get FD_READ when there is data available for us to read. */
  2067. if (event & FD_READ)
  2068. {
  2069. // TRACE_OUT(("MSMCSTCP: FD_READ(%d)", (UINT) wParam));
  2070. ::ReadRequest(XprtConn);
  2071. }
  2072. /* We get FD_ACCEPT when a remote site is connecting with us */
  2073. if (event & FD_ACCEPT)
  2074. {
  2075. TRACE_OUT (("TCP: FD_ACCEPT(%d)", XprtConn.nLogicalHandle));
  2076. /* Note that we always accept calls. Disconnect cancels them. */
  2077. TransportConnection XprtConn2;
  2078. SET_SOCKET_CONNECTION(XprtConn2, Listen_Socket);
  2079. ::AcceptCall(XprtConn2);
  2080. }
  2081. /* We get FD_CONNECT when our connect completes */
  2082. if (event & FD_CONNECT)
  2083. {
  2084. TRACE_OUT (("TCP: FD_CONNECT(%d)", XprtConn.nLogicalHandle));
  2085. ::SendX224ConnectRequest(XprtConn);
  2086. }
  2087. /* We get FD_WRITE when there is space available to write data to WinSock */
  2088. if (event & FD_WRITE)
  2089. {
  2090. /*
  2091. * We need to send a BUFFER_EMPTY_INDICATION to the connection associated
  2092. * with the socket
  2093. */
  2094. TRACE_OUT (("TCP: FD_WRITE(%d)", XprtConn.nLogicalHandle));
  2095. // We need to flush the socket's pending data first.
  2096. if (TRANSPORT_NO_ERROR == ::DataRequest(XprtConn, NULL))
  2097. {
  2098. TRACE_OUT (("TCP: Sending BUFFER_EMPTY_INDICATION to transport."));
  2099. g_Transport->BufferEmptyIndication(XprtConn);
  2100. }
  2101. }
  2102. }
  2103. break;
  2104. case WM_PLUGGABLE_X224:
  2105. // for low level read and write,
  2106. {
  2107. XprtConn.eType = (TransportType) PLUGXPRT_WPARAM_TO_TYPE(wParam);
  2108. XprtConn.nLogicalHandle = PLUGXPRT_WPARAM_TO_ID(wParam);
  2109. ASSERT(IS_PLUGGABLE(XprtConn));
  2110. event = PLUGXPRT_LPARAM_TO_EVENT(lParam);
  2111. error = PLUGXPRT_LPARAM_TO_ERROR(lParam);
  2112. /* We disconnect whenever a socket command generates an error message */
  2113. if (error)
  2114. {
  2115. WARNING_OUT(("PluggableWndProc: error %d on socket (%d, %d). Event: %d",
  2116. error, XprtConn.eType, XprtConn.nLogicalHandle, event));
  2117. ::DisconnectRequest(XprtConn, TPRT_NOTIFY_OTHER_REASON);
  2118. ::PluggableShutdown(XprtConn);
  2119. break;
  2120. }
  2121. switch (event)
  2122. {
  2123. case PLUGXPRT_EVENT_READ:
  2124. TRACE_OUT(("PluggableWndProc: READ(%d, %d)", XprtConn.eType, XprtConn.nLogicalHandle));
  2125. ::ReadRequestEx(XprtConn);
  2126. break;
  2127. case PLUGXPRT_EVENT_WRITE:
  2128. TRACE_OUT(("PluggableWndProc: WRITE(%d, %d)", XprtConn.eType, XprtConn.nLogicalHandle));
  2129. ::PluggableWriteTheFirst(XprtConn);
  2130. break;
  2131. case PLUGXPRT_EVENT_CLOSE:
  2132. TRACE_OUT(("PluggableWndProc: CLOSE(%d, %d)", XprtConn.eType, XprtConn.nLogicalHandle));
  2133. ::DisconnectRequest(XprtConn, TPRT_NOTIFY_OTHER_REASON);
  2134. break;
  2135. case PLUGXPRT_HIGH_LEVEL_READ:
  2136. TRACE_OUT(("PluggableWndProc: READ_NEXT(%d, %d)", XprtConn.eType, XprtConn.nLogicalHandle));
  2137. ::ReadRequestEx(XprtConn);
  2138. break;
  2139. case PLUGXPRT_HIGH_LEVEL_WRITE:
  2140. TRACE_OUT(("PluggableWndProc: WRITE_NEXT(%d, %d)", XprtConn.eType, XprtConn.nLogicalHandle));
  2141. // We need to flush the socket's pending data first.
  2142. if (TRANSPORT_NO_ERROR == ::DataRequest(XprtConn, NULL))
  2143. {
  2144. TRACE_OUT(("PluggableWndProc: Sending BUFFER_EMPTY_INDICATION to transport."));
  2145. g_Transport->BufferEmptyIndication(XprtConn);
  2146. }
  2147. break;
  2148. default:
  2149. ERROR_OUT(("PluggableWndProc: unknown event=%d.", event));
  2150. break;
  2151. }
  2152. }
  2153. break;
  2154. case WM_PLUGGABLE_PSTN:
  2155. {
  2156. extern void HandlePSTNCallback(WPARAM wParam, LPARAM lParam);
  2157. HandlePSTNCallback(wParam, lParam);
  2158. }
  2159. break;
  2160. default:
  2161. {
  2162. /*
  2163. ** The message is not related to WinSock messages, so let
  2164. ** the default window procedure handle it.
  2165. */
  2166. return (DefWindowProc (window_handle, message, wParam, lParam));
  2167. }
  2168. }
  2169. return (0);
  2170. }
  2171. // GetSecurityInfo() takes a connection_handle and returns the security information associated with
  2172. // it.
  2173. //
  2174. // Returns TRUE if we can either find the information or we are not directly connected to the node
  2175. // represented by this connection handle.
  2176. //
  2177. // Returns FALSE if we are directly connected but for some reason could not get the info -- this
  2178. // result should be viewed as suspicious.
  2179. BOOL GetSecurityInfo(ConnectionHandle connection_handle, PBYTE pInfo, PDWORD pcbInfo)
  2180. {
  2181. PSocket pSocket;
  2182. SOCKET socket_number;
  2183. if (g_pMCSController->FindSocketNumber(connection_handle, &socket_number))
  2184. {
  2185. TransportConnection XprtConn;
  2186. SET_SOCKET_CONNECTION(XprtConn, socket_number);
  2187. BOOL fRet = FALSE;
  2188. if (NULL != (pSocket = g_pSocketList->FindByTransportConnection(XprtConn)))
  2189. {
  2190. if (NULL != pSocket->pSC)
  2191. {
  2192. fRet = pSocket->pSC->GetUserCert(pInfo, pcbInfo);
  2193. }
  2194. else
  2195. {
  2196. WARNING_OUT(("GetSecurityInfo: queried non-secure socket %d", socket_number));
  2197. }
  2198. pSocket->Release();
  2199. }
  2200. else
  2201. {
  2202. WARNING_OUT(("GetSecurityInfo: socket %d not found", socket_number ));
  2203. }
  2204. return fRet;
  2205. }
  2206. // In this case we are not directly connected, so will return length of NOT_DIRECTLY_CONNECTED
  2207. // but positive return value.
  2208. *pcbInfo = NOT_DIRECTLY_CONNECTED;
  2209. return TRUE;
  2210. }
  2211. // GetSecurityInfoFromGCCID() takes a GCCID and returns the security information associated with
  2212. // it.
  2213. //
  2214. // Returns TRUE if either (1) we successfully retrieve the information from a transport-level
  2215. // connection, or (2) we find that we are not directly connected to the node with this GCCID.
  2216. //
  2217. // Returns FALSE if we are directly connected but cannot retrieve the info, or some other error
  2218. // occurs. A FALSE return value should be treated as a security violation.
  2219. BOOL WINAPI T120_GetSecurityInfoFromGCCID(DWORD dwGCCID, PBYTE pInfo, PDWORD pcbInfo)
  2220. {
  2221. PSocket pSocket;
  2222. SOCKET socket_number;
  2223. if ( NULL != dwGCCID )
  2224. {
  2225. // Get the user info for a remote connection
  2226. ConnectionHandle connection_handle;
  2227. BOOL fConnected = FindSocketNumber(dwGCCID, &socket_number);
  2228. if (fConnected == FALSE) {
  2229. (* pcbInfo) = 0;
  2230. return TRUE;
  2231. }
  2232. TransportConnection XprtConn;
  2233. SET_SOCKET_CONNECTION(XprtConn, socket_number);
  2234. BOOL fRet = FALSE;
  2235. if (NULL != (pSocket = g_pSocketList->FindByTransportConnection(XprtConn)))
  2236. {
  2237. if (NULL != pSocket->pSC)
  2238. {
  2239. fRet = pSocket->pSC->GetUserCert(pInfo, pcbInfo);
  2240. }
  2241. else
  2242. {
  2243. WARNING_OUT(("GetSecurityInfoFromGCCID: queried non-secure socket %d", socket_number));
  2244. }
  2245. pSocket->Release();
  2246. }
  2247. else
  2248. {
  2249. ERROR_OUT(("GetSecurityInfoFromGCCID: socket %d not found", socket_number ));
  2250. }
  2251. return fRet;
  2252. }
  2253. else
  2254. {
  2255. // Get the user info for the local user
  2256. if ( NULL != g_Transport && NULL != g_Transport->pSecurityInterface )
  2257. return g_Transport->pSecurityInterface->GetUserCert( pInfo, pcbInfo );
  2258. else
  2259. return FALSE;
  2260. }
  2261. }
  2262. DWORD WINAPI T120_TprtSecCtrl ( DWORD dwCode, DWORD_PTR dwParam1, DWORD_PTR dwParam2 )
  2263. {
  2264. DWORD dwRet = TPRTSEC_NOERROR;
  2265. RegEntry re(CONFERENCING_KEY, HKEY_CURRENT_USER);
  2266. switch ( dwCode )
  2267. {
  2268. case TPRTCTRL_SETX509CREDENTIALS:
  2269. //
  2270. // Security. Create transport interface if we don't have one.
  2271. // Update credentials if we do.
  2272. //
  2273. if (!g_Transport->pSecurityInterface)
  2274. {
  2275. g_Transport->pSecurityInterface =
  2276. new SecurityInterface(g_Transport->bInServiceContext);
  2277. if ( TPRTSEC_NOERROR !=
  2278. g_Transport->pSecurityInterface->Initialize())
  2279. {
  2280. delete g_Transport->pSecurityInterface;
  2281. g_Transport->pSecurityInterface = NULL;
  2282. dwRet = TPRTSEC_SSPIFAIL;
  2283. }
  2284. }
  2285. else
  2286. {
  2287. //
  2288. // dwParam1 points to an encoded X509 cert
  2289. // create credentials from it.
  2290. //
  2291. dwRet = g_Transport->pSecurityInterface->
  2292. InitializeCreds((PCCERT_CONTEXT)dwParam1);
  2293. }
  2294. return dwRet;
  2295. break;
  2296. case TPRTCTRL_GETX509CREDENTIALS:
  2297. if ( g_Transport->pSecurityInterface )
  2298. {
  2299. DWORD cb;
  2300. PBYTE pb;
  2301. if ( g_Transport->pSecurityInterface->GetUserCert( NULL, &cb))
  2302. {
  2303. if ( pb = (PBYTE)CoTaskMemAlloc ( cb ))
  2304. {
  2305. if(g_Transport->pSecurityInterface->GetUserCert(pb,&cb))
  2306. {
  2307. *((PBYTE *)dwParam1) = pb;
  2308. *((PDWORD)dwParam2) = cb;
  2309. dwRet = TPRTSEC_NOERROR;
  2310. }
  2311. else
  2312. CoTaskMemFree(pb);
  2313. }
  2314. }
  2315. }
  2316. else
  2317. {
  2318. ERROR_OUT(("TPRTCTRL_GETX509CREDENTIALS w/ no infc"));
  2319. dwRet = TPRTSEC_SSPIFAIL;
  2320. }
  2321. return dwRet;
  2322. break;
  2323. default:
  2324. ERROR_OUT(("TprtSecCtrl: unrecognized command code"));
  2325. return 0;
  2326. }
  2327. ASSERT(FALSE); // Should not reach this
  2328. return 0;
  2329. }