BOOL TsProxyAuthorizeTunnelReadResponse(rdpTsg* tsg, RPC_PDU* pdu) { BYTE* buffer; UINT32 length; UINT32 offset; UINT32 Pointer; UINT32 SizeValue; UINT32 SwitchValue; PTSG_PACKET packet; rdpRpc* rpc = tsg->rpc; PTSG_PACKET_RESPONSE packetResponse; if (!pdu) return FALSE; length = Stream_Length(pdu->s); buffer = Stream_Buffer(pdu->s); if (!(pdu->Flags & RPC_PDU_FLAG_STUB)) buffer = &buffer[24]; packet = (PTSG_PACKET) malloc(sizeof(TSG_PACKET)); ZeroMemory(packet, sizeof(TSG_PACKET)); offset = 4; packet->packetId = *((UINT32*) &buffer[offset]); /* PacketId */ SwitchValue = *((UINT32*) &buffer[offset + 4]); /* SwitchValue */ if ((packet->packetId != TSG_PACKET_TYPE_RESPONSE) || (SwitchValue != TSG_PACKET_TYPE_RESPONSE)) { fprintf(stderr, "Unexpected PacketId: 0x%08X, Expected TSG_PACKET_TYPE_RESPONSE\n", packet->packetId); free(packet); return FALSE; } packetResponse = (PTSG_PACKET_RESPONSE) malloc(sizeof(TSG_PACKET_RESPONSE)); ZeroMemory(packetResponse, sizeof(TSG_PACKET_RESPONSE)); packet->tsgPacket.packetResponse = packetResponse; Pointer = *((UINT32*) &buffer[offset + 8]); /* PacketResponsePtr */ packetResponse->flags = *((UINT32*) &buffer[offset + 12]); /* Flags */ if (packetResponse->flags != TSG_PACKET_TYPE_QUARREQUEST) { fprintf(stderr, "Unexpected Packet Response Flags: 0x%08X, Expected TSG_PACKET_TYPE_QUARREQUEST\n", packetResponse->flags); free(packet); free(packetResponse); return FALSE; } /* Reserved (4 bytes) */ Pointer = *((UINT32*) &buffer[offset + 20]); /* ResponseDataPtr */ packetResponse->responseDataLen = *((UINT32*) &buffer[offset + 24]); /* ResponseDataLength */ packetResponse->redirectionFlags.enableAllRedirections = *((UINT32*) &buffer[offset + 28]); /* EnableAllRedirections */ packetResponse->redirectionFlags.disableAllRedirections = *((UINT32*) &buffer[offset + 32]); /* DisableAllRedirections */ packetResponse->redirectionFlags.driveRedirectionDisabled = *((UINT32*) &buffer[offset + 36]); /* DriveRedirectionDisabled */ packetResponse->redirectionFlags.printerRedirectionDisabled = *((UINT32*) &buffer[offset + 40]); /* PrinterRedirectionDisabled */ packetResponse->redirectionFlags.portRedirectionDisabled = *((UINT32*) &buffer[offset + 44]); /* PortRedirectionDisabled */ packetResponse->redirectionFlags.reserved = *((UINT32*) &buffer[offset + 48]); /* Reserved */ packetResponse->redirectionFlags.clipboardRedirectionDisabled = *((UINT32*) &buffer[offset + 52]); /* ClipboardRedirectionDisabled */ packetResponse->redirectionFlags.pnpRedirectionDisabled = *((UINT32*) &buffer[offset + 56]); /* PnpRedirectionDisabled */ offset += 60; SizeValue = *((UINT32*) &buffer[offset]); offset += 4; if (SizeValue != packetResponse->responseDataLen) { fprintf(stderr, "Unexpected size value: %d, expected: %d\n", SizeValue, packetResponse->responseDataLen); free(packetResponse); free(packet); return FALSE; } offset += SizeValue; /* ResponseData */ rpc_client_receive_pool_return(rpc, pdu); free(packetResponse); free(packet); return TRUE; }
BOOL TsProxyCreateTunnelReadResponse(rdpTsg* tsg, RPC_PDU* pdu) { BYTE* buffer; UINT32 count; UINT32 length; UINT32 offset; UINT32 Pointer; PTSG_PACKET packet; UINT32 SwitchValue; UINT32 MessageSwitchValue; UINT32 IsMessagePresent; UINT32 MsgBytes; rdpRpc* rpc = tsg->rpc; PTSG_PACKET_CAPABILITIES tsgCaps; PTSG_PACKET_VERSIONCAPS versionCaps; PTSG_PACKET_CAPS_RESPONSE packetCapsResponse; PTSG_PACKET_QUARENC_RESPONSE packetQuarEncResponse; if (!pdu) return FALSE; length = Stream_Length(pdu->s); buffer = Stream_Buffer(pdu->s); if (!(pdu->Flags & RPC_PDU_FLAG_STUB)) buffer = &buffer[24]; packet = (PTSG_PACKET) malloc(sizeof(TSG_PACKET)); ZeroMemory(packet, sizeof(TSG_PACKET)); offset = 4; // Skip Packet Pointer packet->packetId = *((UINT32*) &buffer[offset]); /* PacketId */ SwitchValue = *((UINT32*) &buffer[offset + 4]); /* SwitchValue */ if ((packet->packetId == TSG_PACKET_TYPE_CAPS_RESPONSE) && (SwitchValue == TSG_PACKET_TYPE_CAPS_RESPONSE)) { packetCapsResponse = (PTSG_PACKET_CAPS_RESPONSE) malloc(sizeof(TSG_PACKET_CAPS_RESPONSE)); ZeroMemory(packetCapsResponse, sizeof(TSG_PACKET_CAPS_RESPONSE)); packet->tsgPacket.packetCapsResponse = packetCapsResponse; /* PacketQuarResponsePtr (4 bytes) */ packetCapsResponse->pktQuarEncResponse.flags = *((UINT32*) &buffer[offset + 12]); /* Flags */ packetCapsResponse->pktQuarEncResponse.certChainLen = *((UINT32*) &buffer[offset + 16]); /* CertChainLength */ /* CertChainDataPtr (4 bytes) */ CopyMemory(&packetCapsResponse->pktQuarEncResponse.nonce, &buffer[offset + 24], 16); /* Nonce */ offset += 40; Pointer = *((UINT32*) &buffer[offset]); /* VersionCapsPtr */ offset += 4; if ((Pointer == 0x0002000C) || (Pointer == 0x00020008)) { offset += 4; /* MsgID */ offset += 4; /* MsgType */ IsMessagePresent = *((UINT32*) &buffer[offset]); offset += 4; MessageSwitchValue = *((UINT32*) &buffer[offset]); DEBUG_TSG("IsMessagePresent %d MessageSwitchValue %d", IsMessagePresent, MessageSwitchValue); offset += 4; } if (packetCapsResponse->pktQuarEncResponse.certChainLen > 0) { Pointer = *((UINT32*) &buffer[offset]); /* MsgPtr (4 bytes): 0x00020014 */ offset += 4; offset += 4; /* MaxCount (4 bytes) */ offset += 4; /* Offset (4 bytes) */ count = *((UINT32*) &buffer[offset]); /* ActualCount (4 bytes) */ offset += 4; /* * CertChainData is a wide character string, and the count is * given in characters excluding the null terminator, therefore: * size = (count * 2) */ offset += (count * 2); /* CertChainData */ /* 4-byte alignment */ rpc_offset_align(&offset, 4); } else { Pointer = *((UINT32*) &buffer[offset]); /* Ptr (4 bytes) */ offset += 4; } versionCaps = (PTSG_PACKET_VERSIONCAPS) malloc(sizeof(TSG_PACKET_VERSIONCAPS)); ZeroMemory(versionCaps, sizeof(TSG_PACKET_VERSIONCAPS)); packetCapsResponse->pktQuarEncResponse.versionCaps = versionCaps; versionCaps->tsgHeader.ComponentId = *((UINT16*) &buffer[offset]); /* ComponentId */ versionCaps->tsgHeader.PacketId = *((UINT16*) &buffer[offset + 2]); /* PacketId */ offset += 4; if (versionCaps->tsgHeader.ComponentId != TS_GATEWAY_TRANSPORT) { fprintf(stderr, "Unexpected ComponentId: 0x%04X, Expected TS_GATEWAY_TRANSPORT\n", versionCaps->tsgHeader.ComponentId); free(packetCapsResponse); free(versionCaps); free(packet); return FALSE; } Pointer = *((UINT32*) &buffer[offset]); /* TsgCapsPtr */ versionCaps->numCapabilities = *((UINT32*) &buffer[offset + 4]); /* NumCapabilities */ versionCaps->majorVersion = *((UINT16*) &buffer[offset + 8]); /* MajorVersion */ versionCaps->minorVersion = *((UINT16*) &buffer[offset + 10]); /* MinorVersion */ versionCaps->quarantineCapabilities = *((UINT16*) &buffer[offset + 12]); /* QuarantineCapabilities */ offset += 14; /* 4-byte alignment */ rpc_offset_align(&offset, 4); tsgCaps = (PTSG_PACKET_CAPABILITIES) malloc(sizeof(TSG_PACKET_CAPABILITIES)); ZeroMemory(tsgCaps, sizeof(TSG_PACKET_CAPABILITIES)); versionCaps->tsgCaps = tsgCaps; offset += 4; /* MaxCount (4 bytes) */ tsgCaps->capabilityType = *((UINT32*) &buffer[offset]); /* CapabilityType */ SwitchValue = *((UINT32*) &buffer[offset + 4]); /* SwitchValue */ offset += 8; if ((SwitchValue != TSG_CAPABILITY_TYPE_NAP) || (tsgCaps->capabilityType != TSG_CAPABILITY_TYPE_NAP)) { fprintf(stderr, "Unexpected CapabilityType: 0x%08X, Expected TSG_CAPABILITY_TYPE_NAP\n", tsgCaps->capabilityType); free(tsgCaps); free(versionCaps); free(packetCapsResponse); free(packet); return FALSE; } tsgCaps->tsgPacket.tsgCapNap.capabilities = *((UINT32*) &buffer[offset]); /* Capabilities */ offset += 4; switch(MessageSwitchValue) { case TSG_ASYNC_MESSAGE_CONSENT_MESSAGE: case TSG_ASYNC_MESSAGE_SERVICE_MESSAGE: offset += 4; // IsDisplayMandatory offset += 4; // IsConsent Mandatory MsgBytes = *((UINT32*) &buffer[offset]); offset += 4; Pointer = *((UINT32*) &buffer[offset]); offset += 4; if(Pointer) { offset += 4; // MaxCount offset += 8; // UnicodeString Offset, Length } if(MsgBytes > TSG_MESSAGING_MAX_MESSAGE_LENGTH) { fprintf(stderr, "Out of Spec Message Length %d"); return FALSE; } offset += MsgBytes; break; case TSG_ASYNC_MESSAGE_REAUTH: rpc_offset_align(&offset, 8); offset += 8; // UINT64 TunnelContext, not to be confused with // the ContextHandle TunnelContext below. break; default: fprintf(stderr, "Unexpected Message Type: 0x%X\n", MessageSwitchValue); return FALSE; } rpc_offset_align(&offset, 4); /* TunnelContext (20 bytes) */ CopyMemory(&tsg->TunnelContext.ContextType, &buffer[offset], 4); /* ContextType */ CopyMemory(tsg->TunnelContext.ContextUuid, &buffer[offset + 4], 16); /* ContextUuid */ offset += 20; // UINT32 TunnelId // HRESULT ReturnValue #ifdef WITH_DEBUG_TSG fprintf(stderr, "TSG TunnelContext:\n"); winpr_HexDump((void*) &tsg->TunnelContext, 20); fprintf(stderr, "\n"); #endif free(tsgCaps); free(versionCaps); free(packetCapsResponse); } else if ((packet->packetId == TSG_PACKET_TYPE_QUARENC_RESPONSE) && (SwitchValue == TSG_PACKET_TYPE_QUARENC_RESPONSE)) { packetQuarEncResponse = (PTSG_PACKET_QUARENC_RESPONSE) malloc(sizeof(TSG_PACKET_QUARENC_RESPONSE)); ZeroMemory(packetQuarEncResponse, sizeof(TSG_PACKET_QUARENC_RESPONSE)); packet->tsgPacket.packetQuarEncResponse = packetQuarEncResponse; /* PacketQuarResponsePtr (4 bytes) */ packetQuarEncResponse->flags = *((UINT32*) &buffer[offset + 12]); /* Flags */ packetQuarEncResponse->certChainLen = *((UINT32*) &buffer[offset + 16]); /* CertChainLength */ /* CertChainDataPtr (4 bytes) */ CopyMemory(&packetQuarEncResponse->nonce, &buffer[offset + 24], 16); /* Nonce */ offset += 40; if (packetQuarEncResponse->certChainLen > 0) { Pointer = *((UINT32*) &buffer[offset]); /* Ptr (4 bytes): 0x0002000C */ offset += 4; offset += 4; /* MaxCount (4 bytes) */ offset += 4; /* Offset (4 bytes) */ count = *((UINT32*) &buffer[offset]); /* ActualCount (4 bytes) */ offset += 4; /* * CertChainData is a wide character string, and the count is * given in characters excluding the null terminator, therefore: * size = (count * 2) */ offset += (count * 2); /* CertChainData */ /* 4-byte alignment */ rpc_offset_align(&offset, 4); } else { Pointer = *((UINT32*) &buffer[offset]); /* Ptr (4 bytes): 0x00020008 */ offset += 4; } versionCaps = (PTSG_PACKET_VERSIONCAPS) malloc(sizeof(TSG_PACKET_VERSIONCAPS)); ZeroMemory(versionCaps, sizeof(TSG_PACKET_VERSIONCAPS)); packetQuarEncResponse->versionCaps = versionCaps; versionCaps->tsgHeader.ComponentId = *((UINT16*) &buffer[offset]); /* ComponentId */ versionCaps->tsgHeader.PacketId = *((UINT16*) &buffer[offset + 2]); /* PacketId */ offset += 4; if (versionCaps->tsgHeader.ComponentId != TS_GATEWAY_TRANSPORT) { fprintf(stderr, "Unexpected ComponentId: 0x%04X, Expected TS_GATEWAY_TRANSPORT\n", versionCaps->tsgHeader.ComponentId); free(versionCaps); free(packetQuarEncResponse); free(packet); return FALSE; } Pointer = *((UINT32*) &buffer[offset]); /* TsgCapsPtr */ versionCaps->numCapabilities = *((UINT32*) &buffer[offset + 4]); /* NumCapabilities */ versionCaps->majorVersion = *((UINT16*) &buffer[offset + 8]); /* MajorVersion */ versionCaps->majorVersion = *((UINT16*) &buffer[offset + 10]); /* MinorVersion */ versionCaps->quarantineCapabilities = *((UINT16*) &buffer[offset + 12]); /* QuarantineCapabilities */ offset += 14; /* 4-byte alignment */ rpc_offset_align(&offset, 4); /* Not sure exactly what this is */ offset += 4; /* 0x00000001 (4 bytes) */ offset += 4; /* 0x00000001 (4 bytes) */ offset += 4; /* 0x00000001 (4 bytes) */ offset += 4; /* 0x00000002 (4 bytes) */ /* TunnelContext (20 bytes) */ CopyMemory(&tsg->TunnelContext.ContextType, &buffer[offset], 4); /* ContextType */ CopyMemory(tsg->TunnelContext.ContextUuid, &buffer[offset + 4], 16); /* ContextUuid */ offset += 20; #ifdef WITH_DEBUG_TSG fprintf(stderr, "TSG TunnelContext:\n"); winpr_HexDump((void*) &tsg->TunnelContext, 20); fprintf(stderr, "\n"); #endif free(versionCaps); free(packetQuarEncResponse); } else { fprintf(stderr, "Unexpected PacketId: 0x%08X, Expected TSG_PACKET_TYPE_CAPS_RESPONSE " "or TSG_PACKET_TYPE_QUARENC_RESPONSE\n", packet->packetId); free(packet); return FALSE; } rpc_client_receive_pool_return(rpc, pdu); free(packet); return TRUE; }
DWORD TsProxySendToServer(handle_t IDL_handle, byte pRpcMessage[], UINT32 count, UINT32* lengths) { wStream* s; int status; rdpTsg* tsg; BYTE* buffer; UINT32 length; byte* buffer1 = NULL; byte* buffer2 = NULL; byte* buffer3 = NULL; UINT32 buffer1Length; UINT32 buffer2Length; UINT32 buffer3Length; UINT32 numBuffers = 0; UINT32 totalDataBytes = 0; tsg = (rdpTsg*) IDL_handle; buffer1Length = buffer2Length = buffer3Length = 0; if (count > 0) { numBuffers++; buffer1 = &pRpcMessage[0]; buffer1Length = lengths[0]; totalDataBytes += lengths[0] + 4; } if (count > 1) { numBuffers++; buffer2 = &pRpcMessage[1]; buffer2Length = lengths[1]; totalDataBytes += lengths[1] + 4; } if (count > 2) { numBuffers++; buffer3 = &pRpcMessage[2]; buffer3Length = lengths[2]; totalDataBytes += lengths[2] + 4; } length = 28 + totalDataBytes; buffer = (BYTE*) malloc(length); s = Stream_New(buffer, length); /* PCHANNEL_CONTEXT_HANDLE_NOSERIALIZE_NR (20 bytes) */ Stream_Write(s, &tsg->ChannelContext.ContextType, 4); /* ContextType (4 bytes) */ Stream_Write(s, tsg->ChannelContext.ContextUuid, 16); /* ContextUuid (16 bytes) */ Stream_Write_UINT32_BE(s, totalDataBytes); /* totalDataBytes (4 bytes) */ Stream_Write_UINT32_BE(s, numBuffers); /* numBuffers (4 bytes) */ if (buffer1Length > 0) Stream_Write_UINT32_BE(s, buffer1Length); /* buffer1Length (4 bytes) */ if (buffer2Length > 0) Stream_Write_UINT32_BE(s, buffer2Length); /* buffer2Length (4 bytes) */ if (buffer3Length > 0) Stream_Write_UINT32_BE(s, buffer3Length); /* buffer3Length (4 bytes) */ if (buffer1Length > 0) Stream_Write(s, buffer1, buffer1Length); /* buffer1 (variable) */ if (buffer2Length > 0) Stream_Write(s, buffer2, buffer2Length); /* buffer2 (variable) */ if (buffer3Length > 0) Stream_Write(s, buffer3, buffer3Length); /* buffer3 (variable) */ Stream_Length(s) = Stream_GetPosition(s); status = rpc_write(tsg->rpc, Stream_Buffer(s), Stream_Length(s), TsProxySendToServerOpnum); Stream_Free(s, TRUE); if (status <= 0) { fprintf(stderr, "rpc_write failed!\n"); return -1; } return length; }
/** * @brief Try to read a complete PDU (NLA, fast-path or tpkt) from the underlying transport. * * If possible a complete PDU is read, in case of non blocking transport this might not succeed. * Except in case of an error the passed stream will point to the last byte read (correct * position). When the pdu read is completed the stream is sealed and the pointer set to 0 * * @param[in] transport rdpTransport * @param[in] s wStream * @return < 0 on error; 0 if not enough data is available (non blocking mode); > 0 number of * bytes of the *complete* pdu read */ int transport_read_pdu(rdpTransport* transport, wStream* s) { int status; int position; int pduLength; BYTE* header; position = 0; pduLength = 0; if (!transport) return -1; if (!s) return -1; position = Stream_GetPosition(s); /* Make sure there is enough space for the longest header within the stream */ Stream_EnsureCapacity(s, 4); /* Make sure at least two bytes are read for futher processing */ if (position < 2 && (status = transport_read_layer_bytes(transport, s, 2 - position)) != 1) { /* No data available at the moment */ return status; } header = Stream_Buffer(s); if (transport->NlaMode) { /* * In case NlaMode is set TSRequest package(s) are expected * 0x30 = DER encoded data with these bits set: * bit 6 P/C constructed * bit 5 tag number - sequence */ if (header[0] == 0x30) { /* TSRequest (NLA) */ if (header[1] & 0x80) { if ((header[1] & ~(0x80)) == 1) { if ((status = transport_read_layer_bytes(transport, s, 1)) != 1) return status; pduLength = header[2]; pduLength += 3; } else if ((header[1] & ~(0x80)) == 2) { if ((status = transport_read_layer_bytes(transport, s, 2)) != 1) return status; pduLength = (header[2] << 8) | header[3]; pduLength += 4; } else { WLog_ERR(TAG, "Error reading TSRequest!"); return -1; } } else { pduLength = header[1]; pduLength += 2; } } } else { if (header[0] == 0x03) { /* TPKT header */ if ((status = transport_read_layer_bytes(transport, s, 2)) != 1) return status; pduLength = (header[2] << 8) | header[3]; /* min and max values according to ITU-T Rec. T.123 (01/2007) section 8 */ if (pduLength < 7 || pduLength > 0xFFFF) { WLog_ERR(TAG, "tpkt - invalid pduLength: %d", pduLength); return -1; } } else { /* Fast-Path Header */ if (header[1] & 0x80) { if ((status = transport_read_layer_bytes(transport, s, 1)) != 1) return status; pduLength = ((header[1] & 0x7F) << 8) | header[2]; } else pduLength = header[1]; /* * fast-path has 7 bits for length so the maximum size, including headers is 0x8000 * The theoretical minimum fast-path PDU consists only of two header bytes plus one * byte for data (e.g. fast-path input synchronize pdu) */ if (pduLength < 3 || pduLength > 0x8000) { WLog_ERR(TAG, "fast path - invalid pduLength: %d", pduLength); return -1; } } } Stream_EnsureCapacity(s, Stream_GetPosition(s) + pduLength); status = transport_read_layer_bytes(transport, s, pduLength - Stream_GetPosition(s)); if (status != 1) return status; #ifdef WITH_DEBUG_TRANSPORT /* dump when whole PDU is read */ if (Stream_GetPosition(s) >= pduLength) { WLog_DBG(TAG, "Local < Remote"); winpr_HexDump(TAG, WLOG_DEBUG, Stream_Buffer(s), pduLength); } #endif if (Stream_GetPosition(s) >= pduLength) WLog_Packet(transport->log, WLOG_TRACE, Stream_Buffer(s), pduLength, WLOG_PACKET_INBOUND); Stream_SealLength(s); Stream_SetPosition(s, 0); return Stream_Length(s); }
/* * Handle rpdgfx messages - server side * * @param Server side context * * @return 0 on success * ERROR_NO_DATA if no data could be read this time * otherwise a Win32 error code */ UINT rdpgfx_server_handle_messages(RdpgfxServerContext* context) { DWORD BytesReturned; void* buffer; UINT ret = CHANNEL_RC_OK; RdpgfxServerPrivate* priv = context->priv; wStream* s = priv->input_stream; /* Check whether the dynamic channel is ready */ if (!priv->isReady) { if (WTSVirtualChannelQuery(priv->rdpgfx_channel, WTSVirtualChannelReady, &buffer, &BytesReturned) == FALSE) { if (GetLastError() == ERROR_NO_DATA) return ERROR_NO_DATA; WLog_ERR(TAG, "WTSVirtualChannelQuery failed"); return ERROR_INTERNAL_ERROR; } priv->isReady = *((BOOL*) buffer); WTSFreeMemory(buffer); } /* Consume channel event only after the gfx dynamic channel is ready */ if (priv->isReady) { Stream_SetPosition(s, 0); if (!WTSVirtualChannelRead(priv->rdpgfx_channel, 0, NULL, 0, &BytesReturned)) { if (GetLastError() == ERROR_NO_DATA) return ERROR_NO_DATA; WLog_ERR(TAG, "WTSVirtualChannelRead failed!"); return ERROR_INTERNAL_ERROR; } if (BytesReturned < 1) return CHANNEL_RC_OK; if (!Stream_EnsureRemainingCapacity(s, BytesReturned)) { WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); return CHANNEL_RC_NO_MEMORY; } if (WTSVirtualChannelRead(priv->rdpgfx_channel, 0, (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned) == FALSE) { WLog_ERR(TAG, "WTSVirtualChannelRead failed!"); return ERROR_INTERNAL_ERROR; } Stream_SetLength(s, BytesReturned); Stream_SetPosition(s, 0); while (Stream_GetPosition(s) < Stream_Length(s)) { if ((ret = rdpgfx_server_receive_pdu(context, s))) { WLog_ERR(TAG, "rdpgfx_server_receive_pdu " "failed with error %"PRIu32"!", ret); return ret; } } } return ret; }
BOOL rts_connect(rdpRpc* rpc) { RPC_PDU* pdu; rpcconn_rts_hdr_t* rts; HttpResponse* http_response; /** * Connection Opening * * When opening a virtual connection to the server, an implementation of this protocol MUST perform * the following sequence of steps: * * 1. Send an IN channel request as specified in section 2.1.2.1.1, containing the connection timeout, * ResourceType UUID, and Session UUID values, if any, supplied by the higher-layer protocol or application. * * 2. Send an OUT channel request as specified in section 2.1.2.1.2. * * 3. Send a CONN/A1 RTS PDU as specified in section 2.2.4.2 * * 4. Send a CONN/B1 RTS PDU as specified in section 2.2.4.5 * * 5. Wait for the connection establishment protocol sequence as specified in 3.2.1.5.3.1 to complete * * An implementation MAY execute steps 1 and 2 in parallel. An implementation SHOULD execute steps * 3 and 4 in parallel. An implementation MUST execute step 3 after completion of step 1 and execute * step 4 after completion of step 2. * */ rpc->VirtualConnection->State = VIRTUAL_CONNECTION_STATE_INITIAL; DEBUG_RTS("VIRTUAL_CONNECTION_STATE_INITIAL"); rpc->client->SynchronousSend = TRUE; rpc->client->SynchronousReceive = TRUE; if (!rpc_ntlm_http_out_connect(rpc)) { fprintf(stderr, "rpc_out_connect_http error!\n"); return FALSE; } if (rts_send_CONN_A1_pdu(rpc) != 0) { fprintf(stderr, "rpc_send_CONN_A1_pdu error!\n"); return FALSE; } if (!rpc_ntlm_http_in_connect(rpc)) { fprintf(stderr, "rpc_in_connect_http error!\n"); return FALSE; } if (rts_send_CONN_B1_pdu(rpc) != 0) { fprintf(stderr, "rpc_send_CONN_B1_pdu error!\n"); return FALSE; } rpc->VirtualConnection->State = VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT; DEBUG_RTS("VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT"); /** * Receive OUT Channel Response * * A client implementation MUST NOT accept the OUT channel HTTP response in any state other than * Out Channel Wait. If received in any other state, this HTTP response is a protocol error. Therefore, * the client MUST consider the virtual connection opening a failure and indicate this to higher layers * in an implementation-specific way. The Microsoft Windows® implementation returns * RPC_S_PROTOCOL_ERROR, as specified in [MS-ERREF], to higher-layer protocols. * * If this HTTP response is received in Out Channel Wait state, the client MUST process the fields of * this response as defined in this section. * * First, the client MUST determine whether the response indicates a success or a failure. If the status * code is set to 200, the client MUST interpret this as a success, and it MUST do the following: * * 1. Ignore the values of all other header fields. * * 2. Transition to Wait_A3W state. * * 3. Wait for network events. * * 4. Skip the rest of the processing in this section. * * If the status code is not set to 200, the client MUST interpret this as a failure and follow the same * processing rules as specified in section 3.2.2.5.6. * */ http_response = http_response_recv(rpc->TlsOut); if (http_response->StatusCode != HTTP_STATUS_OK) { fprintf(stderr, "rts_connect error! Status Code: %d\n", http_response->StatusCode); http_response_print(http_response); http_response_free(http_response); if (http_response->StatusCode == HTTP_STATUS_DENIED) { if (!connectErrorCode) { connectErrorCode = AUTHENTICATIONERROR; } if (!freerdp_get_last_error(((freerdp*)(rpc->settings->instance))->context)) { freerdp_set_last_error(((freerdp*)(rpc->settings->instance))->context, FREERDP_ERROR_AUTHENTICATION_FAILED); } } return FALSE; } //http_response_print(http_response); http_response_free(http_response); rpc->VirtualConnection->State = VIRTUAL_CONNECTION_STATE_WAIT_A3W; DEBUG_RTS("VIRTUAL_CONNECTION_STATE_WAIT_A3W"); /** * Receive CONN_A3 RTS PDU * * A client implementation MUST NOT accept the CONN/A3 RTS PDU in any state other than * Wait_A3W. If received in any other state, this PDU is a protocol error and the client * MUST consider the virtual connection opening a failure and indicate this to higher * layers in an implementation-specific way. * * Set the ConnectionTimeout in the Ping Originator of the Client's IN Channel to the * ConnectionTimeout in the CONN/A3 PDU. * * If this RTS PDU is received in Wait_A3W state, the client MUST transition the state * machine to Wait_C2 state and wait for network events. * */ rpc_client_start(rpc); pdu = rpc_recv_dequeue_pdu(rpc); if (!pdu) return FALSE; rts = (rpcconn_rts_hdr_t*) Stream_Buffer(pdu->s); if (!rts_match_pdu_signature(rpc, &RTS_PDU_CONN_A3_SIGNATURE, rts)) { fprintf(stderr, "Unexpected RTS PDU: Expected CONN/A3\n"); return FALSE; } rts_recv_CONN_A3_pdu(rpc, Stream_Buffer(pdu->s), Stream_Length(pdu->s)); rpc_client_receive_pool_return(rpc, pdu); rpc->VirtualConnection->State = VIRTUAL_CONNECTION_STATE_WAIT_C2; DEBUG_RTS("VIRTUAL_CONNECTION_STATE_WAIT_C2"); /** * Receive CONN_C2 RTS PDU * * A client implementation MUST NOT accept the CONN/C2 RTS PDU in any state other than Wait_C2. * If received in any other state, this PDU is a protocol error and the client MUST consider the virtual * connection opening a failure and indicate this to higher layers in an implementation-specific way. * * If this RTS PDU is received in Wait_C2 state, the client implementation MUST do the following: * * 1. Transition the state machine to opened state. * * 2. Set the connection time-out protocol variable to the value of the ConnectionTimeout field from * the CONN/C2 RTS PDU. * * 3. Set the PeerReceiveWindow value in the SendingChannel of the Client IN Channel to the * ReceiveWindowSize value in the CONN/C2 PDU. * * 4. Indicate to higher-layer protocols that the virtual connection opening is a success. * */ pdu = rpc_recv_dequeue_pdu(rpc); if (!pdu) return FALSE; rts = (rpcconn_rts_hdr_t*) Stream_Buffer(pdu->s); if (!rts_match_pdu_signature(rpc, &RTS_PDU_CONN_C2_SIGNATURE, rts)) { fprintf(stderr, "Unexpected RTS PDU: Expected CONN/C2\n"); return FALSE; } rts_recv_CONN_C2_pdu(rpc, Stream_Buffer(pdu->s), Stream_Length(pdu->s)); rpc_client_receive_pool_return(rpc, pdu); rpc->VirtualConnection->State = VIRTUAL_CONNECTION_STATE_OPENED; DEBUG_RTS("VIRTUAL_CONNECTION_STATE_OPENED"); rpc->client->SynchronousSend = TRUE; rpc->client->SynchronousReceive = TRUE; return TRUE; }
wStream* http_request_write(HttpContext* context, HttpRequest* request) { wStream* s; int i, count; char** lines; int length = 0; count = 0; lines = (char**) calloc(32, sizeof(char*)); if (!lines) return NULL; lines[count++] = http_encode_header_line(request->Method, request->URI); lines[count++] = http_encode_body_line("Cache-Control", context->CacheControl); lines[count++] = http_encode_body_line("Connection", context->Connection); lines[count++] = http_encode_body_line("Pragma", context->Pragma); lines[count++] = http_encode_body_line("Accept", context->Accept); lines[count++] = http_encode_body_line("User-Agent", context->UserAgent); lines[count++] = http_encode_content_length_line(request->ContentLength); lines[count++] = http_encode_body_line("Host", context->Host); /* check that everything went well */ for (i = 0; i < count; i++) { if (!lines[i]) goto out_free; } if (context->RdgConnectionId) { lines[count] = http_encode_body_line("RDG-Connection-Id", context->RdgConnectionId); if (!lines[count]) goto out_free; count++; } if (request->TransferEncoding) { lines[count] = http_encode_body_line("Transfer-Encoding", request->TransferEncoding); if (!lines[count]) goto out_free; count++; } if (request->Authorization) { lines[count] = http_encode_body_line("Authorization", request->Authorization); if (!lines[count]) goto out_free; count++; } else if (request->AuthScheme && request->AuthParam) { lines[count] = http_encode_authorization_line(request->AuthScheme, request->AuthParam); if (!lines[count]) goto out_free; count++; } for (i = 0; i < count; i++) { length += (strlen(lines[i]) + 2); /* add +2 for each '\r\n' character */ } length += 2; /* empty line "\r\n" at end of header */ length += 1; /* null terminator */ s = Stream_New(NULL, length); if (!s) goto out_free; for (i = 0; i < count; i++) { Stream_Write(s, lines[i], strlen(lines[i])); Stream_Write(s, "\r\n", 2); free(lines[i]); } Stream_Write(s, "\r\n", 2); free(lines); Stream_Write(s, "\0", 1); /* append null terminator */ Stream_Rewind(s, 1); /* don't include null terminator in length */ Stream_Length(s) = Stream_GetPosition(s); return s; out_free: for (i = 0; i < count; i++) free(lines[i]); free(lines); return NULL; }
static UINT video_VideoData(VideoClientContext* context, TSMM_VIDEO_DATA *data) { VideoClientContextPriv *priv = context->priv; PresentationContext *presentation; int status; presentation = priv->currentPresentation; if (!presentation) { WLog_ERR(TAG, "no current presentation"); return CHANNEL_RC_OK; } if (presentation->PresentationId != data->PresentationId) { WLog_ERR(TAG, "current presentation id=%d doesn't match data id=%d", presentation->PresentationId, data->PresentationId); return CHANNEL_RC_OK; } if (!Stream_EnsureRemainingCapacity(presentation->currentSample, data->cbSample)) { WLog_ERR(TAG, "unable to expand the current packet"); return CHANNEL_RC_NO_MEMORY; } Stream_Write(presentation->currentSample, data->pSample, data->cbSample); if (data->CurrentPacketIndex == data->PacketsInSample) { H264_CONTEXT *h264 = presentation->h264; UINT64 startTime = GetTickCount64(), timeAfterH264; MAPPED_GEOMETRY *geom = presentation->geometry; Stream_SealLength(presentation->currentSample); Stream_SetPosition(presentation->currentSample, 0); status = h264->subsystem->Decompress(h264, Stream_Pointer(presentation->currentSample), Stream_Length(presentation->currentSample)); if (status == 0) return CHANNEL_RC_OK; if (status < 0) return CHANNEL_RC_OK; timeAfterH264 = GetTickCount64(); if (data->SampleNumber == 1) { presentation->lastPublishTime = startTime; } presentation->lastPublishTime += (data->hnsDuration / 10000); if (presentation->lastPublishTime <= timeAfterH264 + 10) { int dropped = 0; /* if the frame is to be published in less than 10 ms, let's consider it's now */ yuv_to_rgb(presentation, presentation->surfaceData); context->showSurface(context, presentation->surface); priv->publishedFrames++; /* cleanup previously scheduled frames */ EnterCriticalSection(&priv->framesLock); while (Queue_Count(priv->frames) > 0) { VideoFrame *frame = Queue_Dequeue(priv->frames); if (frame) { priv->droppedFrames++; VideoFrame_free(&frame); dropped++; } } LeaveCriticalSection(&priv->framesLock); if (dropped) WLog_DBG(TAG, "showing frame (%d dropped)", dropped); } else { BOOL enqueueResult; VideoFrame *frame = calloc(1, sizeof(*frame)); if (!frame) { WLog_ERR(TAG, "unable to create frame"); return CHANNEL_RC_NO_MEMORY; } mappedGeometryRef(geom); frame->presentation = presentation; frame->publishTime = presentation->lastPublishTime; frame->geometry = geom; frame->w = presentation->SourceWidth; frame->h = presentation->SourceHeight; frame->surfaceData = BufferPool_Take(priv->surfacePool, frame->w * frame->h * 4); if (!frame->surfaceData) { WLog_ERR(TAG, "unable to allocate frame data"); mappedGeometryUnref(geom); free(frame); return CHANNEL_RC_NO_MEMORY; } if (!yuv_to_rgb(presentation, frame->surfaceData)) { WLog_ERR(TAG, "error during YUV->RGB conversion"); BufferPool_Return(priv->surfacePool, frame->surfaceData); mappedGeometryUnref(geom); free(frame); return CHANNEL_RC_NO_MEMORY; } InterlockedIncrement(&presentation->refCounter); EnterCriticalSection(&priv->framesLock); enqueueResult = Queue_Enqueue(priv->frames, frame); LeaveCriticalSection(&priv->framesLock); if (!enqueueResult) { WLog_ERR(TAG, "unable to enqueue frame"); VideoFrame_free(&frame); return CHANNEL_RC_NO_MEMORY; } WLog_DBG(TAG, "scheduling frame in %"PRIu32" ms", (frame->publishTime-startTime)); } } return CHANNEL_RC_OK; }
BOOL TsProxyMakeTunnelCallReadResponse(rdpTsg* tsg, RPC_PDU* pdu) { BOOL rc = TRUE; BYTE* buffer; UINT32 length; UINT32 offset; UINT32 Pointer; UINT32 MaxCount; UINT32 ActualCount; UINT32 SwitchValue; PTSG_PACKET packet; char* messageText = NULL; PTSG_PACKET_MSG_RESPONSE packetMsgResponse; PTSG_PACKET_STRING_MESSAGE packetStringMessage = NULL; PTSG_PACKET_REAUTH_MESSAGE packetReauthMessage = NULL; /* This is an asynchronous response */ if (!pdu) return FALSE; length = Stream_Length(pdu->s); buffer = Stream_Buffer(pdu->s); if (!(pdu->Flags & RPC_PDU_FLAG_STUB)) buffer = &buffer[24]; packet = (PTSG_PACKET) malloc(sizeof(TSG_PACKET)); ZeroMemory(packet, sizeof(TSG_PACKET)); offset = 4; packet->packetId = *((UINT32*) &buffer[offset]); /* PacketId */ SwitchValue = *((UINT32*) &buffer[offset + 4]); /* SwitchValue */ if ((packet->packetId != TSG_PACKET_TYPE_MESSAGE_PACKET) || (SwitchValue != TSG_PACKET_TYPE_MESSAGE_PACKET)) { fprintf(stderr, "Unexpected PacketId: 0x%08X, Expected TSG_PACKET_TYPE_MESSAGE_PACKET\n", packet->packetId); free(packet); return FALSE; } packetMsgResponse = (PTSG_PACKET_MSG_RESPONSE) malloc(sizeof(TSG_PACKET_MSG_RESPONSE)); ZeroMemory(packetMsgResponse, sizeof(TSG_PACKET_MSG_RESPONSE)); packet->tsgPacket.packetMsgResponse = packetMsgResponse; Pointer = *((UINT32*) &buffer[offset + 8]); /* PacketMsgResponsePtr */ packetMsgResponse->msgID = *((UINT32*) &buffer[offset + 12]); /* MsgId */ packetMsgResponse->msgType = *((UINT32*) &buffer[offset + 16]); /* MsgType */ packetMsgResponse->isMsgPresent = *((INT32*) &buffer[offset + 20]); /* IsMsgPresent */ SwitchValue = *((UINT32*) &buffer[offset + 24]); /* SwitchValue */ switch (SwitchValue) { case TSG_ASYNC_MESSAGE_CONSENT_MESSAGE: packetStringMessage = (PTSG_PACKET_STRING_MESSAGE) malloc(sizeof(TSG_PACKET_STRING_MESSAGE)); ZeroMemory(packetStringMessage, sizeof(TSG_PACKET_STRING_MESSAGE)); packetMsgResponse->messagePacket.consentMessage = packetStringMessage; Pointer = *((UINT32*) &buffer[offset + 28]); /* ConsentMessagePtr */ packetStringMessage->isDisplayMandatory = *((INT32*) &buffer[offset + 32]); /* IsDisplayMandatory */ packetStringMessage->isConsentMandatory = *((INT32*) &buffer[offset + 36]); /* IsConsentMandatory */ packetStringMessage->msgBytes = *((UINT32*) &buffer[offset + 40]); /* MsgBytes */ Pointer = *((UINT32*) &buffer[offset + 44]); /* MsgPtr */ MaxCount = *((UINT32*) &buffer[offset + 48]); /* MaxCount */ /* Offset */ ActualCount = *((UINT32*) &buffer[offset + 56]); /* ActualCount */ ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) &buffer[offset + 60], ActualCount, &messageText, 0, NULL, NULL); fprintf(stderr, "Consent Message: %s\n", messageText); free(messageText); break; case TSG_ASYNC_MESSAGE_SERVICE_MESSAGE: packetStringMessage = (PTSG_PACKET_STRING_MESSAGE) malloc(sizeof(TSG_PACKET_STRING_MESSAGE)); ZeroMemory(packetStringMessage, sizeof(TSG_PACKET_STRING_MESSAGE)); packetMsgResponse->messagePacket.serviceMessage = packetStringMessage; Pointer = *((UINT32*) &buffer[offset + 28]); /* ServiceMessagePtr */ packetStringMessage->isDisplayMandatory = *((INT32*) &buffer[offset + 32]); /* IsDisplayMandatory */ packetStringMessage->isConsentMandatory = *((INT32*) &buffer[offset + 36]); /* IsConsentMandatory */ packetStringMessage->msgBytes = *((UINT32*) &buffer[offset + 40]); /* MsgBytes */ Pointer = *((UINT32*) &buffer[offset + 44]); /* MsgPtr */ MaxCount = *((UINT32*) &buffer[offset + 48]); /* MaxCount */ /* Offset */ ActualCount = *((UINT32*) &buffer[offset + 56]); /* ActualCount */ ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) &buffer[offset + 60], ActualCount, &messageText, 0, NULL, NULL); fprintf(stderr, "Service Message: %s\n", messageText); free(messageText); break; case TSG_ASYNC_MESSAGE_REAUTH: packetReauthMessage = (PTSG_PACKET_REAUTH_MESSAGE) malloc(sizeof(TSG_PACKET_REAUTH_MESSAGE)); ZeroMemory(packetReauthMessage, sizeof(TSG_PACKET_REAUTH_MESSAGE)); packetMsgResponse->messagePacket.reauthMessage = packetReauthMessage; Pointer = *((UINT32*) &buffer[offset + 28]); /* ReauthMessagePtr */ break; default: fprintf(stderr, "TsProxyMakeTunnelCallReadResponse: unexpected message type: %d\n", SwitchValue); rc = FALSE; break; } if (packet) { if (packet->tsgPacket.packetMsgResponse) { if (packet->tsgPacket.packetMsgResponse->messagePacket.reauthMessage) free(packet->tsgPacket.packetMsgResponse->messagePacket.reauthMessage); free(packet->tsgPacket.packetMsgResponse); } free(packet); } return rc; }
int tsg_read(rdpTsg* tsg, BYTE* data, UINT32 length) { int CopyLength; rdpRpc* rpc; if (tsg == NULL) return -1; rpc = tsg->rpc; if (rpc->transport->layer == TRANSPORT_LAYER_CLOSED) { DEBUG_WARN( "tsg_read error: connection lost\n"); return -1; } if (tsg->PendingPdu) { CopyLength = (length < tsg->BytesAvailable) ? length : tsg->BytesAvailable; CopyMemory(data, &tsg->pdu->s->buffer[tsg->BytesRead], CopyLength); tsg->BytesAvailable -= CopyLength; tsg->BytesRead += CopyLength; if (tsg->BytesAvailable < 1) { tsg->PendingPdu = FALSE; rpc_recv_dequeue_pdu(rpc); rpc_client_receive_pool_return(rpc, tsg->pdu); } return CopyLength; } tsg->pdu = rpc_recv_peek_pdu(rpc); if (!tsg->pdu) { if (!tsg->rpc->client->SynchronousReceive) return 0; // weird !!!! return tsg_read(tsg, data, length); } tsg->PendingPdu = TRUE; tsg->BytesAvailable = Stream_Length(tsg->pdu->s); tsg->BytesRead = 0; CopyLength = (length < tsg->BytesAvailable) ? length : tsg->BytesAvailable; CopyMemory(data, &tsg->pdu->s->buffer[tsg->BytesRead], CopyLength); tsg->BytesAvailable -= CopyLength; tsg->BytesRead += CopyLength; if (tsg->BytesAvailable < 1) { tsg->PendingPdu = FALSE; rpc_recv_dequeue_pdu(rpc); rpc_client_receive_pool_return(rpc, tsg->pdu); } return CopyLength; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback) { UINT error; wStream* s; UINT16 index; RDPGFX_PLUGIN* gfx; RDPGFX_HEADER header; RDPGFX_CAPSET* capsSet; RDPGFX_CAPSET capsSets[2]; RDPGFX_CAPS_ADVERTISE_PDU pdu; gfx = (RDPGFX_PLUGIN*) callback->plugin; header.flags = 0; header.cmdId = RDPGFX_CMDID_CAPSADVERTISE; pdu.capsSetCount = 0; pdu.capsSets = (RDPGFX_CAPSET*) capsSets; capsSet = &capsSets[pdu.capsSetCount++]; capsSet->version = RDPGFX_CAPVERSION_8; capsSet->flags = 0; if (gfx->ThinClient) capsSet->flags |= RDPGFX_CAPS_FLAG_THINCLIENT; if (gfx->SmallCache) capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE; capsSet = &capsSets[pdu.capsSetCount++]; capsSet->version = RDPGFX_CAPVERSION_81; capsSet->flags = 0; if (gfx->ThinClient) capsSet->flags |= RDPGFX_CAPS_FLAG_THINCLIENT; if (gfx->SmallCache) capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE; if (gfx->H264) capsSet->flags |= RDPGFX_CAPS_FLAG_H264ENABLED; header.pduLength = RDPGFX_HEADER_SIZE + 2 + (pdu.capsSetCount * RDPGFX_CAPSET_SIZE); WLog_DBG(TAG, "SendCapsAdvertisePdu"); s = Stream_New(NULL, header.pduLength); if (!s) { WLog_ERR(TAG, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } if ((error = rdpgfx_write_header(s, &header))) { WLog_ERR(TAG, "rdpgfx_write_header failed with error %lu!", error); return error; } /* RDPGFX_CAPS_ADVERTISE_PDU */ Stream_Write_UINT16(s, pdu.capsSetCount); /* capsSetCount (2 bytes) */ for (index = 0; index < pdu.capsSetCount; index++) { capsSet = &(pdu.capsSets[index]); Stream_Write_UINT32(s, capsSet->version); /* version (4 bytes) */ Stream_Write_UINT32(s, 4); /* capsDataLength (4 bytes) */ Stream_Write_UINT32(s, capsSet->flags); /* capsData (4 bytes) */ } Stream_SealLength(s); error = callback->channel->Write(callback->channel, (UINT32) Stream_Length(s), Stream_Buffer(s), NULL); Stream_Free(s, TRUE); return error; }
BOOL TsProxyCreateTunnelReadResponse(rdpTsg* tsg) { BYTE* buffer; UINT32 count; UINT32 length; UINT32 offset; UINT32 Pointer; RPC_PDU* pdu; PTSG_PACKET packet; UINT32 SwitchValue; rdpRpc* rpc = tsg->rpc; PTSG_PACKET_CAPABILITIES tsgCaps; PTSG_PACKET_VERSIONCAPS versionCaps; PTSG_PACKET_CAPS_RESPONSE packetCapsResponse; PTSG_PACKET_QUARENC_RESPONSE packetQuarEncResponse; pdu = rpc_recv_dequeue_pdu(rpc); if (!pdu) return FALSE; length = Stream_Length(pdu->s); buffer = Stream_Buffer(pdu->s); if (!(pdu->Flags & RPC_PDU_FLAG_STUB)) buffer = &buffer[24]; packet = (PTSG_PACKET) malloc(sizeof(TSG_PACKET)); ZeroMemory(packet, sizeof(TSG_PACKET)); offset = 4; packet->packetId = *((UINT32*) &buffer[offset]); /* PacketId */ SwitchValue = *((UINT32*) &buffer[offset + 4]); /* SwitchValue */ if ((packet->packetId == TSG_PACKET_TYPE_CAPS_RESPONSE) && (SwitchValue == TSG_PACKET_TYPE_CAPS_RESPONSE)) { packetCapsResponse = (PTSG_PACKET_CAPS_RESPONSE) malloc(sizeof(TSG_PACKET_CAPS_RESPONSE)); ZeroMemory(packetCapsResponse, sizeof(TSG_PACKET_CAPS_RESPONSE)); packet->tsgPacket.packetCapsResponse = packetCapsResponse; /* PacketQuarResponsePtr (4 bytes) */ packetCapsResponse->pktQuarEncResponse.flags = *((UINT32*) &buffer[offset + 12]); /* Flags */ packetCapsResponse->pktQuarEncResponse.certChainLen = *((UINT32*) &buffer[offset + 16]); /* CertChainLength */ /* CertChainDataPtr (4 bytes) */ CopyMemory(&packetCapsResponse->pktQuarEncResponse.nonce, &buffer[offset + 24], 16); /* Nonce */ offset += 40; Pointer = *((UINT32*) &buffer[offset]); /* Ptr */ offset += 4; if ((Pointer == 0x0002000C) || (Pointer == 0x00020008)) { /* Not sure exactly what this is */ offset += 4; /* 0x00000001 (4 bytes) */ offset += 4; /* 0x00000001 (4 bytes) */ offset += 4; /* 0x00000000 (4 bytes) */ offset += 4; /* 0x00000001 (4 bytes) */ } if (packetCapsResponse->pktQuarEncResponse.certChainLen > 0) { Pointer = *((UINT32*) &buffer[offset]); /* Ptr (4 bytes): 0x00020014 */ offset += 4; offset += 4; /* MaxCount (4 bytes) */ offset += 4; /* Offset (4 bytes) */ count = *((UINT32*) &buffer[offset]); /* ActualCount (4 bytes) */ offset += 4; /* * CertChainData is a wide character string, and the count is * given in characters excluding the null terminator, therefore: * size = (count * 2) */ offset += (count * 2); /* CertChainData */ /* 4-byte alignment */ rpc_offset_align(&offset, 4); } else { Pointer = *((UINT32*) &buffer[offset]); /* Ptr (4 bytes) */ offset += 4; } versionCaps = (PTSG_PACKET_VERSIONCAPS) malloc(sizeof(TSG_PACKET_VERSIONCAPS)); ZeroMemory(versionCaps, sizeof(TSG_PACKET_VERSIONCAPS)); packetCapsResponse->pktQuarEncResponse.versionCaps = versionCaps; versionCaps->tsgHeader.ComponentId = *((UINT16*) &buffer[offset]); /* ComponentId */ versionCaps->tsgHeader.PacketId = *((UINT16*) &buffer[offset + 2]); /* PacketId */ offset += 4; if (versionCaps->tsgHeader.ComponentId != TS_GATEWAY_TRANSPORT) { printf("Unexpected ComponentId: 0x%04X, Expected TS_GATEWAY_TRANSPORT\n", versionCaps->tsgHeader.ComponentId); return FALSE; } Pointer = *((UINT32*) &buffer[offset]); /* TsgCapsPtr */ versionCaps->numCapabilities = *((UINT32*) &buffer[offset + 4]); /* NumCapabilities */ versionCaps->majorVersion = *((UINT16*) &buffer[offset + 8]); /* MajorVersion */ versionCaps->majorVersion = *((UINT16*) &buffer[offset + 10]); /* MinorVersion */ versionCaps->quarantineCapabilities = *((UINT16*) &buffer[offset + 12]); /* QuarantineCapabilities */ offset += 14; /* 4-byte alignment */ rpc_offset_align(&offset, 4); tsgCaps = (PTSG_PACKET_CAPABILITIES) malloc(sizeof(TSG_PACKET_CAPABILITIES)); ZeroMemory(tsgCaps, sizeof(TSG_PACKET_CAPABILITIES)); versionCaps->tsgCaps = tsgCaps; offset += 4; /* MaxCount (4 bytes) */ tsgCaps->capabilityType = *((UINT32*) &buffer[offset]); /* CapabilityType */ SwitchValue = *((UINT32*) &buffer[offset + 4]); /* SwitchValue */ offset += 8; if ((SwitchValue != TSG_CAPABILITY_TYPE_NAP) || (tsgCaps->capabilityType != TSG_CAPABILITY_TYPE_NAP)) { printf("Unexpected CapabilityType: 0x%08X, Expected TSG_CAPABILITY_TYPE_NAP\n", tsgCaps->capabilityType); return FALSE; } tsgCaps->tsgPacket.tsgCapNap.capabilities = *((UINT32*) &buffer[offset]); /* Capabilities */ offset += 4; /* ??? (16 bytes): all zeros */ offset += 16; /* TunnelContext (20 bytes) */ CopyMemory(&tsg->TunnelContext.ContextType, &buffer[offset], 4); /* ContextType */ CopyMemory(tsg->TunnelContext.ContextUuid, &buffer[offset + 4], 16); /* ContextUuid */ offset += 20; #ifdef WITH_DEBUG_TSG printf("TSG TunnelContext:\n"); winpr_HexDump((void*) &tsg->TunnelContext, 20); printf("\n"); #endif free(tsgCaps); free(versionCaps); free(packetCapsResponse); } else if ((packet->packetId == TSG_PACKET_TYPE_QUARENC_RESPONSE) && (SwitchValue == TSG_PACKET_TYPE_QUARENC_RESPONSE)) { packetQuarEncResponse = (PTSG_PACKET_QUARENC_RESPONSE) malloc(sizeof(TSG_PACKET_QUARENC_RESPONSE)); ZeroMemory(packetQuarEncResponse, sizeof(TSG_PACKET_QUARENC_RESPONSE)); packet->tsgPacket.packetQuarEncResponse = packetQuarEncResponse; /* PacketQuarResponsePtr (4 bytes) */ packetQuarEncResponse->flags = *((UINT32*) &buffer[offset + 12]); /* Flags */ packetQuarEncResponse->certChainLen = *((UINT32*) &buffer[offset + 16]); /* CertChainLength */ /* CertChainDataPtr (4 bytes) */ CopyMemory(&packetQuarEncResponse->nonce, &buffer[offset + 24], 16); /* Nonce */ offset += 40; if (packetQuarEncResponse->certChainLen > 0) { Pointer = *((UINT32*) &buffer[offset]); /* Ptr (4 bytes): 0x0002000C */ offset += 4; offset += 4; /* MaxCount (4 bytes) */ offset += 4; /* Offset (4 bytes) */ count = *((UINT32*) &buffer[offset]); /* ActualCount (4 bytes) */ offset += 4; /* * CertChainData is a wide character string, and the count is * given in characters excluding the null terminator, therefore: * size = (count * 2) */ offset += (count * 2); /* CertChainData */ /* 4-byte alignment */ rpc_offset_align(&offset, 4); } else { Pointer = *((UINT32*) &buffer[offset]); /* Ptr (4 bytes): 0x00020008 */ offset += 4; } versionCaps = (PTSG_PACKET_VERSIONCAPS) malloc(sizeof(TSG_PACKET_VERSIONCAPS)); ZeroMemory(versionCaps, sizeof(TSG_PACKET_VERSIONCAPS)); packetQuarEncResponse->versionCaps = versionCaps; versionCaps->tsgHeader.ComponentId = *((UINT16*) &buffer[offset]); /* ComponentId */ versionCaps->tsgHeader.PacketId = *((UINT16*) &buffer[offset + 2]); /* PacketId */ offset += 4; if (versionCaps->tsgHeader.ComponentId != TS_GATEWAY_TRANSPORT) { printf("Unexpected ComponentId: 0x%04X, Expected TS_GATEWAY_TRANSPORT\n", versionCaps->tsgHeader.ComponentId); return FALSE; } Pointer = *((UINT32*) &buffer[offset]); /* TsgCapsPtr */ versionCaps->numCapabilities = *((UINT32*) &buffer[offset + 4]); /* NumCapabilities */ versionCaps->majorVersion = *((UINT16*) &buffer[offset + 8]); /* MajorVersion */ versionCaps->majorVersion = *((UINT16*) &buffer[offset + 10]); /* MinorVersion */ versionCaps->quarantineCapabilities = *((UINT16*) &buffer[offset + 12]); /* QuarantineCapabilities */ offset += 14; /* 4-byte alignment */ rpc_offset_align(&offset, 4); /* Not sure exactly what this is */ offset += 4; /* 0x00000001 (4 bytes) */ offset += 4; /* 0x00000001 (4 bytes) */ offset += 4; /* 0x00000001 (4 bytes) */ offset += 4; /* 0x00000002 (4 bytes) */ /* TunnelContext (20 bytes) */ CopyMemory(&tsg->TunnelContext.ContextType, &buffer[offset], 4); /* ContextType */ CopyMemory(tsg->TunnelContext.ContextUuid, &buffer[offset + 4], 16); /* ContextUuid */ offset += 20; #ifdef WITH_DEBUG_TSG printf("TSG TunnelContext:\n"); winpr_HexDump((void*) &tsg->TunnelContext, 20); printf("\n"); #endif free(versionCaps); free(packetQuarEncResponse); } else { printf("Unexpected PacketId: 0x%08X, Expected TSG_PACKET_TYPE_CAPS_RESPONSE " "or TSG_PACKET_TYPE_QUARENC_RESPONSE\n", packet->packetId); return FALSE; } rpc_client_receive_pool_return(rpc, pdu); free(packet); return TRUE; }
int credssp_recv(rdpCredssp* credssp) { wStream* s; int length; int status; UINT32 version; s = Stream_New(NULL, 4096); status = transport_read(credssp->transport, s); Stream_Length(s) = status; if (status < 0) { fprintf(stderr, "credssp_recv() error: %d\n", status); Stream_Free(s, TRUE); return -1; } /* TSRequest */ if(!ber_read_sequence_tag(s, &length) || !ber_read_contextual_tag(s, 0, &length, TRUE) || !ber_read_integer(s, &version)) return -1; /* [1] negoTokens (NegoData) */ if (ber_read_contextual_tag(s, 1, &length, TRUE) != FALSE) { if (!ber_read_sequence_tag(s, &length) || /* SEQUENCE OF NegoDataItem */ !ber_read_sequence_tag(s, &length) || /* NegoDataItem */ !ber_read_contextual_tag(s, 0, &length, TRUE) || /* [0] negoToken */ !ber_read_octet_string_tag(s, &length) || /* OCTET STRING */ Stream_GetRemainingLength(s) < length) return -1; sspi_SecBufferAlloc(&credssp->negoToken, length); Stream_Read(s, credssp->negoToken.pvBuffer, length); credssp->negoToken.cbBuffer = length; } /* [2] authInfo (OCTET STRING) */ if (ber_read_contextual_tag(s, 2, &length, TRUE) != FALSE) { if(!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */ Stream_GetRemainingLength(s) < length) return -1; sspi_SecBufferAlloc(&credssp->authInfo, length); Stream_Read(s, credssp->authInfo.pvBuffer, length); credssp->authInfo.cbBuffer = length; } /* [3] pubKeyAuth (OCTET STRING) */ if (ber_read_contextual_tag(s, 3, &length, TRUE) != FALSE) { if(!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */ Stream_GetRemainingLength(s) < length) return -1; sspi_SecBufferAlloc(&credssp->pubKeyAuth, length); Stream_Read(s, credssp->pubKeyAuth.pvBuffer, length); credssp->pubKeyAuth.cbBuffer = length; } Stream_Free(s, TRUE); return 0; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ UINT disp_send_display_control_monitor_layout_pdu(DISP_CHANNEL_CALLBACK* callback, UINT32 NumMonitors, DISPLAY_CONTROL_MONITOR_LAYOUT* Monitors) { UINT status; wStream* s; UINT32 type; UINT32 index; UINT32 length; DISP_PLUGIN* disp; UINT32 MonitorLayoutSize; disp = (DISP_PLUGIN*) callback->plugin; MonitorLayoutSize = 40; length = 8 + 8 + (NumMonitors * MonitorLayoutSize); type = DISPLAY_CONTROL_PDU_TYPE_MONITOR_LAYOUT; s = Stream_New(NULL, length); if(!s) { WLog_ERR(TAG, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } Stream_Write_UINT32(s, type); /* Type (4 bytes) */ Stream_Write_UINT32(s, length); /* Length (4 bytes) */ if (NumMonitors > disp->MaxNumMonitors) NumMonitors = disp->MaxNumMonitors; Stream_Write_UINT32(s, MonitorLayoutSize); /* MonitorLayoutSize (4 bytes) */ Stream_Write_UINT32(s, NumMonitors); /* NumMonitors (4 bytes) */ //WLog_ERR(TAG, "NumMonitors: %d", NumMonitors); for (index = 0; index < NumMonitors; index++) { Monitors[index].Width -= (Monitors[index].Width % 2); if (Monitors[index].Width < 200) Monitors[index].Width = 200; if (Monitors[index].Width > 8192) Monitors[index].Width = 8192; if (Monitors[index].Width % 2) Monitors[index].Width++; if (Monitors[index].Height < 200) Monitors[index].Height = 200; if (Monitors[index].Height > 8192) Monitors[index].Height = 8192; Stream_Write_UINT32(s, Monitors[index].Flags); /* Flags (4 bytes) */ Stream_Write_UINT32(s, Monitors[index].Left); /* Left (4 bytes) */ Stream_Write_UINT32(s, Monitors[index].Top); /* Top (4 bytes) */ Stream_Write_UINT32(s, Monitors[index].Width); /* Width (4 bytes) */ Stream_Write_UINT32(s, Monitors[index].Height); /* Height (4 bytes) */ Stream_Write_UINT32(s, Monitors[index].PhysicalWidth); /* PhysicalWidth (4 bytes) */ Stream_Write_UINT32(s, Monitors[index].PhysicalHeight); /* PhysicalHeight (4 bytes) */ Stream_Write_UINT32(s, Monitors[index].Orientation); /* Orientation (4 bytes) */ Stream_Write_UINT32(s, Monitors[index].DesktopScaleFactor); /* DesktopScaleFactor (4 bytes) */ Stream_Write_UINT32(s, Monitors[index].DeviceScaleFactor); /* DeviceScaleFactor (4 bytes) */ #if 0 WLog_DBG(TAG, "\t: Flags: 0x%04X", Monitors[index].Flags); WLog_DBG(TAG, "\t: Left: %d", Monitors[index].Left); WLog_DBG(TAG, "\t: Top: %d", Monitors[index].Top); WLog_DBG(TAG, "\t: Width: %d", Monitors[index].Width); WLog_DBG(TAG, "\t: Height: %d", Monitors[index].Height); WLog_DBG(TAG, "\t: PhysicalWidth: %d", Monitors[index].PhysicalWidth); WLog_DBG(TAG, "\t: PhysicalHeight: %d", Monitors[index].PhysicalHeight); WLog_DBG(TAG, "\t: Orientation: %d", Monitors[index].Orientation); #endif } Stream_SealLength(s); status = callback->channel->Write(callback->channel, (UINT32) Stream_Length(s), Stream_Buffer(s), NULL); Stream_Free(s, TRUE); return status; }