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.

2665 lines
98 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. //x5:223196 - fix AV when invalid PDU is processed
  793. if(CP_length < length)
  794. {
  795. CP_length = 0;
  796. *pNotify = TPRT_NOTIFY_INCOMPATIBLE_T120_TPDU;
  797. break;
  798. }
  799. CP_ptr += length;
  800. CP_length -= length;
  801. }
  802. if (bSecurityInfoFound == FALSE) {
  803. if ((pSocket->Read_State == CONNECTION_CONFIRM) && (pSC != NULL) && pSC->ContinueNeeded()) {
  804. WARNING_OUT(("Downlevel response to secure call attempt"));
  805. if (NULL != pNotify)
  806. *pNotify = TPRT_NOTIFY_REMOTE_DOWNLEVEL_SECURITY;
  807. return FALSE;
  808. }
  809. }
  810. return TRUE;
  811. }
  812. void ProcessX224DisconnectPDU(PSocket pSocket, PUChar CP_ptr, UINT CP_length, ULONG *pNotify)
  813. {
  814. UChar length;
  815. BOOL bSecurityInfoFound = FALSE;
  816. PSecurityContext pSC = pSocket->pSC;
  817. /* This structure must be accessed using byte-alignment */
  818. #pragma pack(1)
  819. X224_VARIABLE_INFO *pX224VarInfo;
  820. /* return to normal alignment */
  821. #pragma pack()
  822. while (CP_length > 0) {
  823. pX224VarInfo = (X224_VARIABLE_INFO *) CP_ptr;
  824. if ( 0xe0 == pX224VarInfo->InfoType) {
  825. LPVOID pdecoding_buf = NULL;
  826. UINT decoding_len = 0;
  827. LPBYTE pbEncoded_data = CP_ptr + sizeof(X224_VARIABLE_INFO);
  828. if ( g_CNPCoder->Decode (pbEncoded_data,
  829. pX224VarInfo->InfoSize,
  830. CNPPDU_PDU, PACKED_ENCODING_RULES,
  831. (LPVOID *) &pdecoding_buf, &decoding_len))
  832. {
  833. #pragma pack(1)
  834. CNPPDU *pCnp_pdu;
  835. /* return to normal alignment */
  836. #pragma pack()
  837. pCnp_pdu = (CNPPDU *) pdecoding_buf;
  838. if (disconnectRequest_chosen == pCnp_pdu->choice)
  839. {
  840. switch (pCnp_pdu->u.disconnectRequest.disconnectReason.choice)
  841. {
  842. case securityDenied_chosen:
  843. *pNotify = TPRT_NOTIFY_REMOTE_REQUIRE_SECURITY;
  844. break;
  845. default:
  846. *pNotify = TPRT_NOTIFY_OTHER_REASON;
  847. break;
  848. }
  849. }
  850. }
  851. g_CNPCoder->FreeDecoded(decoding_len, pdecoding_buf);
  852. }
  853. length = pX224VarInfo->InfoSize + sizeof(X224_VARIABLE_INFO);
  854. CP_ptr += length;
  855. //x5:223196 - fix AV when invalid PDU is processed
  856. if(CP_length < length)
  857. {
  858. CP_length = 0;
  859. *pNotify = TPRT_NOTIFY_INCOMPATIBLE_T120_TPDU;
  860. break;
  861. }
  862. CP_length -= length;
  863. }
  864. }
  865. /*
  866. * void DisconnectRequest (TransportConnection XprtConn)
  867. *
  868. * Functional Description:
  869. * This function closes the socket and deletes its connection node.
  870. */
  871. void DisconnectRequest (TransportConnection XprtConn,
  872. ULONG ulNotify)
  873. {
  874. PSocket pSocket;
  875. TRACE_OUT(("DisconnectRequest"));
  876. /* If the transport connection handle is not registered, return error */
  877. if (NULL != (pSocket = g_pSocketList->FindByTransportConnection(XprtConn, TRUE)))
  878. {
  879. // LONCHANC: cannot do Remove in the above line because PurgeRequest() uses it again.
  880. ::PurgeRequest(XprtConn);
  881. // SendStatusMessage (pSocket -> Remote_Address, TSTATE_NOT_CONNECTED, IDS_NULL_STRING);
  882. if (IS_PLUGGABLE_PSTN(XprtConn))
  883. {
  884. CPluggableConnection *p = ::GetPluggableConnection(XprtConn.nLogicalHandle);
  885. if (NULL != p)
  886. {
  887. p->TDisconnectRequest();
  888. }
  889. }
  890. /* Free the structures and close the socket */
  891. TransportConnection XprtConn2 = XprtConn;
  892. if (IS_SOCKET(XprtConn2))
  893. {
  894. XprtConn2.nLogicalHandle = INVALID_SOCKET;
  895. }
  896. ::freeSocket(pSocket, XprtConn2);
  897. // Free up QoS resources if this disconnect was the
  898. // last connected socket.
  899. MaybeReleaseQoSResources();
  900. // Notify the user
  901. if (TPRT_NOTIFY_NONE != ulNotify && g_Transport)
  902. {
  903. TRACE_OUT (("TCP Callback: g_Transport->DisconnectIndication (%d, %d)", XprtConn.eType, XprtConn.nLogicalHandle));
  904. /* We issue a callback to the user to notify him of the message */
  905. g_Transport->DisconnectIndication(XprtConn, ulNotify);
  906. }
  907. }
  908. else
  909. {
  910. WARNING_OUT(("DisconnectRequest: logical handle (%d, %d) not found",
  911. XprtConn.eType, XprtConn.nLogicalHandle));
  912. }
  913. ::OnProtocolControl(XprtConn, PLUGXPRT_DISCONNECTED);
  914. }
  915. typedef enum {
  916. RECVRET_CONTINUE = 0,
  917. RECVRET_NON_FATAL_ERROR,
  918. RECVRET_DISCONNECT,
  919. RECVRET_NO_PLUGGABLE_CONNECTION,
  920. } RecvReturn;
  921. /* RecvReturn Call_recv (PSocket pSocket)
  922. *
  923. * Functional Description:
  924. * This function calls recv once and checks for errors coming from the
  925. * recv call. It knows about the socket's state from the "pSocket" argument
  926. * and uses this info to create the arguments for the recv call.
  927. *
  928. * Return value:
  929. * Continue, if everything went ok and we have new data
  930. * Non_Fatal_Error, if no real error has happenned, but we did not recv all data we asked for
  931. * Disconnect, if a real error has occurred, or the other side has disconnected.
  932. */
  933. RecvReturn Call_recv (PSocket pSocket)
  934. {
  935. PUChar buffer;
  936. int length;
  937. int bytes_received;
  938. BOOL bAllocationOK;
  939. RecvReturn rrCode = RECVRET_NON_FATAL_ERROR;
  940. PLUGXPRT_RESULT plug_rc = PLUGXPRT_RESULT_SUCCESSFUL;
  941. TRACE_OUT(("Call_recv"));
  942. if (READ_HEADER != pSocket->Read_State)
  943. {
  944. // Verify packet size is within acceptable limits (64K)
  945. ASSERT((0 < pSocket->X224_Length) && (pSocket->X224_Length <= 65536));
  946. if((pSocket->X224_Length <= 0) || (65536 < pSocket->X224_Length))
  947. {
  948. rrCode = RECVRET_DISCONNECT;
  949. goto ExitLabel;
  950. }
  951. // Compute how much data we have to read from this X.224 pkt.
  952. length = pSocket->X224_Length - sizeof(X224_DATA_PACKET);
  953. // Space allocation
  954. if (! pSocket->bSpaceAllocated)
  955. {
  956. // We need to allocate the space for the recv call.
  957. if (NULL == pSocket->Data_Indication_Buffer)
  958. {
  959. DBG_SAVE_FILE_LINE
  960. pSocket->Data_Memory = AllocateMemory (
  961. NULL, pSocket->X224_Length,
  962. ((READ_DATA == pSocket->Read_State) ?
  963. RECV_PRIORITY : HIGHEST_PRIORITY));
  964. // Leave space for the X.224 header in the newly allocated data buffer
  965. pSocket->Data_Indication_Length = sizeof (X224_DATA_PACKET);
  966. bAllocationOK = (pSocket->Data_Memory != NULL);
  967. }
  968. else
  969. {
  970. // This is an MCS PDU broken up in many X.224 packets.
  971. ASSERT (READ_DATA == pSocket->Read_State);
  972. bAllocationOK = ReAllocateMemory (&(pSocket->Data_Memory), length);
  973. }
  974. // Check whether the allocations were successful.
  975. if (bAllocationOK)
  976. {
  977. pSocket->bSpaceAllocated = TRUE;
  978. pSocket->Data_Indication_Buffer = pSocket->Data_Memory->GetPointer();
  979. /*
  980. * If this is an X.224 CONNECT_REQUEST or CONNECT_CONFIRM packet,
  981. * we need to copy the first 7 bytes into the buffer for the whole
  982. * packet.
  983. */
  984. if (READ_DATA != pSocket->Read_State)
  985. {
  986. memcpy ((void *) pSocket->Data_Indication_Buffer,
  987. (void *) &(pSocket->X224_Header),
  988. sizeof(X224_DATA_PACKET));
  989. }
  990. }
  991. else
  992. {
  993. /*
  994. * We will retry the operation later.
  995. */
  996. WARNING_OUT (("Call_recv: Buffer allocation failed."));
  997. g_pMCSController->HandleTransportWaitUpdateIndication(TRUE);
  998. goto ExitLabel;
  999. }
  1000. }
  1001. buffer = pSocket->Data_Indication_Buffer + pSocket->Data_Indication_Length;
  1002. }
  1003. else
  1004. {
  1005. buffer = (PUChar) &(pSocket->X224_Header);
  1006. length = sizeof(X224_DATA_PACKET);
  1007. }
  1008. // Adjust "buffer" and "length" for data already read from the current X.224 pkt.
  1009. buffer += pSocket->Current_Length;
  1010. length -= pSocket->Current_Length;
  1011. ASSERT (length > 0);
  1012. if (IS_SOCKET(pSocket->XprtConn))
  1013. {
  1014. // Issue the recv call.
  1015. bytes_received = recv (pSocket->XprtConn.nLogicalHandle, (char *) buffer, length, 0);
  1016. }
  1017. else
  1018. {
  1019. bytes_received = ::X224Recv(pSocket, buffer, length, &plug_rc);
  1020. }
  1021. if (bytes_received == length)
  1022. {
  1023. TRACE_OUT (("Call_recv: Received %d bytes on socket (%d, %d).", bytes_received,
  1024. pSocket->XprtConn.eType, pSocket->XprtConn.nLogicalHandle));
  1025. // We have received the whole X.224 packet.
  1026. if (READ_HEADER != pSocket->Read_State)
  1027. {
  1028. pSocket->Data_Indication_Length += pSocket->X224_Length - sizeof(X224_DATA_PACKET);
  1029. }
  1030. // Reset the current length variable for the next Call_recv().
  1031. pSocket->Current_Length = 0;
  1032. rrCode = RECVRET_CONTINUE;
  1033. }
  1034. // Handle errors
  1035. else
  1036. if (bytes_received == SOCKET_ERROR)
  1037. {
  1038. if (IS_SOCKET(pSocket->XprtConn))
  1039. {
  1040. if(WSAGetLastError() == WSAEWOULDBLOCK)
  1041. {
  1042. TRACE_OUT(("Call_recv: recv blocked on socket (%d, %d).",
  1043. pSocket->XprtConn.eType, pSocket->XprtConn.nLogicalHandle));
  1044. }
  1045. else
  1046. {
  1047. /* If the error is not WOULD BLOCK, we have a real error. */
  1048. WARNING_OUT (("Call_recv: Error %d on recv. Socket: (%d, %d). Disconnecting...",
  1049. WSAGetLastError(), pSocket->XprtConn.eType, pSocket->XprtConn.nLogicalHandle));
  1050. rrCode = RECVRET_DISCONNECT;
  1051. }
  1052. }
  1053. else
  1054. {
  1055. if (PLUGXPRT_RESULT_SUCCESSFUL == plug_rc)
  1056. {
  1057. // do nothing, treat it as WSAEWOULDBLOCK
  1058. }
  1059. else
  1060. {
  1061. /* If the error is not WOULD BLOCK, we have a real error. */
  1062. WARNING_OUT (("Call_recv: Error %d on recv. Socket: (%d, %d). Disconnecting...",
  1063. WSAGetLastError(), pSocket->XprtConn.eType, pSocket->XprtConn.nLogicalHandle));
  1064. rrCode = RECVRET_DISCONNECT;
  1065. }
  1066. }
  1067. }
  1068. else
  1069. if (bytes_received > 0)
  1070. {
  1071. TRACE_OUT(("Call_recv: Received %d bytes out of %d bytes requested on socket (%d, %d).",
  1072. bytes_received, length, pSocket->XprtConn.eType, pSocket->XprtConn.nLogicalHandle));
  1073. // We received only part of what we wanted. We retry later.
  1074. pSocket->Current_Length += bytes_received;
  1075. }
  1076. else
  1077. {
  1078. WARNING_OUT(("Call_recv: Socket (%d, %d) has been gracefully closed.",
  1079. pSocket->XprtConn.eType, pSocket->XprtConn.nLogicalHandle));
  1080. rrCode = RECVRET_DISCONNECT;
  1081. }
  1082. ExitLabel:
  1083. return rrCode;
  1084. }
  1085. int X224Recv(PSocket pSocket, LPBYTE buffer, int length, PLUGXPRT_RESULT *plug_rc)
  1086. {
  1087. TRACE_OUT(("X224Recv"));
  1088. if (IS_PLUGGABLE_X224(pSocket->XprtConn))
  1089. {
  1090. return ::SubmitPluggableRead(pSocket, buffer, length, plug_rc);
  1091. }
  1092. if (IS_PLUGGABLE_PSTN(pSocket->XprtConn))
  1093. {
  1094. return Q922Recv(pSocket, buffer, length, plug_rc);
  1095. }
  1096. ERROR_OUT(("X224Recv: invalid plugable type (%d, %d)",
  1097. pSocket->XprtConn.eType, pSocket->XprtConn.nLogicalHandle));
  1098. return SOCKET_ERROR;
  1099. }
  1100. int Q922Recv(PSocket pSocket, LPBYTE buffer, int length, PLUGXPRT_RESULT *plug_rc)
  1101. {
  1102. ERROR_OUT(("Q922Recv: NYI (%d, %d)",
  1103. pSocket->XprtConn.eType, pSocket->XprtConn.nLogicalHandle));
  1104. return SOCKET_ERROR;
  1105. }
  1106. typedef enum {
  1107. FreeX224AndExit,
  1108. ErrorExit,
  1109. ImmediateExit
  1110. } ExitWay;
  1111. /*
  1112. * void ReadRequest ( TransportConnection )
  1113. *
  1114. * Functional Description:
  1115. * This function will attempt to read and process a full X.224 packet.
  1116. * However, it may only be able to read part of a packet or fail to
  1117. * process it at this time. In this case, it must keep enough state
  1118. * info for the next entrance into this function, to be able to handle
  1119. * the partly-received or unprocessed X.224 packet.
  1120. */
  1121. void ReadRequest (TransportConnection XprtConn)
  1122. {
  1123. PSocket pSocket;
  1124. ExitWay ew = ImmediateExit;
  1125. RecvReturn rrCode;
  1126. ULONG ulNotify = TPRT_NOTIFY_OTHER_REASON;
  1127. TRACE_OUT(("ReadRequest"));
  1128. if (IS_PLUGGABLE_PSTN(XprtConn))
  1129. {
  1130. ERROR_OUT(("ReadRequest: PSTN should not be here"));
  1131. return;
  1132. }
  1133. /* If the transport connection handle is not registered, return */
  1134. if (NULL != (pSocket = g_pSocketList->FindByTransportConnection(XprtConn)))
  1135. {
  1136. if (pSocket->State != WAITING_FOR_CONNECTION)
  1137. {
  1138. PSecurityContext pSC = pSocket->pSC;
  1139. /*
  1140. * If we haven't read the header of the incoming packet yet,
  1141. * we need to read it into the header space
  1142. */
  1143. if (READ_HEADER == pSocket->Read_State)
  1144. {
  1145. rrCode = Call_recv (pSocket);
  1146. if (RECVRET_CONTINUE == rrCode)
  1147. {
  1148. // We need to allocate the space for the rest of the X.224 packet.
  1149. pSocket->bSpaceAllocated = FALSE;
  1150. // Find the length of the X.224 packet.
  1151. pSocket->X224_Length = (pSocket->X224_Header.rfc.msbPacketSize << 8) +
  1152. pSocket->X224_Header.rfc.lsbPacketSize;
  1153. /*
  1154. * We have the whole X.224 header. Compute the next state,
  1155. * based on the packet type.
  1156. */
  1157. switch (pSocket->X224_Header.PacketType)
  1158. {
  1159. case DATA_PACKET:
  1160. pSocket->Read_State = READ_DATA;
  1161. break;
  1162. case CONNECTION_CONFIRM_PACKET:
  1163. if (pSocket->State != X224_CONNECTED)
  1164. {
  1165. pSocket->Read_State = CONNECTION_CONFIRM;
  1166. }
  1167. else
  1168. {
  1169. ERROR_OUT (("ReadRequest: Received X.224 CONNECTION_CONFIRM packet while already connected!! Socket: (%d, %d).",
  1170. XprtConn.eType, XprtConn.nLogicalHandle));
  1171. ew = ErrorExit;
  1172. }
  1173. break;
  1174. case CONNECTION_REQUEST_PACKET:
  1175. // we just received a X224 Connect request
  1176. pSocket->Read_State = CONNECTION_REQUEST;
  1177. ::OnProtocolControl(XprtConn, PLUGXPRT_CONNECTING);
  1178. break;
  1179. case DISCONNECT_REQUEST_PACKET:
  1180. // we just received a X224 Disconnect request
  1181. pSocket->Read_State = DISCONNECT_REQUEST;
  1182. ::OnProtocolControl(XprtConn, PLUGXPRT_DISCONNECTING);
  1183. break;
  1184. default:
  1185. // We have lost sync with the remote side.
  1186. ERROR_OUT (("ReadRequest: Bad X.224 packet on socket (%d, %d). Disconnecting...", XprtConn.eType, XprtConn.nLogicalHandle));
  1187. ew = ErrorExit;
  1188. break;
  1189. }
  1190. }
  1191. else
  1192. if (RECVRET_DISCONNECT == rrCode)
  1193. {
  1194. ew = ErrorExit;
  1195. }
  1196. }
  1197. if ((READ_DATA <= pSocket->Read_State) &&
  1198. (CONNECTION_REQUEST >= pSocket->Read_State))
  1199. {
  1200. rrCode = Call_recv (pSocket);
  1201. if (RECVRET_CONTINUE == rrCode)
  1202. {
  1203. // We now have the whole X.224 packet.
  1204. switch (pSocket->Read_State)
  1205. {
  1206. case READ_DATA:
  1207. // Check whether this is the final X.224 packet
  1208. if (pSocket->X224_Header.FinalPacket & EOT_BIT)
  1209. {
  1210. // If we're waiting for a security data packet we will process
  1211. // this internally without passing it up to the transport
  1212. // client.
  1213. if (NULL != pSC)
  1214. {
  1215. if (pSC->WaitingForPacket())
  1216. {
  1217. TransportSecurityError SecErr;
  1218. SecErr = pSC->AdvanceState((PBYTE) pSocket->Data_Indication_Buffer +
  1219. sizeof(X224_DATA_PACKET),
  1220. pSocket->Data_Indication_Length -
  1221. sizeof(X224_DATA_PACKET));
  1222. if (TPRTSEC_NOERROR != SecErr)
  1223. {
  1224. // Something has gone wrong. Need to disconnect
  1225. delete pSC;
  1226. pSocket->pSC = NULL;
  1227. ulNotify = TPRT_NOTIFY_AUTHENTICATION_FAILED;
  1228. ew = ErrorExit;
  1229. break;
  1230. }
  1231. if (pSC->ContinueNeeded())
  1232. {
  1233. // We need to send out another token
  1234. // bugbug: what should we do if this fails?
  1235. ContinueAuthentication(pSocket);
  1236. }
  1237. if (pSC->StateComplete())
  1238. {
  1239. // We're connected... inform the client
  1240. TRACE_OUT(("deferred g_Transport->ConnectConfirm"));
  1241. g_Transport->ConnectConfirm(XprtConn);
  1242. }
  1243. ew = FreeX224AndExit;
  1244. break;
  1245. }
  1246. // We must decrypt the data (in place)
  1247. TRACE_OUT(("Decrypting received data"));
  1248. if (! pSC->Decrypt(pSocket->Data_Indication_Buffer +
  1249. sizeof(X224_DATA_PACKET),
  1250. pSocket->Data_Indication_Length -
  1251. sizeof(X224_DATA_PACKET)))
  1252. {
  1253. TRACE_OUT(("Sending %d bytes to application",
  1254. pSocket->Data_Indication_Length - sizeof(X224_DATA_PACKET)));
  1255. }
  1256. else
  1257. {
  1258. ERROR_OUT(("Error decrypting packet"));
  1259. ew = ErrorExit;
  1260. break;
  1261. }
  1262. }
  1263. pSocket->Read_State = DATA_READY;
  1264. }
  1265. else
  1266. {
  1267. // This and the next X.224 packets are part of a bigger MCS data PDU.
  1268. ASSERT (NULL == pSC);
  1269. pSocket->Read_State = READ_HEADER;
  1270. }
  1271. break;
  1272. case CONNECTION_CONFIRM:
  1273. {
  1274. TRACE_OUT(("ReadRequest: X224 CONNECTION_CONFIRM_PACKET received"));
  1275. BOOL bCallback = ((NULL == pSC) || (! pSC->ContinueNeeded()));
  1276. // Process the CC packet.
  1277. if (FALSE == ProcessX224ConnectPDU (pSocket,
  1278. pSocket->Data_Indication_Buffer + sizeof(X224_CONNECT),
  1279. pSocket->X224_Length - sizeof (X224_CONNECT), &ulNotify))
  1280. {
  1281. ew = ErrorExit;
  1282. break;
  1283. }
  1284. // Issue the callback if the CC was not on a secure connection
  1285. // Otherwise, we don't notify the transport client yet... still need to
  1286. // exchange security information. TRANSPORT_CONNECT_CONFIRM will
  1287. // be sent when the final security data token is received and
  1288. // processed.
  1289. if (bCallback)
  1290. {
  1291. TRACE_OUT (("TCP Callback: g_Transport->ConnectConfirm (%d, %d)", XprtConn.eType, XprtConn.nLogicalHandle));
  1292. /* We issue a callback to the user to notify him of the message */
  1293. g_Transport->ConnectConfirm(XprtConn);
  1294. }
  1295. pSocket->State = X224_CONNECTED;
  1296. ::OnProtocolControl(XprtConn, PLUGXPRT_CONNECTED);
  1297. ew = FreeX224AndExit;
  1298. }
  1299. break;
  1300. case CONNECTION_REQUEST:
  1301. {
  1302. UINT remote;
  1303. /* This structure must be accessed using byte-alignment */
  1304. #pragma pack(1)
  1305. X224_CONNECT *pConnectRequest;
  1306. /* return to normal alignment */
  1307. #pragma pack()
  1308. /* Grab the remote connection ID */
  1309. TRACE_OUT (("ReadRequest: X224 CONNECTION_REQUEST_PACKET received"));
  1310. pConnectRequest = (X224_CONNECT *) pSocket->Data_Indication_Buffer;
  1311. remote = ((unsigned int) pConnectRequest->conn.msbSrc) << 8;
  1312. remote |= pConnectRequest->conn.lsbSrc;
  1313. if (FALSE == ProcessX224ConnectPDU (pSocket, (PUChar) (pConnectRequest + 1),
  1314. pSocket->X224_Length - sizeof (X224_CONNECT), &ulNotify))
  1315. {
  1316. ew = ErrorExit;
  1317. break;
  1318. }
  1319. if (::SendX224ConnectConfirm(pSocket, remote))
  1320. {
  1321. // success
  1322. if (IS_PLUGGABLE(pSocket->XprtConn))
  1323. {
  1324. pSocket->State = SOCKET_CONNECTED;
  1325. g_Transport->ConnectIndication(XprtConn);
  1326. ASSERT(X224_CONNECTED == pSocket->State);
  1327. }
  1328. ::OnProtocolControl(XprtConn, PLUGXPRT_CONNECTED);
  1329. ew = FreeX224AndExit;
  1330. }
  1331. else
  1332. {
  1333. if (pSocket->fExtendedX224)
  1334. {
  1335. ::SendX224DisconnectRequest(pSocket, remote, securityDenied_chosen);
  1336. }
  1337. ew = ErrorExit;
  1338. }
  1339. }
  1340. break;
  1341. case DISCONNECT_REQUEST:
  1342. {
  1343. UINT remote;
  1344. X224_DR_FIXED *pX224_DR_fixed;
  1345. TRACE_OUT(("ReadRequest: X224 DISCONNECT_REQUEST_PACKET received"));
  1346. pX224_DR_fixed = (X224_DR_FIXED *) pSocket->Data_Indication_Buffer;
  1347. remote = ((unsigned int) pX224_DR_fixed->disconn.msbSrc) << 8;
  1348. remote |= pX224_DR_fixed->disconn.lsbSrc;
  1349. ProcessX224DisconnectPDU(pSocket, pSocket->Data_Indication_Buffer + sizeof(X224_DR_FIXED),
  1350. pSocket->X224_Length - sizeof(X224_DR_FIXED), &ulNotify);
  1351. ew = ErrorExit;
  1352. }
  1353. break;
  1354. }
  1355. }
  1356. else if (RECVRET_DISCONNECT == rrCode)
  1357. {
  1358. ew = ErrorExit;
  1359. }
  1360. }
  1361. if (DATA_READY == pSocket->Read_State)
  1362. {
  1363. TransportData transport_data;
  1364. // Fill in the callback structure.
  1365. transport_data.transport_connection = XprtConn;
  1366. transport_data.user_data = pSocket->Data_Indication_Buffer;
  1367. transport_data.user_data_length = pSocket->Data_Indication_Length;
  1368. transport_data.memory = pSocket->Data_Memory;
  1369. /*
  1370. * If there is an incoming security context associated with this
  1371. * socket, we must adjust pointer by header and overall size by header and
  1372. * trailer.
  1373. */
  1374. if (NULL != pSC)
  1375. {
  1376. transport_data.user_data += pSC->GetStreamHeaderSize();
  1377. transport_data.user_data_length -= (pSC->GetStreamHeaderSize() +
  1378. pSC->GetStreamTrailerSize());
  1379. }
  1380. if (TRANSPORT_NO_ERROR == g_Transport->DataIndication(&transport_data))
  1381. {
  1382. TRACE_OUT (("ReadRequest: %d bytes were accepted from socket (%d, %d)",
  1383. transport_data.user_data_length, XprtConn.eType, XprtConn.nLogicalHandle));
  1384. // Prepare for the next X.224 packet
  1385. pSocket->Read_State = READ_HEADER;
  1386. pSocket->Data_Indication_Buffer = NULL;
  1387. pSocket->Data_Memory = NULL;
  1388. }
  1389. else
  1390. {
  1391. WARNING_OUT(("ReadRequest: Error on g_Transport->DataIndication from socket (%d, %d)",
  1392. XprtConn.eType, XprtConn.nLogicalHandle));
  1393. }
  1394. }
  1395. }
  1396. else
  1397. {
  1398. WARNING_OUT (("ReadRequest: socket (%d, %d) is in WAITING_FOR_CONNECTION state.", XprtConn.eType, XprtConn.nLogicalHandle));
  1399. }
  1400. }
  1401. else
  1402. {
  1403. WARNING_OUT (("ReadRequest: socket (%d, %d) can not be found.", XprtConn.eType, XprtConn.nLogicalHandle));
  1404. }
  1405. switch (ew)
  1406. {
  1407. case FreeX224AndExit:
  1408. if (NULL != pSocket)
  1409. {
  1410. // Free the buffers we have allocated.
  1411. pSocket->FreeTransportBuffer();
  1412. // Prepare for the next X.224 packet
  1413. pSocket->Read_State = READ_HEADER;
  1414. }
  1415. break;
  1416. case ErrorExit:
  1417. // We get here only if we need to disconnect the socket (because of an error)
  1418. ASSERT(TPRT_NOTIFY_NONE != ulNotify);
  1419. ::DisconnectRequest(XprtConn, ulNotify);
  1420. break;
  1421. }
  1422. if (NULL != pSocket)
  1423. {
  1424. pSocket->Release(); // offset the previous AddRef.
  1425. }
  1426. }
  1427. /*
  1428. * TransportError FlushSendBuffer ( PSocket pSocket )
  1429. *
  1430. * Functional Description:
  1431. * This function sends any pending data through the transport.
  1432. */
  1433. TransportError FlushSendBuffer(PSocket pSocket, LPBYTE buffer, UINT length)
  1434. {
  1435. int bytes_sent = SOCKET_ERROR;
  1436. PLUGXPRT_RESULT plug_rc = PLUGXPRT_RESULT_SUCCESSFUL;
  1437. TRACE_OUT(("FlushSendBuffer"));
  1438. /* send the data */
  1439. if (IS_SOCKET(pSocket->XprtConn))
  1440. {
  1441. bytes_sent = ::send(pSocket->XprtConn.nLogicalHandle, (PChar) buffer,
  1442. (int) length, 0);
  1443. }
  1444. else
  1445. if (IS_PLUGGABLE_X224(pSocket->XprtConn))
  1446. {
  1447. bytes_sent = ::SubmitPluggableWrite(pSocket, buffer, length, &plug_rc);
  1448. }
  1449. else
  1450. if (IS_PLUGGABLE_PSTN(pSocket->XprtConn))
  1451. {
  1452. CPluggableConnection *p = ::GetPluggableConnection(pSocket);
  1453. if (NULL != p)
  1454. {
  1455. bytes_sent = p->TDataRequest(buffer, length, &plug_rc);
  1456. }
  1457. else
  1458. {
  1459. plug_rc = PLUGXPRT_RESULT_WRITE_FAILED;
  1460. }
  1461. }
  1462. if (bytes_sent == SOCKET_ERROR)
  1463. {
  1464. if (IS_SOCKET(pSocket->XprtConn))
  1465. {
  1466. /* If the error is not WOULD BLOCK, it is a real error! */
  1467. if (::WSAGetLastError() != WSAEWOULDBLOCK)
  1468. {
  1469. WARNING_OUT (("FlushSendBuffer: Error %d on write", ::WSAGetLastError()));
  1470. /* Notify the owner of the broken connection */
  1471. WARNING_OUT (("FlushSendBuffer: Sending up DISCONNECT_INDICATION"));
  1472. // SendStatusMessage (pSocket -> Remote_Address, TSTATE_REMOVED, IDS_NULL_STRING);
  1473. ::DisconnectRequest(pSocket->XprtConn, TPRT_NOTIFY_OTHER_REASON);
  1474. return (TRANSPORT_WRITE_QUEUE_FULL);
  1475. }
  1476. }
  1477. else
  1478. {
  1479. // do nothing if it is WSAEWOULDBLOCK
  1480. if (PLUGXPRT_RESULT_SUCCESSFUL != plug_rc)
  1481. {
  1482. /* Notify the owner of the broken connection */
  1483. WARNING_OUT (("FlushSendBuffer: Sending up DISCONNECT_INDICATION"));
  1484. // SendStatusMessage (pSocket -> Remote_Address, TSTATE_REMOVED, IDS_NULL_STRING);
  1485. ::DisconnectRequest(pSocket->XprtConn, TPRT_NOTIFY_OTHER_REASON);
  1486. return (TRANSPORT_WRITE_QUEUE_FULL);
  1487. }
  1488. }
  1489. bytes_sent = 0;
  1490. }
  1491. /* If the transport layer did not accept the data, its write buffers are full */
  1492. if (bytes_sent != (int) length)
  1493. {
  1494. ASSERT (bytes_sent == 0);
  1495. TRACE_OUT(("FlushSendBuffer: returning TRANSPORT_WRITE_QUEUE_FULL"));
  1496. return (TRANSPORT_WRITE_QUEUE_FULL);
  1497. }
  1498. // Increment our counter of bytes sent since last QoS notification
  1499. if (bytes_sent)
  1500. {
  1501. QoSLock();
  1502. g_dwSentSinceLastQoS += bytes_sent;
  1503. QoSUnlock();
  1504. }
  1505. TRACE_OUT (("FlushSendBuffer: %d bytes sent on Socket (%d, %d).",
  1506. length, pSocket->XprtConn.eType, pSocket->XprtConn.nLogicalHandle));
  1507. return (TRANSPORT_NO_ERROR);
  1508. }
  1509. /*
  1510. * SegmentX224Data
  1511. *
  1512. * This function segments outgoing data into X.224 packets of the appropriate size.
  1513. * It should not be called in a NM to NM call or in a call when we have negotiated an
  1514. * X.224 max PDU size of at least the size of a max MCS PDU. NM attempts to negotiate
  1515. * X.224 sizes of 8K, but will accept anything the other side proposes.
  1516. * This function does memcpy's so it will slow us down sending data.
  1517. *
  1518. * The 2 buffers specified by "ptr1" and "ptr2" and their lengths are used to create
  1519. * one stream of X.224 bytes. The function will return TRANSPORT_WRITE_QUEUE_FULL if
  1520. * it fails to allocate the necessary amount of memory.
  1521. */
  1522. TransportError SegmentX224Data (PSocket pSocket,
  1523. LPBYTE *pPtr1, UINT *pLength1,
  1524. LPBYTE Ptr2, UINT Length2)
  1525. {
  1526. TransportError TransError;
  1527. UINT length;
  1528. LPBYTE ptr1 = *pPtr1 + sizeof (X224_DATA_PACKET);
  1529. UINT length1 = *pLength1 - sizeof (X224_DATA_PACKET);
  1530. LPBYTE ptr;
  1531. UINT max_pdu_length = pSocket->Max_Packet_Length;
  1532. X224_DATA_PACKET l_X224Header = {3, 0, (UChar) (max_pdu_length >> 8), (UChar) (max_pdu_length & 0xFF),
  1533. 2, DATA_PACKET, 0};
  1534. UINT last_length;
  1535. /* This structure must be accessed using byte-alignment */
  1536. #pragma pack(1)
  1537. X224_DATA_PACKET *pX224Data;
  1538. /* return to normal alignment */
  1539. #pragma pack()
  1540. ASSERT(! IS_PLUGGABLE_PSTN(pSocket->XprtConn));
  1541. // Calculate how much space we need.
  1542. length = *pLength1 + Length2;
  1543. ASSERT (pSocket->Max_Packet_Length < length);
  1544. ASSERT (pSocket->Max_Packet_Length > sizeof(X224_DATA_PACKET));
  1545. max_pdu_length -= sizeof (X224_DATA_PACKET);
  1546. /*
  1547. * Calculate the space we need to allocate. Notice that the data already
  1548. * contains one X.224 header.
  1549. */
  1550. length += (length / max_pdu_length) * sizeof (X224_DATA_PACKET);
  1551. *pPtr1 = Allocate (length);
  1552. if (*pPtr1 != NULL) {
  1553. TransError = TRANSPORT_NO_ERROR;
  1554. ptr = *pPtr1;
  1555. // Go through the 1st buffer.
  1556. while (length1 > 0) {
  1557. // Copy the X.224 header.
  1558. memcpy (ptr, &l_X224Header, sizeof(X224_DATA_PACKET));
  1559. pX224Data = (X224_DATA_PACKET *) ptr;
  1560. ptr += sizeof (X224_DATA_PACKET);
  1561. // Copy data
  1562. length = ((max_pdu_length > length1) ? length1 : max_pdu_length);
  1563. memcpy (ptr, ptr1, length);
  1564. last_length = length;
  1565. // Advance pointers
  1566. ptr1 += length;
  1567. ptr += length;
  1568. length1 -= length;
  1569. }
  1570. // If there is space in the current X.224 PDU, we need to use it.
  1571. length = max_pdu_length - length;
  1572. if (length > 0 && Length2 > 0) {
  1573. if (length > Length2)
  1574. length = Length2;
  1575. memcpy (ptr, Ptr2, length);
  1576. last_length += length;
  1577. Ptr2 += length;
  1578. ptr += length;
  1579. Length2 -= length;
  1580. }
  1581. // Go through the 2nd buffer.
  1582. while (Length2 > 0) {
  1583. // Copy the X.224 header.
  1584. memcpy (ptr, &l_X224Header, sizeof(X224_DATA_PACKET));
  1585. pX224Data = (X224_DATA_PACKET *) ptr;
  1586. ptr += sizeof (X224_DATA_PACKET);
  1587. // Copy data
  1588. length = ((max_pdu_length > Length2) ? Length2 : max_pdu_length);
  1589. memcpy (ptr, Ptr2, length);
  1590. last_length = length;
  1591. // Advance pointers
  1592. Ptr2 += length;
  1593. ptr += length;
  1594. Length2 -= length;
  1595. }
  1596. // Prepare for return
  1597. *pLength1 = (UINT)(ptr - *pPtr1);
  1598. // Set the last X.224 header
  1599. last_length += sizeof(X224_DATA_PACKET);
  1600. pX224Data->FinalPacket = EOT_BIT;
  1601. pX224Data->rfc.msbPacketSize = (UChar) (last_length >> 8);
  1602. pX224Data->rfc.lsbPacketSize = (UChar) (last_length & 0xFF);
  1603. }
  1604. else {
  1605. ERROR_OUT (("SegmentX224Data: Failed to allocate memory of length %d.", length));
  1606. TransError = TRANSPORT_WRITE_QUEUE_FULL;
  1607. }
  1608. return TransError;
  1609. }
  1610. /*
  1611. * SendSecureData
  1612. *
  1613. * This function segments secure data into X.224 packets, if needed, and flushes them through
  1614. * the transport. "pBuf" and "cbBuf" provide the encrypted data buffer and length.
  1615. */
  1616. TransportError SendSecureData (PSocket pSocket, LPBYTE pBuf, UINT cbBuf)
  1617. {
  1618. TransportError TransError;
  1619. LPBYTE pBuf_Copy = pBuf;
  1620. UINT cbBuf_Copy = cbBuf;
  1621. // Do we need to segment the data into X.224 packets?
  1622. if (pSocket->Max_Packet_Length >= cbBuf) {
  1623. TransError = TRANSPORT_NO_ERROR;
  1624. }
  1625. else {
  1626. TransError = SegmentX224Data (pSocket, &pBuf, &cbBuf, NULL, 0);
  1627. }
  1628. // Flush the data, if everything OK so far.
  1629. if (TRANSPORT_NO_ERROR == TransError)
  1630. TransError = FlushSendBuffer (pSocket, pBuf, cbBuf);
  1631. // If we segmented the data, we need to free the segmented buffer.
  1632. if (pBuf != pBuf_Copy)
  1633. Free(pBuf);
  1634. // If there are errors, we need to store the decrypted data for the next time, so don't free it.
  1635. if (TRANSPORT_NO_ERROR == TransError) {
  1636. LocalFree(pBuf_Copy);
  1637. }
  1638. return TransError;
  1639. }
  1640. /*
  1641. * TransportError DataRequest ( TransportConnection XprtConn,
  1642. * PSimplePacket packet)
  1643. *
  1644. * Functional Description:
  1645. * This function is used to send a data packet to the remote site.
  1646. * If the user_data_length is zero, and we have no pending data,
  1647. * it sends a keep-alive (zero-length) packet.
  1648. */
  1649. TransportError DataRequest (TransportConnection XprtConn,
  1650. PSimplePacket packet)
  1651. {
  1652. PSocket pSocket;
  1653. LPBYTE ptr1, ptr2;
  1654. UINT length1, length2;
  1655. TransportError TransError = TRANSPORT_NO_ERROR;
  1656. TRACE_OUT(("DataRequest: packet=0x%x", packet));
  1657. if (NULL != (pSocket = g_pSocketList->FindByTransportConnection(XprtConn)))
  1658. {
  1659. // First, we need to handle the retry operations.
  1660. if (NULL != pSocket->pSC) {
  1661. LPBYTE lpBuf;
  1662. /*
  1663. * Check to see whether we have already encrypted, but not sent
  1664. * the last piece of data.
  1665. */
  1666. lpBuf = pSocket->Retry_Info.sbiBufferInfo.lpBuffer;
  1667. if (NULL != lpBuf) {
  1668. TransError = SendSecureData (pSocket, lpBuf,
  1669. pSocket->Retry_Info.sbiBufferInfo.uiLength);
  1670. if (TransError == TRANSPORT_NO_ERROR) {
  1671. TRACE_OUT(("DataRequest: Sent previously-encrypted piece of data."));
  1672. pSocket->Retry_Info.sbiBufferInfo.lpBuffer = NULL;
  1673. }
  1674. }
  1675. }
  1676. else {
  1677. PDataPacket pdpPacket = pSocket->Retry_Info.pUnfinishedPacket;
  1678. // Check to see whether we have half-sent the last packet.
  1679. if (NULL != pdpPacket) {
  1680. /*
  1681. * We need to send the rest of the unfinished packet,
  1682. * before we can go on. The 1st part of the packet
  1683. * must have already been sent.
  1684. */
  1685. // The packet's encoded data must be in 2 buffers.
  1686. ASSERT (TRUE == pdpPacket->IsEncodedDataBroken());
  1687. TransError = FlushSendBuffer (pSocket, pdpPacket->GetUserData(),
  1688. pdpPacket->GetUserDataLength());
  1689. if (TransError == TRANSPORT_NO_ERROR) {
  1690. pdpPacket->Unlock();
  1691. TRACE_OUT(("DataRequest: 2nd part of data packet was sent out in separate request"));
  1692. pSocket->Retry_Info.pUnfinishedPacket = NULL;
  1693. }
  1694. }
  1695. }
  1696. if ((TransError == TRANSPORT_NO_ERROR) && (packet != NULL)) {
  1697. // Now, let's try to send this new packet.
  1698. ptr1 = packet->GetEncodedData();
  1699. length1 = packet->GetEncodedDataLength();
  1700. /*
  1701. * We need to find out whether the packet to send is a
  1702. * DataPacket or a Packet object. If it's a DataPacket, the
  1703. * encoded data may not be contiguous (may be broken in 2 parts)
  1704. */
  1705. if ((packet->IsDataPacket()) &&
  1706. ((PDataPacket) packet)->IsEncodedDataBroken()) {
  1707. // the data to send is broken into 2 parts.
  1708. ptr2 = ((PDataPacket) packet)->GetUserData();
  1709. length2 = ((PDataPacket) packet)->GetUserDataLength();
  1710. }
  1711. else {
  1712. // the data to send is contiguous.
  1713. ptr2 = NULL;
  1714. length2 = 0;
  1715. }
  1716. if (NULL != pSocket->pSC) {
  1717. LPBYTE pBuf;
  1718. UINT cbBuf;
  1719. TRACE_OUT(("Encrypting %d bytes of outgoing data",
  1720. (length1 + length2) - sizeof(X224_DATA_PACKET)));
  1721. if (!pSocket->pSC->Encrypt(ptr1 + sizeof(X224_DATA_PACKET),
  1722. length1 - sizeof(X224_DATA_PACKET),
  1723. ptr2, length2, &pBuf, &cbBuf))
  1724. {
  1725. ASSERT (TransError == TRANSPORT_NO_ERROR);
  1726. TransError = SendSecureData (pSocket, pBuf, cbBuf);
  1727. if (TRANSPORT_NO_ERROR != TransError) {
  1728. TRACE_OUT(("DataRequest: Failed to send encrypted data. Keeping buffer for retry."));
  1729. pSocket->Retry_Info.sbiBufferInfo.lpBuffer = pBuf;
  1730. pSocket->Retry_Info.sbiBufferInfo.uiLength = cbBuf;
  1731. // The caller needs to remove the packet from its queue.
  1732. TransError = TRANSPORT_NO_ERROR;
  1733. }
  1734. }
  1735. else
  1736. {
  1737. WARNING_OUT (("DataRequest: Encryption failed. Disconnecting..."));
  1738. ::DisconnectRequest(pSocket->XprtConn, TPRT_NOTIFY_OTHER_REASON);
  1739. TransError = TRANSPORT_MEMORY_FAILURE;
  1740. }
  1741. }
  1742. else {
  1743. BOOL bNeedToFree = FALSE;
  1744. // Do we need to segment the data into X.224 packets?
  1745. if (pSocket->Max_Packet_Length >= length1 + length2)
  1746. ;
  1747. else {
  1748. TransError = SegmentX224Data (pSocket, &ptr1, &length1, ptr2, length2);
  1749. if (TRANSPORT_NO_ERROR == TransError) {
  1750. // The data is now contiguous
  1751. ptr2 = NULL;
  1752. bNeedToFree = TRUE;
  1753. }
  1754. }
  1755. // Flush the data, if everything OK so far.
  1756. if (TRANSPORT_NO_ERROR == TransError)
  1757. TransError = FlushSendBuffer (pSocket, ptr1, length1);
  1758. // Free the temporary X.224 buffer if we need to.
  1759. if (bNeedToFree)
  1760. Free(ptr1);
  1761. if (TRANSPORT_NO_ERROR == TransError) {
  1762. // If there is more, send it, too.
  1763. if (NULL != ptr2) {
  1764. TransError = FlushSendBuffer (pSocket, ptr2, length2);
  1765. if (TRANSPORT_NO_ERROR != TransError) {
  1766. /*
  1767. * We need to keep the partial packet to send it later.
  1768. * Notice we have already sent a part of this packet.
  1769. */
  1770. ASSERT (pSocket->Retry_Info.pUnfinishedPacket == NULL);
  1771. pSocket->Retry_Info.pUnfinishedPacket = (PDataPacket) packet;
  1772. packet->Lock();
  1773. // Return success.
  1774. TransError = TRANSPORT_NO_ERROR;
  1775. }
  1776. }
  1777. }
  1778. }
  1779. }
  1780. pSocket->Release();
  1781. }
  1782. else {
  1783. TransError = TRANSPORT_NO_SUCH_CONNECTION;
  1784. WARNING_OUT (("DataRequest: Attempt to send to unknown transport connection (%d, %d)",
  1785. XprtConn.eType, XprtConn.nLogicalHandle));
  1786. }
  1787. return TransError;
  1788. }
  1789. /*
  1790. * void PurgeRequest (TransportConnection XprtConn)
  1791. *
  1792. * Functional Description:
  1793. * This function purges the outbound packets for the given transport
  1794. * connection.
  1795. */
  1796. void PurgeRequest (TransportConnection XprtConn)
  1797. {
  1798. PSocket pSocket;
  1799. TRACE_OUT (("In PurgeRequest for transport connection (%d, %d)", XprtConn.eType, XprtConn.nLogicalHandle));
  1800. if (IS_PLUGGABLE_PSTN(XprtConn))
  1801. {
  1802. CPluggableConnection *p = ::GetPluggableConnection(XprtConn.nLogicalHandle);
  1803. if (NULL != p)
  1804. {
  1805. p->TPurgeRequest();
  1806. }
  1807. }
  1808. else
  1809. /* If the logical connection handle is not registered, return error */
  1810. if (NULL != (pSocket = g_pSocketList->FindByTransportConnection(XprtConn)))
  1811. {
  1812. /* Purge the pending data stored in the socket struct */
  1813. if (NULL != pSocket->pSC) {
  1814. if (NULL != pSocket->Retry_Info.sbiBufferInfo.lpBuffer) {
  1815. TRACE_OUT (("PurgeRequest: Purging data packet for secure connection"));
  1816. LocalFree (pSocket->Retry_Info.sbiBufferInfo.lpBuffer);
  1817. pSocket->Retry_Info.sbiBufferInfo.lpBuffer = NULL;
  1818. }
  1819. }
  1820. pSocket->Release();
  1821. }
  1822. }
  1823. /*
  1824. * void EnableReceiver (Void)
  1825. *
  1826. * Functional Description:
  1827. * This function allows packets to be sent to the user application.
  1828. */
  1829. void EnableReceiver (void)
  1830. {
  1831. PSocket pSocket;
  1832. ::EnterCriticalSection(&g_csTransport);
  1833. CSocketList Connection_List_Copy (*g_pSocketList);
  1834. ::LeaveCriticalSection(&g_csTransport);
  1835. TRACE_OUT(("EnableReceiver"));
  1836. if (NULL != g_pLegacyTransport)
  1837. {
  1838. g_pLegacyTransport->TEnableReceiver();
  1839. }
  1840. /* Go thru all the sockets and enable receiving */
  1841. while (NULL != (pSocket = Connection_List_Copy.Get()))
  1842. {
  1843. /*
  1844. * If we had failed to deliver a data pkt to MCS before, we need
  1845. * an extra ReadRequest to recv and keep the FD_READ msgs coming.
  1846. */
  1847. if (DATA_READY == pSocket->Read_State)
  1848. {
  1849. ::ReadRequest(pSocket->XprtConn);
  1850. }
  1851. TRACE_OUT (("EnableReceiver: Calling ReadRequestEx on socket (%d, %d)",
  1852. pSocket->XprtConn.eType, pSocket->XprtConn.nLogicalHandle));
  1853. ::ReadRequestEx(pSocket->XprtConn);
  1854. }
  1855. }
  1856. /*
  1857. * TransportError ShutdownAndClose (TransportConnection , BOOL fShutdown, int how)
  1858. *
  1859. * Functional Description
  1860. * This function shuts down the socket and closes it.
  1861. *
  1862. */
  1863. void ShutdownAndClose (TransportConnection XprtConn, BOOL fShutdown, int how)
  1864. {
  1865. if (IS_SOCKET(XprtConn))
  1866. {
  1867. int error;
  1868. if (fShutdown)
  1869. {
  1870. error = ::shutdown(XprtConn.nLogicalHandle, how);
  1871. ASSERT(error != SOCKET_ERROR);
  1872. #ifdef DEBUG
  1873. if(error == SOCKET_ERROR)
  1874. {
  1875. error = WSAGetLastError();
  1876. WARNING_OUT (("ShutdownAndClose: shutdown returned %d", error));
  1877. }
  1878. #endif // DEBUG
  1879. }
  1880. error = ::closesocket(XprtConn.nLogicalHandle);
  1881. #ifdef DEBUG
  1882. if(error == SOCKET_ERROR)
  1883. {
  1884. WARNING_OUT(("ShutdownAndClose: closesocket returned %d", WSAGetLastError()));
  1885. }
  1886. #endif // DEBUG
  1887. }
  1888. }
  1889. /*
  1890. * TransportError GetLocalAddress (TransportConnection XprtConn,
  1891. * TransportAddress address,
  1892. * int * size)
  1893. *
  1894. * Functional Description:
  1895. * This function retrieves the local IP address associated with the given
  1896. * connection. It returns TRANSPORT_NO_SUCH_CONNECTION if the address is
  1897. * not available. If the address is available, the size parameter specifies
  1898. * the size of the address buffer on entry, and it is filled in with the size
  1899. * used for the address on exit.
  1900. */
  1901. TransportError GetLocalAddress( TransportConnection XprtConn,
  1902. TransportAddress address,
  1903. int * size)
  1904. {
  1905. SOCKADDR_IN socket_control;
  1906. PChar szTemp;
  1907. int Length;
  1908. TransportError error = TRANSPORT_NO_SUCH_CONNECTION;
  1909. if (NULL != g_pSocketList->FindByTransportConnection(XprtConn, TRUE))
  1910. {
  1911. if (IS_SOCKET(XprtConn))
  1912. {
  1913. /* Get the local name for the socket */
  1914. Length = sizeof(socket_control);
  1915. if (getsockname(XprtConn.nLogicalHandle, (LPSOCKADDR) &socket_control, &Length) == 0) {
  1916. /* Convert it to an IP address string */
  1917. szTemp = inet_ntoa(socket_control.sin_addr);
  1918. ASSERT (szTemp);
  1919. Length = (int) strlen(szTemp) + 1;
  1920. ASSERT (*size >= Length);
  1921. ASSERT (address);
  1922. /* Copy it to the buffer */
  1923. lstrcpyn((PChar)address, szTemp, Length);
  1924. *size = Length;
  1925. error = TRANSPORT_NO_ERROR;
  1926. }
  1927. }
  1928. else
  1929. {
  1930. ASSERT(IS_PLUGGABLE(XprtConn));
  1931. // string should look like "xprt: 1"
  1932. char szConnStr[T120_CONNECTION_ID_LENGTH];
  1933. Length = ::CreateConnString((UINT)XprtConn.nLogicalHandle, szConnStr);
  1934. if (*size > ++Length)
  1935. {
  1936. ::lstrcpyn(address, szConnStr, Length+1);
  1937. *size = Length;
  1938. error = TRANSPORT_NO_ERROR;
  1939. TRACE_OUT (("GetLocalAddress: plugable connection local address (%s)", address));
  1940. }
  1941. else
  1942. {
  1943. ERROR_OUT(("GetLocalAddress: buffer too small, given=%d, required=%d", *size, Length));
  1944. error = TRANSPORT_BUFFER_TOO_SMALL;
  1945. }
  1946. }
  1947. }
  1948. #ifdef DEBUG
  1949. if (error != TRANSPORT_NO_ERROR)
  1950. WARNING_OUT (("GetLocalAddress: Failure to obtain local address (%d)", WSAGetLastError()));
  1951. #endif // DEBUG
  1952. return (error);
  1953. }
  1954. /*
  1955. * void AcceptCall (BOOL fSecure)
  1956. *
  1957. * Functional Description:
  1958. * This function calls Winsock to answer an incoming call.
  1959. */
  1960. void AcceptCall (TransportConnection XprtConn)
  1961. {
  1962. PSocket pSocket;
  1963. PSecurityContext pSC = NULL;
  1964. SOCKADDR_IN socket_control;
  1965. int size;
  1966. TRACE_OUT(("AcceptCall"));
  1967. if (IS_SOCKET(XprtConn))
  1968. {
  1969. ASSERT(XprtConn.nLogicalHandle == Listen_Socket);
  1970. ASSERT (Listen_Socket != INVALID_SOCKET);
  1971. /* Call accept() to see if anyone is calling us */
  1972. size = sizeof (socket_control);
  1973. XprtConn.nLogicalHandle = ::accept ( Listen_Socket,
  1974. (struct sockaddr *) &socket_control, &size);
  1975. /* Note that we expect accept to complete immediately */
  1976. if (XprtConn.nLogicalHandle == INVALID_SOCKET)
  1977. {
  1978. ERROR_OUT (("AcceptCall: Error on accept = %d", WSAGetLastError()));
  1979. // SendStatusMessage ("", TSTATE_NOT_READY, IDS_NULL_STRING);
  1980. return;
  1981. }
  1982. }
  1983. /* If the accept() received an incoming call, create a connection and notify our owner object. */
  1984. pSocket = newSocket(XprtConn, NULL);
  1985. if( pSocket == NULL )
  1986. {
  1987. /* Close the socket */
  1988. ::ShutdownAndClose(XprtConn, TRUE, 2);
  1989. return;
  1990. }
  1991. pSocket -> State = SOCKET_CONNECTED;
  1992. if (IS_SOCKET(XprtConn))
  1993. {
  1994. /* Issue the getpeername() function to get the remote user's address */
  1995. size = sizeof (socket_control);
  1996. if (::getpeername(XprtConn.nLogicalHandle, (LPSOCKADDR) &socket_control, &size) == 0)
  1997. {
  1998. lstrcpyn (
  1999. pSocket -> Remote_Address,
  2000. inet_ntoa (socket_control.sin_addr),
  2001. MAXIMUM_IP_ADDRESS_SIZE-1);
  2002. pSocket -> Remote_Address[MAXIMUM_IP_ADDRESS_SIZE - 1] = NULL;
  2003. }
  2004. // SendStatusMessage(pSocket -> Remote_Address, TSTATE_CONNECTED, IDS_NULL_STRING);
  2005. }
  2006. /* Add to connection list */
  2007. // bugbug: we fail to insert.
  2008. g_pSocketList->SafeAppend(pSocket);
  2009. /* Notify the user */
  2010. TRACE_OUT (("TCP Callback: g_Transport->ConnectIndication (%d, %d)", XprtConn.eType, XprtConn.nLogicalHandle));
  2011. /* We issue a callback to the user to notify him of the message */
  2012. g_Transport->ConnectIndication(XprtConn);
  2013. }
  2014. //
  2015. // ReadRequestEx() is for the plugable transport.
  2016. // Since we do not have the FD_ACCEPT notifcation, we try to make sure
  2017. // we have a valid transport connection for every read...
  2018. // The following piece of code is derived from AcceptCall().
  2019. //
  2020. void ReadRequestEx(TransportConnection XprtConn)
  2021. {
  2022. if (! IS_PLUGGABLE_PSTN(XprtConn))
  2023. {
  2024. ::ReadRequest(XprtConn);
  2025. }
  2026. }
  2027. /*
  2028. * LRESULT WindowProcedure (
  2029. * HWND window_handle,
  2030. * UINT message,
  2031. * WPARAM wParam,
  2032. * LPARAM lParam)
  2033. *
  2034. * Public
  2035. *
  2036. * Functional Description:
  2037. * This function is called by Windows when we dispatch a TCP message from the
  2038. * event loop above. It gives us a chance to process the incoming socket messages.
  2039. */
  2040. LRESULT WindowProcedure (HWND window_handle,
  2041. UINT message,
  2042. WPARAM wParam,
  2043. LPARAM lParam)
  2044. {
  2045. TransportConnection XprtConn;
  2046. UShort error;
  2047. UShort event;
  2048. //PSocket pSocket;
  2049. switch (message)
  2050. {
  2051. #ifndef NO_TCP_TIMER
  2052. case WM_TIMER:
  2053. {
  2054. /*
  2055. ** We are currently using a slow timer to keep reading even when
  2056. ** FD_READ msgs get lost (this happens on Win95).
  2057. **
  2058. */
  2059. if (NULL != g_Transport) {
  2060. TRACE_OUT(("MSMCSTCP: WM_TIMER"));
  2061. EnableReceiver ();
  2062. }
  2063. }
  2064. break;
  2065. #endif /* NO_TCP_TIMER */
  2066. case WM_SOCKET_NOTIFICATION:
  2067. {
  2068. /* This message is generated by WinSock */
  2069. event = WSAGETSELECTEVENT (lParam);
  2070. error = WSAGETSELECTERROR (lParam);
  2071. SET_SOCKET_CONNECTION(XprtConn, wParam);
  2072. /* We disconnect whenever a socket command generates an error message */
  2073. if (error)
  2074. {
  2075. WARNING_OUT (("TCP: error %d on socket (%d). Event: %d", error, XprtConn.nLogicalHandle, event));
  2076. ::DisconnectRequest(XprtConn, TPRT_NOTIFY_OTHER_REASON);
  2077. break;
  2078. }
  2079. /* We get FD_CLOSE when the socket is closed by the remote site. */
  2080. if (event & FD_CLOSE)
  2081. {
  2082. TRACE_OUT (("TCP: FD_CLOSE(%d)", XprtConn.nLogicalHandle));
  2083. ::DisconnectRequest(XprtConn, TPRT_NOTIFY_OTHER_REASON);
  2084. break;
  2085. }
  2086. /* We get FD_READ when there is data available for us to read. */
  2087. if (event & FD_READ)
  2088. {
  2089. // TRACE_OUT(("MSMCSTCP: FD_READ(%d)", (UINT) wParam));
  2090. ::ReadRequest(XprtConn);
  2091. }
  2092. /* We get FD_ACCEPT when a remote site is connecting with us */
  2093. if (event & FD_ACCEPT)
  2094. {
  2095. TRACE_OUT (("TCP: FD_ACCEPT(%d)", XprtConn.nLogicalHandle));
  2096. /* Note that we always accept calls. Disconnect cancels them. */
  2097. TransportConnection XprtConn2;
  2098. SET_SOCKET_CONNECTION(XprtConn2, Listen_Socket);
  2099. ::AcceptCall(XprtConn2);
  2100. }
  2101. /* We get FD_CONNECT when our connect completes */
  2102. if (event & FD_CONNECT)
  2103. {
  2104. TRACE_OUT (("TCP: FD_CONNECT(%d)", XprtConn.nLogicalHandle));
  2105. ::SendX224ConnectRequest(XprtConn);
  2106. }
  2107. /* We get FD_WRITE when there is space available to write data to WinSock */
  2108. if (event & FD_WRITE)
  2109. {
  2110. /*
  2111. * We need to send a BUFFER_EMPTY_INDICATION to the connection associated
  2112. * with the socket
  2113. */
  2114. TRACE_OUT (("TCP: FD_WRITE(%d)", XprtConn.nLogicalHandle));
  2115. // We need to flush the socket's pending data first.
  2116. if (TRANSPORT_NO_ERROR == ::DataRequest(XprtConn, NULL))
  2117. {
  2118. TRACE_OUT (("TCP: Sending BUFFER_EMPTY_INDICATION to transport."));
  2119. g_Transport->BufferEmptyIndication(XprtConn);
  2120. }
  2121. }
  2122. }
  2123. break;
  2124. case WM_PLUGGABLE_X224:
  2125. // for low level read and write,
  2126. {
  2127. XprtConn.eType = (TransportType) PLUGXPRT_WPARAM_TO_TYPE(wParam);
  2128. XprtConn.nLogicalHandle = PLUGXPRT_WPARAM_TO_ID(wParam);
  2129. ASSERT(IS_PLUGGABLE(XprtConn));
  2130. event = PLUGXPRT_LPARAM_TO_EVENT(lParam);
  2131. error = PLUGXPRT_LPARAM_TO_ERROR(lParam);
  2132. /* We disconnect whenever a socket command generates an error message */
  2133. if (error)
  2134. {
  2135. WARNING_OUT(("PluggableWndProc: error %d on socket (%d, %d). Event: %d",
  2136. error, XprtConn.eType, XprtConn.nLogicalHandle, event));
  2137. ::DisconnectRequest(XprtConn, TPRT_NOTIFY_OTHER_REASON);
  2138. ::PluggableShutdown(XprtConn);
  2139. break;
  2140. }
  2141. switch (event)
  2142. {
  2143. case PLUGXPRT_EVENT_READ:
  2144. TRACE_OUT(("PluggableWndProc: READ(%d, %d)", XprtConn.eType, XprtConn.nLogicalHandle));
  2145. ::ReadRequestEx(XprtConn);
  2146. break;
  2147. case PLUGXPRT_EVENT_WRITE:
  2148. TRACE_OUT(("PluggableWndProc: WRITE(%d, %d)", XprtConn.eType, XprtConn.nLogicalHandle));
  2149. ::PluggableWriteTheFirst(XprtConn);
  2150. break;
  2151. case PLUGXPRT_EVENT_CLOSE:
  2152. TRACE_OUT(("PluggableWndProc: CLOSE(%d, %d)", XprtConn.eType, XprtConn.nLogicalHandle));
  2153. ::DisconnectRequest(XprtConn, TPRT_NOTIFY_OTHER_REASON);
  2154. break;
  2155. case PLUGXPRT_HIGH_LEVEL_READ:
  2156. TRACE_OUT(("PluggableWndProc: READ_NEXT(%d, %d)", XprtConn.eType, XprtConn.nLogicalHandle));
  2157. ::ReadRequestEx(XprtConn);
  2158. break;
  2159. case PLUGXPRT_HIGH_LEVEL_WRITE:
  2160. TRACE_OUT(("PluggableWndProc: WRITE_NEXT(%d, %d)", XprtConn.eType, XprtConn.nLogicalHandle));
  2161. // We need to flush the socket's pending data first.
  2162. if (TRANSPORT_NO_ERROR == ::DataRequest(XprtConn, NULL))
  2163. {
  2164. TRACE_OUT(("PluggableWndProc: Sending BUFFER_EMPTY_INDICATION to transport."));
  2165. g_Transport->BufferEmptyIndication(XprtConn);
  2166. }
  2167. break;
  2168. default:
  2169. ERROR_OUT(("PluggableWndProc: unknown event=%d.", event));
  2170. break;
  2171. }
  2172. }
  2173. break;
  2174. case WM_PLUGGABLE_PSTN:
  2175. {
  2176. extern void HandlePSTNCallback(WPARAM wParam, LPARAM lParam);
  2177. HandlePSTNCallback(wParam, lParam);
  2178. }
  2179. break;
  2180. default:
  2181. {
  2182. /*
  2183. ** The message is not related to WinSock messages, so let
  2184. ** the default window procedure handle it.
  2185. */
  2186. return (DefWindowProc (window_handle, message, wParam, lParam));
  2187. }
  2188. }
  2189. return (0);
  2190. }
  2191. // GetSecurityInfo() takes a connection_handle and returns the security information associated with
  2192. // it.
  2193. //
  2194. // Returns TRUE if we can either find the information or we are not directly connected to the node
  2195. // represented by this connection handle.
  2196. //
  2197. // Returns FALSE if we are directly connected but for some reason could not get the info -- this
  2198. // result should be viewed as suspicious.
  2199. BOOL GetSecurityInfo(ConnectionHandle connection_handle, PBYTE pInfo, PDWORD pcbInfo)
  2200. {
  2201. PSocket pSocket;
  2202. SOCKET socket_number;
  2203. if (g_pMCSController->FindSocketNumber(connection_handle, &socket_number))
  2204. {
  2205. TransportConnection XprtConn;
  2206. SET_SOCKET_CONNECTION(XprtConn, socket_number);
  2207. BOOL fRet = FALSE;
  2208. if (NULL != (pSocket = g_pSocketList->FindByTransportConnection(XprtConn)))
  2209. {
  2210. if (NULL != pSocket->pSC)
  2211. {
  2212. fRet = pSocket->pSC->GetUserCert(pInfo, pcbInfo);
  2213. }
  2214. else
  2215. {
  2216. WARNING_OUT(("GetSecurityInfo: queried non-secure socket %d", socket_number));
  2217. }
  2218. pSocket->Release();
  2219. }
  2220. else
  2221. {
  2222. WARNING_OUT(("GetSecurityInfo: socket %d not found", socket_number ));
  2223. }
  2224. return fRet;
  2225. }
  2226. // In this case we are not directly connected, so will return length of NOT_DIRECTLY_CONNECTED
  2227. // but positive return value.
  2228. *pcbInfo = NOT_DIRECTLY_CONNECTED;
  2229. return TRUE;
  2230. }
  2231. // GetSecurityInfoFromGCCID() takes a GCCID and returns the security information associated with
  2232. // it.
  2233. //
  2234. // Returns TRUE if either (1) we successfully retrieve the information from a transport-level
  2235. // connection, or (2) we find that we are not directly connected to the node with this GCCID.
  2236. //
  2237. // Returns FALSE if we are directly connected but cannot retrieve the info, or some other error
  2238. // occurs. A FALSE return value should be treated as a security violation.
  2239. BOOL WINAPI T120_GetSecurityInfoFromGCCID(DWORD dwGCCID, PBYTE pInfo, PDWORD pcbInfo)
  2240. {
  2241. PSocket pSocket;
  2242. SOCKET socket_number;
  2243. if ( NULL != dwGCCID )
  2244. {
  2245. // Get the user info for a remote connection
  2246. ConnectionHandle connection_handle;
  2247. BOOL fConnected = FindSocketNumber(dwGCCID, &socket_number);
  2248. if (fConnected == FALSE) {
  2249. (* pcbInfo) = 0;
  2250. return TRUE;
  2251. }
  2252. TransportConnection XprtConn;
  2253. SET_SOCKET_CONNECTION(XprtConn, socket_number);
  2254. BOOL fRet = FALSE;
  2255. if (NULL != (pSocket = g_pSocketList->FindByTransportConnection(XprtConn)))
  2256. {
  2257. if (NULL != pSocket->pSC)
  2258. {
  2259. fRet = pSocket->pSC->GetUserCert(pInfo, pcbInfo);
  2260. }
  2261. else
  2262. {
  2263. WARNING_OUT(("GetSecurityInfoFromGCCID: queried non-secure socket %d", socket_number));
  2264. }
  2265. pSocket->Release();
  2266. }
  2267. else
  2268. {
  2269. ERROR_OUT(("GetSecurityInfoFromGCCID: socket %d not found", socket_number ));
  2270. }
  2271. return fRet;
  2272. }
  2273. else
  2274. {
  2275. // Get the user info for the local user
  2276. if ( NULL != g_Transport && NULL != g_Transport->pSecurityInterface )
  2277. return g_Transport->pSecurityInterface->GetUserCert( pInfo, pcbInfo );
  2278. else
  2279. return FALSE;
  2280. }
  2281. }
  2282. DWORD WINAPI T120_TprtSecCtrl ( DWORD dwCode, DWORD_PTR dwParam1, DWORD_PTR dwParam2 )
  2283. {
  2284. DWORD dwRet = TPRTSEC_NOERROR;
  2285. RegEntry re(CONFERENCING_KEY, HKEY_CURRENT_USER);
  2286. switch ( dwCode )
  2287. {
  2288. case TPRTCTRL_SETX509CREDENTIALS:
  2289. //
  2290. // Security. Create transport interface if we don't have one.
  2291. // Update credentials if we do.
  2292. //
  2293. if (!g_Transport->pSecurityInterface)
  2294. {
  2295. g_Transport->pSecurityInterface =
  2296. new SecurityInterface(g_Transport->bInServiceContext);
  2297. if ( TPRTSEC_NOERROR !=
  2298. g_Transport->pSecurityInterface->Initialize())
  2299. {
  2300. delete g_Transport->pSecurityInterface;
  2301. g_Transport->pSecurityInterface = NULL;
  2302. dwRet = TPRTSEC_SSPIFAIL;
  2303. }
  2304. }
  2305. else
  2306. {
  2307. //
  2308. // dwParam1 points to an encoded X509 cert
  2309. // create credentials from it.
  2310. //
  2311. dwRet = g_Transport->pSecurityInterface->
  2312. InitializeCreds((PCCERT_CONTEXT)dwParam1);
  2313. }
  2314. return dwRet;
  2315. break;
  2316. case TPRTCTRL_GETX509CREDENTIALS:
  2317. if ( g_Transport->pSecurityInterface )
  2318. {
  2319. DWORD cb;
  2320. PBYTE pb;
  2321. if ( g_Transport->pSecurityInterface->GetUserCert( NULL, &cb))
  2322. {
  2323. if ( pb = (PBYTE)CoTaskMemAlloc ( cb ))
  2324. {
  2325. if(g_Transport->pSecurityInterface->GetUserCert(pb,&cb))
  2326. {
  2327. *((PBYTE *)dwParam1) = pb;
  2328. *((PDWORD)dwParam2) = cb;
  2329. dwRet = TPRTSEC_NOERROR;
  2330. }
  2331. else
  2332. CoTaskMemFree(pb);
  2333. }
  2334. }
  2335. }
  2336. else
  2337. {
  2338. ERROR_OUT(("TPRTCTRL_GETX509CREDENTIALS w/ no infc"));
  2339. dwRet = TPRTSEC_SSPIFAIL;
  2340. }
  2341. return dwRet;
  2342. break;
  2343. default:
  2344. ERROR_OUT(("TprtSecCtrl: unrecognized command code"));
  2345. return 0;
  2346. }
  2347. ASSERT(FALSE); // Should not reach this
  2348. return 0;
  2349. }