Blame libfreerdp/core/gateway/rpc.c

Packit 1fb8d4
/**
Packit 1fb8d4
 * FreeRDP: A Remote Desktop Protocol Implementation
Packit 1fb8d4
 * RPC over HTTP
Packit 1fb8d4
 *
Packit 1fb8d4
 * Copyright 2012 Fujitsu Technology Solutions GmbH
Packit 1fb8d4
 * Copyright 2012 Dmitrij Jasnov <dmitrij.jasnov@ts.fujitsu.com>
Packit 1fb8d4
 * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit 1fb8d4
 *
Packit 1fb8d4
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit 1fb8d4
 * you may not use this file except in compliance with the License.
Packit 1fb8d4
 * You may obtain a copy of the License at
Packit 1fb8d4
 *
Packit 1fb8d4
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 1fb8d4
 *
Packit 1fb8d4
 * Unless required by applicable law or agreed to in writing, software
Packit 1fb8d4
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 1fb8d4
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 1fb8d4
 * See the License for the specific language governing permissions and
Packit 1fb8d4
 * limitations under the License.
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_CONFIG_H
Packit 1fb8d4
#include "config.h"
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#include <winpr/crt.h>
Packit 1fb8d4
#include <winpr/tchar.h>
Packit 1fb8d4
#include <winpr/synch.h>
Packit 1fb8d4
#include <winpr/dsparse.h>
Packit 1fb8d4
#include <winpr/crypto.h>
Packit 1fb8d4
Packit 1fb8d4
#include <freerdp/log.h>
Packit 1fb8d4
Packit 1fb8d4
#include <openssl/bio.h>
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_VALGRIND_MEMCHECK_H
Packit 1fb8d4
#include <valgrind/memcheck.h>
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#include "../proxy.h"
Packit 1fb8d4
#include "http.h"
Packit 1fb8d4
#include "ntlm.h"
Packit 1fb8d4
#include "ncacn_http.h"
Packit 1fb8d4
#include "rpc_bind.h"
Packit 1fb8d4
#include "rpc_fault.h"
Packit 1fb8d4
#include "rpc_client.h"
Packit 1fb8d4
Packit 1fb8d4
#include "rpc.h"
Packit 1fb8d4
Packit 1fb8d4
#define TAG FREERDP_TAG("core.gateway.rpc")
Packit 1fb8d4
Packit Service 5a9772
static const char* PTYPE_STRINGS[] = { "PTYPE_REQUEST",       "PTYPE_PING",
Packit Service 5a9772
	                                   "PTYPE_RESPONSE",      "PTYPE_FAULT",
Packit Service 5a9772
	                                   "PTYPE_WORKING",       "PTYPE_NOCALL",
Packit Service 5a9772
	                                   "PTYPE_REJECT",        "PTYPE_ACK",
Packit Service 5a9772
	                                   "PTYPE_CL_CANCEL",     "PTYPE_FACK",
Packit Service 5a9772
	                                   "PTYPE_CANCEL_ACK",    "PTYPE_BIND",
Packit Service 5a9772
	                                   "PTYPE_BIND_ACK",      "PTYPE_BIND_NAK",
Packit Service 5a9772
	                                   "PTYPE_ALTER_CONTEXT", "PTYPE_ALTER_CONTEXT_RESP",
Packit Service 5a9772
	                                   "PTYPE_RPC_AUTH_3",    "PTYPE_SHUTDOWN",
Packit Service 5a9772
	                                   "PTYPE_CO_CANCEL",     "PTYPE_ORPHANED",
Packit Service 5a9772
	                                   "PTYPE_RTS",           "" };
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * [MS-RPCH]: Remote Procedure Call over HTTP Protocol Specification:
Packit 1fb8d4
 * http://msdn.microsoft.com/en-us/library/cc243950/
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 *                                      Connection Establishment\n
Packit 1fb8d4
 *
Packit 1fb8d4
 *     Client                  Outbound Proxy           Inbound Proxy                 Server\n
Packit 1fb8d4
 *        |                         |                         |                         |\n
Packit 1fb8d4
 *        |-----------------IN Channel Request--------------->|                         |\n
Packit 1fb8d4
 *        |---OUT Channel Request-->|                         |<-Legacy Server Response-|\n
Packit 1fb8d4
 *        |                         |<--------------Legacy Server Response--------------|\n
Packit 1fb8d4
 *        |                         |                         |                         |\n
Packit 1fb8d4
 *        |---------CONN_A1-------->|                         |                         |\n
Packit 1fb8d4
 *        |----------------------CONN_B1--------------------->|                         |\n
Packit 1fb8d4
 *        |                         |----------------------CONN_A2--------------------->|\n
Packit 1fb8d4
 *        |                         |                         |                         |\n
Packit 1fb8d4
 *        |<--OUT Channel Response--|                         |---------CONN_B2-------->|\n
Packit 1fb8d4
 *        |<--------CONN_A3---------|                         |                         |\n
Packit 1fb8d4
 *        |                         |<---------------------CONN_C1----------------------|\n
Packit 1fb8d4
 *        |                         |                         |<--------CONN_B3---------|\n
Packit 1fb8d4
 *        |<--------CONN_C2---------|                         |                         |\n
Packit 1fb8d4
 *        |                         |                         |                         |\n
Packit 1fb8d4
 *
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
void rpc_pdu_header_print(rpcconn_hdr_t* header)
Packit 1fb8d4
{
Packit Service 5a9772
	WLog_INFO(TAG, "rpc_vers: %" PRIu8 "", header->common.rpc_vers);
Packit Service 5a9772
	WLog_INFO(TAG, "rpc_vers_minor: %" PRIu8 "", header->common.rpc_vers_minor);
Packit 1fb8d4
Packit 1fb8d4
	if (header->common.ptype > PTYPE_RTS)
Packit Service 5a9772
		WLog_INFO(TAG, "ptype: %s (%" PRIu8 ")", "PTYPE_UNKNOWN", header->common.ptype);
Packit 1fb8d4
	else
Packit Service 5a9772
		WLog_INFO(TAG, "ptype: %s (%" PRIu8 ")", PTYPE_STRINGS[header->common.ptype],
Packit Service 5a9772
		          header->common.ptype);
Packit 1fb8d4
Packit Service 5a9772
	WLog_INFO(TAG, "pfc_flags (0x%02" PRIX8 ") = {", header->common.pfc_flags);
Packit 1fb8d4
Packit 1fb8d4
	if (header->common.pfc_flags & PFC_FIRST_FRAG)
Packit Service 5a9772
		WLog_INFO(TAG, " PFC_FIRST_FRAG");
Packit 1fb8d4
Packit 1fb8d4
	if (header->common.pfc_flags & PFC_LAST_FRAG)
Packit Service 5a9772
		WLog_INFO(TAG, " PFC_LAST_FRAG");
Packit 1fb8d4
Packit 1fb8d4
	if (header->common.pfc_flags & PFC_PENDING_CANCEL)
Packit Service 5a9772
		WLog_INFO(TAG, " PFC_PENDING_CANCEL");
Packit 1fb8d4
Packit 1fb8d4
	if (header->common.pfc_flags & PFC_RESERVED_1)
Packit Service 5a9772
		WLog_INFO(TAG, " PFC_RESERVED_1");
Packit 1fb8d4
Packit 1fb8d4
	if (header->common.pfc_flags & PFC_CONC_MPX)
Packit Service 5a9772
		WLog_INFO(TAG, " PFC_CONC_MPX");
Packit 1fb8d4
Packit 1fb8d4
	if (header->common.pfc_flags & PFC_DID_NOT_EXECUTE)
Packit Service 5a9772
		WLog_INFO(TAG, " PFC_DID_NOT_EXECUTE");
Packit 1fb8d4
Packit 1fb8d4
	if (header->common.pfc_flags & PFC_OBJECT_UUID)
Packit Service 5a9772
		WLog_INFO(TAG, " PFC_OBJECT_UUID");
Packit 1fb8d4
Packit Service 5a9772
	WLog_INFO(TAG, " }");
Packit Service 5a9772
	WLog_INFO(TAG, "packed_drep[4]: %02" PRIX8 " %02" PRIX8 " %02" PRIX8 " %02" PRIX8 "",
Packit 1fb8d4
	          header->common.packed_drep[0], header->common.packed_drep[1],
Packit 1fb8d4
	          header->common.packed_drep[2], header->common.packed_drep[3]);
Packit Service 5a9772
	WLog_INFO(TAG, "frag_length: %" PRIu16 "", header->common.frag_length);
Packit Service 5a9772
	WLog_INFO(TAG, "auth_length: %" PRIu16 "", header->common.auth_length);
Packit Service 5a9772
	WLog_INFO(TAG, "call_id: %" PRIu32 "", header->common.call_id);
Packit 1fb8d4
Packit 1fb8d4
	if (header->common.ptype == PTYPE_RESPONSE)
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_INFO(TAG, "alloc_hint: %" PRIu32 "", header->response.alloc_hint);
Packit Service 5a9772
		WLog_INFO(TAG, "p_cont_id: %" PRIu16 "", header->response.p_cont_id);
Packit Service 5a9772
		WLog_INFO(TAG, "cancel_count: %" PRIu8 "", header->response.cancel_count);
Packit Service 5a9772
		WLog_INFO(TAG, "reserved: %" PRIu8 "", header->response.reserved);
Packit 1fb8d4
	}
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
void rpc_pdu_header_init(rdpRpc* rpc, rpcconn_hdr_t* header)
Packit 1fb8d4
{
Packit 1fb8d4
	header->common.rpc_vers = rpc->rpc_vers;
Packit 1fb8d4
	header->common.rpc_vers_minor = rpc->rpc_vers_minor;
Packit 1fb8d4
	header->common.packed_drep[0] = rpc->packed_drep[0];
Packit 1fb8d4
	header->common.packed_drep[1] = rpc->packed_drep[1];
Packit 1fb8d4
	header->common.packed_drep[2] = rpc->packed_drep[2];
Packit 1fb8d4
	header->common.packed_drep[3] = rpc->packed_drep[3];
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
UINT32 rpc_offset_align(UINT32* offset, UINT32 alignment)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT32 pad;
Packit 1fb8d4
	pad = *offset;
Packit 1fb8d4
	*offset = (*offset + alignment - 1) & ~(alignment - 1);
Packit 1fb8d4
	pad = *offset - pad;
Packit 1fb8d4
	return pad;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
UINT32 rpc_offset_pad(UINT32* offset, UINT32 pad)
Packit 1fb8d4
{
Packit 1fb8d4
	*offset += pad;
Packit 1fb8d4
	return pad;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * PDU Segments:
Packit 1fb8d4
 *  ________________________________
Packit 1fb8d4
 * |                                |
Packit 1fb8d4
 * |           PDU Header           |
Packit 1fb8d4
 * |________________________________|
Packit 1fb8d4
 * |                                |
Packit 1fb8d4
 * |                                |
Packit 1fb8d4
 * |            PDU Body            |
Packit 1fb8d4
 * |                                |
Packit 1fb8d4
 * |________________________________|
Packit 1fb8d4
 * |                                |
Packit 1fb8d4
 * |        Security Trailer        |
Packit 1fb8d4
 * |________________________________|
Packit 1fb8d4
 * |                                |
Packit 1fb8d4
 * |      Authentication Token      |
Packit 1fb8d4
 * |________________________________|
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * PDU Structure with verification trailer
Packit 1fb8d4
 *
Packit 1fb8d4
 * MUST only appear in a request PDU!
Packit 1fb8d4
 *  ________________________________
Packit 1fb8d4
 * |                                |
Packit 1fb8d4
 * |           PDU Header           |
Packit 1fb8d4
 * |________________________________| _______
Packit 1fb8d4
 * |                                |   /|\
Packit 1fb8d4
 * |                                |    |
Packit 1fb8d4
 * |           Stub Data            |    |
Packit 1fb8d4
 * |                                |    |
Packit 1fb8d4
 * |________________________________|    |
Packit 1fb8d4
 * |                                | PDU Body
Packit 1fb8d4
 * |            Stub Pad            |    |
Packit 1fb8d4
 * |________________________________|    |
Packit 1fb8d4
 * |                                |    |
Packit 1fb8d4
 * |      Verification Trailer      |    |
Packit 1fb8d4
 * |________________________________|    |
Packit 1fb8d4
 * |                                |    |
Packit 1fb8d4
 * |       Authentication Pad       |    |
Packit 1fb8d4
 * |________________________________| __\|/__
Packit 1fb8d4
 * |                                |
Packit 1fb8d4
 * |        Security Trailer        |
Packit 1fb8d4
 * |________________________________|
Packit 1fb8d4
 * |                                |
Packit 1fb8d4
 * |      Authentication Token      |
Packit 1fb8d4
 * |________________________________|
Packit 1fb8d4
 *
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Security Trailer:
Packit 1fb8d4
 *
Packit 1fb8d4
 * The sec_trailer structure MUST be placed at the end of the PDU, including past stub data,
Packit 1fb8d4
 * when present. The sec_trailer structure MUST be 4-byte aligned with respect to the beginning
Packit 1fb8d4
 * of the PDU. Padding octets MUST be used to align the sec_trailer structure if its natural
Packit 1fb8d4
 * beginning is not already 4-byte aligned.
Packit 1fb8d4
 *
Packit 1fb8d4
 * All PDUs that carry sec_trailer information share certain common fields:
Packit 1fb8d4
 * frag_length and auth_length. The beginning of the sec_trailer structure for each PDU MUST be
Packit 1fb8d4
 * calculated to start from offset (frag_length – auth_length – 8) from the beginning of the PDU.
Packit 1fb8d4
 *
Packit 1fb8d4
 * Immediately after the sec_trailer structure, there MUST be a BLOB carrying the authentication
Packit 1fb8d4
 * information produced by the security provider. This BLOB is called the authentication token and
Packit 1fb8d4
 * MUST be of size auth_length. The size MUST also be equal to the length from the first octet
Packit 1fb8d4
 * immediately after the sec_trailer structure all the way to the end of the fragment;
Packit 1fb8d4
 * the two values MUST be the same.
Packit 1fb8d4
 *
Packit 1fb8d4
 * A client or a server that (during composing of a PDU) has allocated more space for the
Packit 1fb8d4
 * authentication token than the security provider fills in SHOULD fill in the rest of
Packit 1fb8d4
 * the allocated space with zero octets. These zero octets are still considered to belong
Packit 1fb8d4
 * to the authentication token part of the PDU.
Packit 1fb8d4
 *
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
BOOL rpc_get_stub_data_info(rdpRpc* rpc, BYTE* buffer, UINT32* offset, UINT32* length)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT32 alloc_hint = 0;
Packit 1fb8d4
	rpcconn_hdr_t* header;
Packit 1fb8d4
	UINT32 frag_length;
Packit 1fb8d4
	UINT32 auth_length;
Packit 1fb8d4
	UINT32 auth_pad_length;
Packit 1fb8d4
	UINT32 sec_trailer_offset;
Packit 1fb8d4
	rpc_sec_trailer* sec_trailer;
Packit 1fb8d4
	*offset = RPC_COMMON_FIELDS_LENGTH;
Packit Service 5a9772
	header = ((rpcconn_hdr_t*)buffer);
Packit 1fb8d4
Packit 1fb8d4
	switch (header->common.ptype)
Packit 1fb8d4
	{
Packit 1fb8d4
		case PTYPE_RESPONSE:
Packit 1fb8d4
			*offset += 8;
Packit 1fb8d4
			rpc_offset_align(offset, 8);
Packit 1fb8d4
			alloc_hint = header->response.alloc_hint;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case PTYPE_REQUEST:
Packit 1fb8d4
			*offset += 4;
Packit 1fb8d4
			rpc_offset_align(offset, 8);
Packit 1fb8d4
			alloc_hint = header->request.alloc_hint;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case PTYPE_RTS:
Packit 1fb8d4
			*offset += 4;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		default:
Packit Service 5a9772
			WLog_ERR(TAG, "Unknown PTYPE: 0x%02" PRIX8 "", header->common.ptype);
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!length)
Packit 1fb8d4
		return TRUE;
Packit 1fb8d4
Packit 1fb8d4
	if (header->common.ptype == PTYPE_REQUEST)
Packit 1fb8d4
	{
Packit 1fb8d4
		UINT32 sec_trailer_offset;
Packit 1fb8d4
		sec_trailer_offset = header->common.frag_length - header->common.auth_length - 8;
Packit 1fb8d4
		*length = sec_trailer_offset - *offset;
Packit 1fb8d4
		return TRUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	frag_length = header->common.frag_length;
Packit 1fb8d4
	auth_length = header->common.auth_length;
Packit 1fb8d4
	sec_trailer_offset = frag_length - auth_length - 8;
Packit Service 5a9772
	sec_trailer = (rpc_sec_trailer*)&buffer[sec_trailer_offset];
Packit 1fb8d4
	auth_pad_length = sec_trailer->auth_pad_length;
Packit 1fb8d4
#if 0
Packit 1fb8d4
	WLog_DBG(TAG,
Packit 1fb8d4
	         "sec_trailer: type: %"PRIu8" level: %"PRIu8" pad_length: %"PRIu8" reserved: %"PRIu8" context_id: %"PRIu32"",
Packit 1fb8d4
	         sec_trailer->auth_type, sec_trailer->auth_level,
Packit 1fb8d4
	         sec_trailer->auth_pad_length, sec_trailer->auth_reserved,
Packit 1fb8d4
	         sec_trailer->auth_context_id);
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
	/**
Packit 1fb8d4
	 * According to [MS-RPCE], auth_pad_length is the number of padding
Packit 1fb8d4
	 * octets used to 4-byte align the security trailer, but in practice
Packit 1fb8d4
	 * we get values up to 15, which indicates 16-byte alignment.
Packit 1fb8d4
	 */
Packit 1fb8d4
Packit 1fb8d4
	if ((frag_length - (sec_trailer_offset + 8)) != auth_length)
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_ERR(TAG, "invalid auth_length: actual: %" PRIu32 ", expected: %" PRIu32 "",
Packit Service 5a9772
		         auth_length, (frag_length - (sec_trailer_offset + 8)));
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	*length = frag_length - auth_length - 24 - 8 - auth_pad_length;
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
SSIZE_T rpc_channel_read(RpcChannel* channel, wStream* s, size_t length)
Packit 1fb8d4
{
Packit 1fb8d4
	int status;
Packit 1fb8d4
Packit 1fb8d4
	if (!channel)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	status = BIO_read(channel->tls->bio, Stream_Pointer(s), length);
Packit 1fb8d4
Packit 1fb8d4
	if (status > 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		Stream_Seek(s, (size_t)status);
Packit 1fb8d4
		return status;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (BIO_should_retry(channel->tls->bio))
Packit 1fb8d4
		return 0;
Packit 1fb8d4
Packit Service 5a9772
	WLog_ERR(TAG, "rpc_channel_read: Out of retries");
Packit 1fb8d4
	return -1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
SSIZE_T rpc_channel_write(RpcChannel* channel, const BYTE* data, size_t length)
Packit 1fb8d4
{
Packit 1fb8d4
	int status;
Packit 1fb8d4
Packit 1fb8d4
	if (!channel)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	status = tls_write_all(channel->tls, data, length);
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL rpc_in_channel_transition_to_state(RpcInChannel* inChannel, CLIENT_IN_CHANNEL_STATE state)
Packit 1fb8d4
{
Packit 1fb8d4
	const char* str = "CLIENT_IN_CHANNEL_STATE_UNKNOWN";
Packit 1fb8d4
Packit 1fb8d4
	switch (state)
Packit 1fb8d4
	{
Packit 1fb8d4
		case CLIENT_IN_CHANNEL_STATE_INITIAL:
Packit 1fb8d4
			str = "CLIENT_IN_CHANNEL_STATE_INITIAL";
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case CLIENT_IN_CHANNEL_STATE_CONNECTED:
Packit 1fb8d4
			str = "CLIENT_IN_CHANNEL_STATE_CONNECTED";
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case CLIENT_IN_CHANNEL_STATE_SECURITY:
Packit 1fb8d4
			str = "CLIENT_IN_CHANNEL_STATE_SECURITY";
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case CLIENT_IN_CHANNEL_STATE_NEGOTIATED:
Packit 1fb8d4
			str = "CLIENT_IN_CHANNEL_STATE_NEGOTIATED";
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case CLIENT_IN_CHANNEL_STATE_OPENED:
Packit 1fb8d4
			str = "CLIENT_IN_CHANNEL_STATE_OPENED";
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case CLIENT_IN_CHANNEL_STATE_OPENED_A4W:
Packit 1fb8d4
			str = "CLIENT_IN_CHANNEL_STATE_OPENED_A4W";
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case CLIENT_IN_CHANNEL_STATE_FINAL:
Packit 1fb8d4
			str = "CLIENT_IN_CHANNEL_STATE_FINAL";
Packit 1fb8d4
			break;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!inChannel)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	inChannel->State = state;
Packit 1fb8d4
	WLog_DBG(TAG, "%s", str);
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static int rpc_channel_rpch_init(RpcClient* client, RpcChannel* channel, const char* inout)
Packit 1fb8d4
{
Packit 1fb8d4
	HttpContext* http;
Packit 1fb8d4
	rdpSettings* settings;
Packit 1fb8d4
Packit 1fb8d4
	if (!client || !channel || !inout || !client->context || !client->context->settings)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	settings = client->context->settings;
Packit 1fb8d4
	channel->ntlm = ntlm_new();
Packit Service 5a9772
	rts_generate_cookie((BYTE*)&channel->Cookie);
Packit 1fb8d4
	channel->client = client;
Packit 1fb8d4
Packit 1fb8d4
	if (!channel->ntlm)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	channel->http = http_context_new();
Packit 1fb8d4
Packit 1fb8d4
	if (!channel->http)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	http = channel->http;
Packit 1fb8d4
Packit 1fb8d4
	if (!http_context_set_method(http, inout) ||
Packit 1fb8d4
	    !http_context_set_uri(http, "/rpc/rpcproxy.dll?localhost:3388") ||
Packit 1fb8d4
	    !http_context_set_accept(http, "application/rpc") ||
Packit 1fb8d4
	    !http_context_set_cache_control(http, "no-cache") ||
Packit Service 5a9772
	    !http_context_set_connection(http, "Keep-Alive") ||
Packit Service 5a9772
	    !http_context_set_user_agent(http, "MSRPC") ||
Packit 1fb8d4
	    !http_context_set_host(http, settings->GatewayHostname) ||
Packit Service 5a9772
	    !http_context_set_pragma(http, "ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729, "
Packit Service 5a9772
	                                   "SessionId=fbd9c34f-397d-471d-a109-1b08cc554624"))
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static int rpc_in_channel_init(rdpRpc* rpc, RpcInChannel* inChannel)
Packit 1fb8d4
{
Packit 1fb8d4
	inChannel->State = CLIENT_IN_CHANNEL_STATE_INITIAL;
Packit 1fb8d4
	inChannel->BytesSent = 0;
Packit 1fb8d4
	inChannel->SenderAvailableWindow = rpc->ReceiveWindow;
Packit 1fb8d4
	inChannel->PingOriginator.ConnectionTimeout = 30;
Packit 1fb8d4
	inChannel->PingOriginator.KeepAliveInterval = 0;
Packit 1fb8d4
Packit 1fb8d4
	if (rpc_channel_rpch_init(rpc->client, &inChannel->common, "RPC_IN_DATA") < 0)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static RpcInChannel* rpc_in_channel_new(rdpRpc* rpc)
Packit 1fb8d4
{
Packit 1fb8d4
	RpcInChannel* inChannel = NULL;
Packit Service 5a9772
	inChannel = (RpcInChannel*)calloc(1, sizeof(RpcInChannel));
Packit 1fb8d4
Packit 1fb8d4
	if (inChannel)
Packit 1fb8d4
	{
Packit 1fb8d4
		rpc_in_channel_init(rpc, inChannel);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return inChannel;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
void rpc_channel_free(RpcChannel* channel)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!channel)
Packit 1fb8d4
		return;
Packit 1fb8d4
Packit 1fb8d4
	ntlm_free(channel->ntlm);
Packit 1fb8d4
	http_context_free(channel->http);
Packit 1fb8d4
	tls_free(channel->tls);
Packit 1fb8d4
	free(channel);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL rpc_out_channel_transition_to_state(RpcOutChannel* outChannel, CLIENT_OUT_CHANNEL_STATE state)
Packit 1fb8d4
{
Packit 1fb8d4
	const char* str = "CLIENT_OUT_CHANNEL_STATE_UNKNOWN";
Packit 1fb8d4
Packit 1fb8d4
	switch (state)
Packit 1fb8d4
	{
Packit 1fb8d4
		case CLIENT_OUT_CHANNEL_STATE_INITIAL:
Packit 1fb8d4
			str = "CLIENT_OUT_CHANNEL_STATE_INITIAL";
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case CLIENT_OUT_CHANNEL_STATE_CONNECTED:
Packit 1fb8d4
			str = "CLIENT_OUT_CHANNEL_STATE_CONNECTED";
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case CLIENT_OUT_CHANNEL_STATE_SECURITY:
Packit 1fb8d4
			str = "CLIENT_OUT_CHANNEL_STATE_SECURITY";
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case CLIENT_OUT_CHANNEL_STATE_NEGOTIATED:
Packit 1fb8d4
			str = "CLIENT_OUT_CHANNEL_STATE_NEGOTIATED";
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case CLIENT_OUT_CHANNEL_STATE_OPENED:
Packit 1fb8d4
			str = "CLIENT_OUT_CHANNEL_STATE_OPENED";
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case CLIENT_OUT_CHANNEL_STATE_OPENED_A6W:
Packit 1fb8d4
			str = "CLIENT_OUT_CHANNEL_STATE_OPENED_A6W";
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case CLIENT_OUT_CHANNEL_STATE_OPENED_A10W:
Packit 1fb8d4
			str = "CLIENT_OUT_CHANNEL_STATE_OPENED_A10W";
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case CLIENT_OUT_CHANNEL_STATE_OPENED_B3W:
Packit 1fb8d4
			str = "CLIENT_OUT_CHANNEL_STATE_OPENED_B3W";
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case CLIENT_OUT_CHANNEL_STATE_RECYCLED:
Packit 1fb8d4
			str = "CLIENT_OUT_CHANNEL_STATE_RECYCLED";
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case CLIENT_OUT_CHANNEL_STATE_FINAL:
Packit 1fb8d4
			str = "CLIENT_OUT_CHANNEL_STATE_FINAL";
Packit 1fb8d4
			break;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!outChannel)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	outChannel->State = state;
Packit 1fb8d4
	WLog_DBG(TAG, "%s", str);
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static int rpc_out_channel_init(rdpRpc* rpc, RpcOutChannel* outChannel)
Packit 1fb8d4
{
Packit 1fb8d4
	outChannel->State = CLIENT_OUT_CHANNEL_STATE_INITIAL;
Packit 1fb8d4
	outChannel->BytesReceived = 0;
Packit 1fb8d4
	outChannel->ReceiverAvailableWindow = rpc->ReceiveWindow;
Packit 1fb8d4
	outChannel->ReceiveWindow = rpc->ReceiveWindow;
Packit 1fb8d4
	outChannel->ReceiveWindowSize = rpc->ReceiveWindow;
Packit 1fb8d4
	outChannel->AvailableWindowAdvertised = rpc->ReceiveWindow;
Packit 1fb8d4
Packit 1fb8d4
	if (rpc_channel_rpch_init(rpc->client, &outChannel->common, "RPC_OUT_DATA") < 0)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
RpcOutChannel* rpc_out_channel_new(rdpRpc* rpc)
Packit 1fb8d4
{
Packit 1fb8d4
	RpcOutChannel* outChannel = NULL;
Packit Service 5a9772
	outChannel = (RpcOutChannel*)calloc(1, sizeof(RpcOutChannel));
Packit 1fb8d4
Packit 1fb8d4
	if (outChannel)
Packit 1fb8d4
	{
Packit 1fb8d4
		rpc_out_channel_init(rpc, outChannel);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return outChannel;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
BOOL rpc_virtual_connection_transition_to_state(rdpRpc* rpc, RpcVirtualConnection* connection,
Packit Service 5a9772
                                                VIRTUAL_CONNECTION_STATE state)
Packit 1fb8d4
{
Packit 1fb8d4
	const char* str = "VIRTUAL_CONNECTION_STATE_UNKNOWN";
Packit 1fb8d4
Packit 1fb8d4
	switch (state)
Packit 1fb8d4
	{
Packit 1fb8d4
		case VIRTUAL_CONNECTION_STATE_INITIAL:
Packit 1fb8d4
			str = "VIRTUAL_CONNECTION_STATE_INITIAL";
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT:
Packit 1fb8d4
			str = "VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT";
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case VIRTUAL_CONNECTION_STATE_WAIT_A3W:
Packit 1fb8d4
			str = "VIRTUAL_CONNECTION_STATE_WAIT_A3W";
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case VIRTUAL_CONNECTION_STATE_WAIT_C2:
Packit 1fb8d4
			str = "VIRTUAL_CONNECTION_STATE_WAIT_C2";
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case VIRTUAL_CONNECTION_STATE_OPENED:
Packit 1fb8d4
			str = "VIRTUAL_CONNECTION_STATE_OPENED";
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case VIRTUAL_CONNECTION_STATE_FINAL:
Packit 1fb8d4
			str = "VIRTUAL_CONNECTION_STATE_FINAL";
Packit 1fb8d4
			break;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!connection)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	connection->State = state;
Packit 1fb8d4
	WLog_DBG(TAG, "%s", str);
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static RpcVirtualConnection* rpc_virtual_connection_new(rdpRpc* rpc)
Packit 1fb8d4
{
Packit 1fb8d4
	RpcVirtualConnection* connection;
Packit Service 5a9772
	connection = (RpcVirtualConnection*)calloc(1, sizeof(RpcVirtualConnection));
Packit 1fb8d4
Packit 1fb8d4
	if (!connection)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit Service 5a9772
	rts_generate_cookie((BYTE*)&(connection->Cookie));
Packit Service 5a9772
	rts_generate_cookie((BYTE*)&(connection->AssociationGroupId));
Packit 1fb8d4
	connection->State = VIRTUAL_CONNECTION_STATE_INITIAL;
Packit 1fb8d4
	connection->DefaultInChannel = rpc_in_channel_new(rpc);
Packit 1fb8d4
Packit 1fb8d4
	if (!connection->DefaultInChannel)
Packit 1fb8d4
		goto out_free;
Packit 1fb8d4
Packit 1fb8d4
	connection->DefaultOutChannel = rpc_out_channel_new(rpc);
Packit 1fb8d4
Packit 1fb8d4
	if (!connection->DefaultOutChannel)
Packit 1fb8d4
		goto out_default_in;
Packit 1fb8d4
Packit 1fb8d4
	return connection;
Packit 1fb8d4
out_default_in:
Packit 1fb8d4
	free(connection->DefaultInChannel);
Packit 1fb8d4
out_free:
Packit 1fb8d4
	free(connection);
Packit 1fb8d4
	return NULL;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static void rpc_virtual_connection_free(RpcVirtualConnection* connection)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!connection)
Packit 1fb8d4
		return;
Packit 1fb8d4
Packit 1fb8d4
	rpc_channel_free(&connection->DefaultInChannel->common);
Packit 1fb8d4
	rpc_channel_free(&connection->NonDefaultInChannel->common);
Packit 1fb8d4
	rpc_channel_free(&connection->DefaultOutChannel->common);
Packit 1fb8d4
	rpc_channel_free(&connection->NonDefaultOutChannel->common);
Packit 1fb8d4
	free(connection);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL rpc_channel_tls_connect(RpcChannel* channel, int timeout)
Packit 1fb8d4
{
Packit 1fb8d4
	int sockfd;
Packit 1fb8d4
	rdpTls* tls;
Packit 1fb8d4
	int tlsStatus;
Packit 1fb8d4
	BIO* socketBio;
Packit 1fb8d4
	BIO* bufferedBio;
Packit 1fb8d4
	rdpContext* context;
Packit 1fb8d4
	rdpSettings* settings;
Packit 1fb8d4
	const char* proxyUsername;
Packit 1fb8d4
	const char* proxyPassword;
Packit 1fb8d4
Packit 1fb8d4
	if (!channel || !channel->client || !channel->client->context ||
Packit 1fb8d4
	    !channel->client->context->settings)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	context = channel->client->context;
Packit 1fb8d4
	settings = context->settings;
Packit 1fb8d4
	proxyUsername = settings->ProxyUsername;
Packit 1fb8d4
	proxyPassword = settings->ProxyPassword;
Packit 1fb8d4
	{
Packit 1fb8d4
		sockfd = freerdp_tcp_connect(context, settings, channel->client->host,
Packit 1fb8d4
		                             channel->client->port, timeout);
Packit 1fb8d4
Packit 1fb8d4
		if (sockfd < 0)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
	socketBio = BIO_new(BIO_s_simple_socket());
Packit 1fb8d4
Packit 1fb8d4
	if (!socketBio)
Packit 1fb8d4
	{
Packit 1fb8d4
		closesocket(sockfd);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	BIO_set_fd(socketBio, sockfd, BIO_CLOSE);
Packit 1fb8d4
	bufferedBio = BIO_new(BIO_s_buffered_socket());
Packit 1fb8d4
Packit 1fb8d4
	if (!bufferedBio)
Packit 1fb8d4
	{
Packit 1fb8d4
		BIO_free_all(socketBio);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	bufferedBio = BIO_push(bufferedBio, socketBio);
Packit 1fb8d4
Packit 1fb8d4
	if (!BIO_set_nonblock(bufferedBio, TRUE))
Packit 1fb8d4
	{
Packit 1fb8d4
		BIO_free_all(bufferedBio);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (channel->client->isProxy)
Packit 1fb8d4
	{
Packit Service 5a9772
		if (!proxy_connect(settings, bufferedBio, proxyUsername, proxyPassword,
Packit Service 5a9772
		                   settings->GatewayHostname, settings->GatewayPort))
Packit 1fb8d4
		{
Packit 1fb8d4
			BIO_free_all(bufferedBio);
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	channel->bio = bufferedBio;
Packit 1fb8d4
	tls = channel->tls = tls_new(settings);
Packit 1fb8d4
Packit 1fb8d4
	if (!tls)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	tls->hostname = settings->GatewayHostname;
Packit 1fb8d4
	tls->port = settings->GatewayPort;
Packit 1fb8d4
	tls->isGatewayTransport = TRUE;
Packit 1fb8d4
	tlsStatus = tls_connect(tls, bufferedBio);
Packit 1fb8d4
Packit 1fb8d4
	if (tlsStatus < 1)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (tlsStatus < 0)
Packit 1fb8d4
		{
Packit Service 5a9772
			freerdp_set_last_error_if_not(context, FREERDP_ERROR_TLS_CONNECT_FAILED);
Packit 1fb8d4
		}
Packit 1fb8d4
		else
Packit 1fb8d4
		{
Packit Service 5a9772
			freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_CANCELLED);
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static int rpc_in_channel_connect(RpcInChannel* inChannel, int timeout)
Packit 1fb8d4
{
Packit 1fb8d4
	rdpContext* context;
Packit 1fb8d4
Packit 1fb8d4
	if (!inChannel || !inChannel->common.client || !inChannel->common.client->context)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	context = inChannel->common.client->context;
Packit 1fb8d4
Packit 1fb8d4
	/* Connect IN Channel */
Packit 1fb8d4
Packit 1fb8d4
	if (!rpc_channel_tls_connect(&inChannel->common, timeout))
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	rpc_in_channel_transition_to_state(inChannel, CLIENT_IN_CHANNEL_STATE_CONNECTED);
Packit 1fb8d4
Packit 1fb8d4
	if (!rpc_ncacn_http_ntlm_init(context, &inChannel->common))
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	/* Send IN Channel Request */
Packit 1fb8d4
Packit 1fb8d4
	if (!rpc_ncacn_http_send_in_channel_request(&inChannel->common))
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "rpc_ncacn_http_send_in_channel_request failure");
Packit 1fb8d4
		return -1;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!rpc_in_channel_transition_to_state(inChannel, CLIENT_IN_CHANNEL_STATE_SECURITY))
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static int rpc_out_channel_connect(RpcOutChannel* outChannel, int timeout)
Packit 1fb8d4
{
Packit 1fb8d4
	rdpContext* context;
Packit 1fb8d4
Packit 1fb8d4
	if (!outChannel || !outChannel->common.client || !outChannel->common.client->context)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	context = outChannel->common.client->context;
Packit 1fb8d4
Packit 1fb8d4
	/* Connect OUT Channel */
Packit 1fb8d4
Packit 1fb8d4
	if (!rpc_channel_tls_connect(&outChannel->common, timeout))
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_CONNECTED);
Packit 1fb8d4
Packit 1fb8d4
	if (!rpc_ncacn_http_ntlm_init(context, &outChannel->common))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	/* Send OUT Channel Request */
Packit 1fb8d4
Packit 1fb8d4
	if (!rpc_ncacn_http_send_out_channel_request(&outChannel->common, FALSE))
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "rpc_ncacn_http_send_out_channel_request failure");
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_SECURITY);
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
int rpc_out_channel_replacement_connect(RpcOutChannel* outChannel, int timeout)
Packit 1fb8d4
{
Packit 1fb8d4
	rdpContext* context;
Packit 1fb8d4
Packit 1fb8d4
	if (!outChannel || !outChannel->common.client || !outChannel->common.client->context)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	context = outChannel->common.client->context;
Packit 1fb8d4
Packit 1fb8d4
	/* Connect OUT Channel */
Packit 1fb8d4
Packit 1fb8d4
	if (!rpc_channel_tls_connect(&outChannel->common, timeout))
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_CONNECTED);
Packit 1fb8d4
Packit Service 5a9772
	if (!rpc_ncacn_http_ntlm_init(context, (RpcChannel*)outChannel))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	/* Send OUT Channel Request */
Packit 1fb8d4
Packit 1fb8d4
	if (!rpc_ncacn_http_send_out_channel_request(&outChannel->common, TRUE))
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "rpc_ncacn_http_send_out_channel_request failure");
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_SECURITY);
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL rpc_connect(rdpRpc* rpc, int timeout)
Packit 1fb8d4
{
Packit 1fb8d4
	RpcInChannel* inChannel;
Packit 1fb8d4
	RpcOutChannel* outChannel;
Packit 1fb8d4
	RpcVirtualConnection* connection;
Packit 1fb8d4
	rpc->VirtualConnection = rpc_virtual_connection_new(rpc);
Packit 1fb8d4
Packit 1fb8d4
	if (!rpc->VirtualConnection)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	connection = rpc->VirtualConnection;
Packit 1fb8d4
	inChannel = connection->DefaultInChannel;
Packit 1fb8d4
	outChannel = connection->DefaultOutChannel;
Packit 1fb8d4
	rpc_virtual_connection_transition_to_state(rpc, connection, VIRTUAL_CONNECTION_STATE_INITIAL);
Packit 1fb8d4
Packit 1fb8d4
	if (rpc_in_channel_connect(inChannel, timeout) < 0)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (rpc_out_channel_connect(outChannel, timeout) < 0)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
rdpRpc* rpc_new(rdpTransport* transport)
Packit 1fb8d4
{
Packit Service 5a9772
	rdpRpc* rpc = (rdpRpc*)calloc(1, sizeof(rdpRpc));
Packit 1fb8d4
Packit 1fb8d4
	if (!rpc)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	rpc->State = RPC_CLIENT_STATE_INITIAL;
Packit 1fb8d4
	rpc->transport = transport;
Packit 1fb8d4
	rpc->settings = transport->settings;
Packit 1fb8d4
	rpc->context = transport->context;
Packit 1fb8d4
	rpc->SendSeqNum = 0;
Packit 1fb8d4
	rpc->ntlm = ntlm_new();
Packit 1fb8d4
Packit 1fb8d4
	if (!rpc->ntlm)
Packit 1fb8d4
		goto out_free;
Packit 1fb8d4
Packit 1fb8d4
	rpc->PipeCallId = 0;
Packit 1fb8d4
	rpc->StubCallId = 0;
Packit 1fb8d4
	rpc->StubFragCount = 0;
Packit 1fb8d4
	rpc->rpc_vers = 5;
Packit 1fb8d4
	rpc->rpc_vers_minor = 0;
Packit 1fb8d4
	/* little-endian data representation */
Packit 1fb8d4
	rpc->packed_drep[0] = 0x10;
Packit 1fb8d4
	rpc->packed_drep[1] = 0x00;
Packit 1fb8d4
	rpc->packed_drep[2] = 0x00;
Packit 1fb8d4
	rpc->packed_drep[3] = 0x00;
Packit 1fb8d4
	rpc->max_xmit_frag = 0x0FF8;
Packit 1fb8d4
	rpc->max_recv_frag = 0x0FF8;
Packit 1fb8d4
	rpc->ReceiveWindow = 0x00010000;
Packit 1fb8d4
	rpc->ChannelLifetime = 0x40000000;
Packit 1fb8d4
	rpc->KeepAliveInterval = 300000;
Packit 1fb8d4
	rpc->CurrentKeepAliveInterval = rpc->KeepAliveInterval;
Packit 1fb8d4
	rpc->CurrentKeepAliveTime = 0;
Packit 1fb8d4
	rpc->CallId = 2;
Packit 1fb8d4
	rpc->client = rpc_client_new(rpc->context, rpc->max_recv_frag);
Packit 1fb8d4
Packit 1fb8d4
	if (!rpc->client)
Packit 1fb8d4
		goto out_free;
Packit 1fb8d4
Packit 1fb8d4
	return rpc;
Packit 1fb8d4
out_free:
Packit 1fb8d4
	rpc_free(rpc);
Packit 1fb8d4
	return NULL;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
void rpc_free(rdpRpc* rpc)
Packit 1fb8d4
{
Packit 1fb8d4
	if (rpc)
Packit 1fb8d4
	{
Packit 1fb8d4
		rpc_client_free(rpc->client);
Packit 1fb8d4
		ntlm_free(rpc->ntlm);
Packit 1fb8d4
		rpc_virtual_connection_free(rpc->VirtualConnection);
Packit 1fb8d4
		free(rpc);
Packit 1fb8d4
	}
Packit 1fb8d4
}