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.

2528 lines
91 KiB

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