BOOL TsProxyCreateChannel(rdpTsg* tsg, PTUNNEL_CONTEXT_HANDLE_NOSERIALIZE tunnelContext, PTSENDPOINTINFO tsEndPointInfo, PCHANNEL_CONTEXT_HANDLE_SERIALIZE* channelContext, UINT32* channelId) { /** * OpNum = 4 * * HRESULT TsProxyCreateChannel( * [in] PTUNNEL_CONTEXT_HANDLE_NOSERIALIZE tunnelContext, * [in, ref] PTSENDPOINTINFO tsEndPointInfo, * [out] PCHANNEL_CONTEXT_HANDLE_SERIALIZE* channelContext, * [out] unsigned long* channelId * ); */ DEBUG_TSG("TsProxyCreateChannel"); if (!TsProxyCreateChannelWriteRequest(tsg, tunnelContext)) { printf("TsProxyCreateChannel: error writing request\n"); return FALSE; } if (!TsProxyCreateChannelReadResponse(tsg)) { printf("TsProxyCreateChannel: error reading response\n"); return FALSE; } return TRUE; }
BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port) { RPC_PDU* pdu = NULL; RpcClientCall* call; rdpRpc* rpc = tsg->rpc; rdpSettings* settings = rpc->settings; tsg->Port = port; ConvertToUnicode(CP_UTF8, 0, hostname, -1, &tsg->Hostname, 0); ConvertToUnicode(CP_UTF8, 0, settings->ComputerName, -1, &tsg->MachineName, 0); if (!rpc_connect(rpc)) { fprintf(stderr, "rpc_connect failed!\n"); return FALSE; } DEBUG_TSG("rpc_connect success"); tsg->state = TSG_STATE_INITIAL; rpc->client->SynchronousSend = TRUE; rpc->client->SynchronousReceive = TRUE; /* * Sequential processing rules for connection process: * * 1. The RDG client MUST call TsProxyCreateTunnel to create a tunnel to the gateway. * * 2. If the call fails, the RDG client MUST end the protocol and MUST NOT perform the following steps. * * 3. The RDG client MUST initialize the following ADM elements using TsProxyCreateTunnel out parameters: * * a. The RDG client MUST initialize the ADM element Tunnel id with the tunnelId out parameter. * * b. The RDG client MUST initialize the ADM element Tunnel Context Handle with the tunnelContext * out parameter. This Tunnel Context Handle is used for subsequent tunnel-related calls. * * c. If TSGPacketResponse->packetId is TSG_PACKET_TYPE_CAPS_RESPONSE, where TSGPacketResponse is an out parameter, * * i. The RDG client MUST initialize the ADM element Nonce with TSGPacketResponse-> * TSGPacket.packetCapsResponse->pktQuarEncResponse.nonce. * * ii. The RDG client MUST initialize the ADM element Negotiated Capabilities with TSGPacketResponse-> * TSGPacket.packetCapsResponse->pktQuarEncResponse.versionCaps->TSGCaps[0].TSGPacket.TSGCapNap.capabilities. * * d. If TSGPacketResponse->packetId is TSG_PACKET_TYPE_QUARENC_RESPONSE, where TSGPacketResponse is an out parameter, * * i. The RDG client MUST initialize the ADM element Nonce with TSGPacketResponse-> * TSGPacket.packetQuarEncResponse->nonce. * * ii. The RDG client MUST initialize the ADM element Negotiated Capabilities with TSGPacketResponse-> * TSGPacket.packetQuarEncResponse->versionCaps->TSGCaps[0].TSGPacket.TSGCapNap.capabilities. * * 4. The RDG client MUST get its statement of health (SoH) by calling NAP EC API.<49> Details of the SoH format are * specified in [TNC-IF-TNCCSPBSoH]. If the SoH is received successfully, then the RDG client MUST encrypt the SoH * using the Triple Data Encryption Standard algorithm and encode it using one of PKCS #7 or X.509 encoding types, * whichever is supported by the RDG server certificate context available in the ADM element CertChainData. * * 5. The RDG client MUST copy the ADM element Nonce to TSGPacket.packetQuarRequest->data and append the encrypted SoH * message into TSGPacket.packetQuarRequest->data. The RDG client MUST set the TSGPacket.packetQuarRequest->dataLen * to the sum of the number of bytes in the encrypted SoH message and number of bytes in the ADM element Nonce, where * TSGpacket is an input parameter of TsProxyAuthorizeTunnel. The format of the packetQuarRequest field is specified * in section 2.2.9.2.1.4. */ if (!TsProxyCreateTunnel(tsg, NULL, NULL, NULL, NULL)) { tsg->state = TSG_STATE_FINAL; return FALSE; } pdu = rpc_recv_dequeue_pdu(rpc); if (!TsProxyCreateTunnelReadResponse(tsg, pdu)) { fprintf(stderr, "TsProxyCreateTunnel: error reading response\n"); return FALSE; } tsg->state = TSG_STATE_CONNECTED; /** * Sequential processing rules for connection process (continued): * * 6. The RDG client MUST call TsProxyAuthorizeTunnel to authorize the tunnel. * * 7. If the call succeeds or fails with error E_PROXY_QUARANTINE_ACCESSDENIED, follow the steps later in this section. * Else, the RDG client MUST end the protocol and MUST NOT follow the steps later in this section. * * 8. If the ADM element Negotiated Capabilities contains TSG_NAP_CAPABILITY_IDLE_TIMEOUT, then the ADM element Idle * Timeout Value SHOULD be initialized with first 4 bytes of TSGPacketResponse->TSGPacket.packetResponse->responseData * and the Statement of health response variable should be initialized with the remaining bytes of responseData, where * TSGPacketResponse is an out parameter of TsProxyAuthorizeTunnel. The format of the responseData member is specified * in section 2.2.9.2.1.5.1. * * 9. If the ADM element Negotiated Capabilities doesn't contain TSG_NAP_CAPABILITY_IDLE_TIMEOUT, then the ADM element Idle * Timeout Value SHOULD be initialized to zero and the Statement of health response variable should be initialized with all * the bytes of TSGPacketResponse->TSGPacket.packetResponse->responseData. * * 10. Verify the signature of the Statement of health response variable using SHA-1 hash and decode it using the RDG server * certificate context available in the ADM element CertChainData using one of PKCS #7 or X.509 encoding types, whichever * is supported by the RDG Server certificate. The SoHR is processed by calling the NAP EC API * INapEnforcementClientConnection::GetSoHResponse. * * 11. If the call TsProxyAuthorizeTunnel fails with error E_PROXY_QUARANTINE_ACCESSDENIED, the RDG client MUST end the protocol * and MUST NOT follow the steps later in this section. * * 12. If the ADM element Idle Timeout Value is nonzero, the RDG client SHOULD start the idle time processing as specified in * section 3.6.2.1.1 and SHOULD end the protocol when the connection has been idle for the specified Idle Timeout Value. */ if (!TsProxyAuthorizeTunnel(tsg, &tsg->TunnelContext, NULL, NULL)) { tsg->state = TSG_STATE_TUNNEL_CLOSE_PENDING; return FALSE; } pdu = rpc_recv_dequeue_pdu(rpc); if (!TsProxyAuthorizeTunnelReadResponse(tsg, pdu)) { fprintf(stderr, "TsProxyAuthorizeTunnel: error reading response\n"); return FALSE; } tsg->state = TSG_STATE_AUTHORIZED; /** * Sequential processing rules for connection process (continued): * * 13. If the ADM element Negotiated Capabilities contains TSG_MESSAGING_CAP_SERVICE_MSG, a TsProxyMakeTunnelCall call MAY be * made by the client, with TSG_TUNNEL_CALL_ASYNC_MSG_REQUEST as the parameter, to receive messages from the RDG server. * */ if (!TsProxyMakeTunnelCall(tsg, &tsg->TunnelContext, TSG_TUNNEL_CALL_ASYNC_MSG_REQUEST, NULL, NULL)) return FALSE; /** * Sequential processing rules for connection process (continued): * * 14. The RDG client MUST call TsProxyCreateChannel to create a channel to the target server name as specified by the ADM * element Target Server Name (section 3.5.1). * * 15. If the call fails, the RDG client MUST end the protocol and MUST not follow the below steps. * * 16. The RDG client MUST initialize the following ADM elements using TsProxyCreateChannel out parameters. * * a. The RDG client MUST initialize the ADM element Channel id with the channelId out parameter. * * b. The RDG client MUST initialize the ADM element Channel Context Handle with the channelContext * out parameter. This Channel Context Handle is used for subsequent channel-related calls. */ if (!TsProxyCreateChannel(tsg, &tsg->TunnelContext, NULL, NULL, NULL)) return FALSE; pdu = rpc_recv_dequeue_pdu(rpc); call = rpc_client_call_find_by_id(rpc, pdu->CallId); if (call->OpNum == TsProxyMakeTunnelCallOpnum) { if (!TsProxyMakeTunnelCallReadResponse(tsg, pdu)) { fprintf(stderr, "TsProxyMakeTunnelCall: error reading response\n"); return FALSE; } pdu = rpc_recv_dequeue_pdu(rpc); } if (!TsProxyCreateChannelReadResponse(tsg, pdu)) { fprintf(stderr, "TsProxyCreateChannel: error reading response\n"); return FALSE; } tsg->state = TSG_STATE_CHANNEL_CREATED; /** * Sequential processing rules for data transfer: * * 1. The RDG client MUST call TsProxySetupReceivePipe to receive data from the target server, via the RDG server. * * 2. The RDG client MUST call TsProxySendToServer to send data to the target server via the RDG server, and if * the Idle Timeout Timer is started, the RDG client SHOULD reset the Idle Timeout Timer. * * 3. If TsProxyMakeTunnelCall is returned, the RDG client MUST process the message and MAY call TsProxyMakeTunnelCall * again with TSG_TUNNEL_CALL_ASYNC_MSG_REQUEST as the parameter. * * 4. The RDG client MUST end the protocol after it receives the final response to TsProxySetupReceivePipe. * The final response format is specified in section 2.2.9.4.3. */ if (!TsProxySetupReceivePipe((handle_t) tsg, NULL)) return FALSE; #if 0 pdu = rpc_recv_dequeue_pdu(rpc); if (!TsProxySetupReceivePipeReadResponse(tsg, pdu)) { fprintf(stderr, "TsProxySetupReceivePipe: error reading response\n"); return FALSE; } #endif rpc->client->SynchronousSend = TRUE; rpc->client->SynchronousReceive = TRUE; fprintf(stderr, "TS Gateway Connection Success\n"); return TRUE; }