Esempio n. 1
0
BOOL rdg_in_channel_recv(rdpRdg* rdg)
{
	BOOL status = TRUE;
	HttpResponse* response = NULL;

	switch (rdg->state)
	{
		case RDG_CLIENT_STATE_IN_CHANNEL_REQUEST:
			response = http_response_recv(rdg->tlsIn);

			if (!response)
				return FALSE;

			status = rdg_process_in_channel_response(rdg, response);
			http_response_free(response);
			break;

		case RDG_CLIENT_STATE_IN_CHANNEL_AUTHORIZE:
			response = http_response_recv(rdg->tlsIn);

			if (!response)
				return FALSE;

			status = rdg_process_in_channel_authorization(rdg, response);
			http_response_free(response);
			break;
	}

	return status;
}
Esempio n. 2
0
int rpc_ncacn_http_recv_in_channel_response(rdpRpc* rpc)
{
	char* token64;
	int ntlm_token_length = 0;
	BYTE* ntlm_token_data = NULL;
	HttpResponse* http_response;
	rdpNtlm* ntlm = rpc->NtlmHttpIn->ntlm;

	http_response = http_response_recv(rpc->TlsIn);

	if (!http_response)
		return -1;

	if (ListDictionary_Contains(http_response->Authenticates, "NTLM"))
	{
		token64 = ListDictionary_GetItemValue(http_response->Authenticates, "NTLM");

		if (!token64)
			goto out;

		crypto_base64_decode(token64, strlen(token64), &ntlm_token_data, &ntlm_token_length);
	}

out:
	ntlm->inputBuffer[0].pvBuffer = ntlm_token_data;
	ntlm->inputBuffer[0].cbBuffer = ntlm_token_length;
	http_response_free(http_response);

	return 0;
}
Esempio n. 3
0
BOOL rts_connect(rdpRpc* rpc)
{
	int status;
	RTS_PDU rts_pdu;
	HttpResponse* http_response;

	if (!rpc_ntlm_http_out_connect(rpc))
	{
		printf("rpc_out_connect_http error!\n");
		return FALSE;
	}

	if (!rts_send_CONN_A1_pdu(rpc))
	{
		printf("rpc_send_CONN_A1_pdu error!\n");
		return FALSE;
	}

	if (!rpc_ntlm_http_in_connect(rpc))
	{
		printf("rpc_in_connect_http error!\n");
		return FALSE;
	}

	if (!rts_send_CONN_B1_pdu(rpc))
	{
		printf("rpc_send_CONN_B1_pdu error!\n");
		return FALSE;
	}

	/* Receive OUT Channel Response */
	http_response = http_response_recv(rpc->tls_out);

	if (http_response->StatusCode != 200)
	{
		printf("rts_connect error!\n");
		http_response_print(http_response);
		http_response_free(http_response) ;
		return FALSE;
	}

	http_response_print(http_response);

	http_response_free(http_response);

	/* Receive CONN_A3 RTS PDU */
	status = rts_recv_pdu(rpc, &rts_pdu);

	/* Receive CONN_C2 RTS PDU */
	status = rts_recv_pdu(rpc, &rts_pdu);

	return TRUE;
}
Esempio n. 4
0
BOOL rdg_out_channel_recv(rdpRdg* rdg)
{
	wStream* s;
	BOOL status = TRUE;
	HttpResponse* response = NULL;

	switch (rdg->state)
	{
		case RDG_CLIENT_STATE_OUT_CHANNEL_REQUEST:
			response = http_response_recv(rdg->tlsOut);
			if (!response)
			{
				return FALSE;
			}
			status = rdg_process_out_channel_response(rdg, response);
			http_response_free(response);
			break;

		case RDG_CLIENT_STATE_OUT_CHANNEL_AUTHORIZE:
			response = http_response_recv(rdg->tlsOut);
			if (!response)
			{
				return FALSE;
			}
			status = rdg_process_out_channel_authorization(rdg, response);
			http_response_free(response);
			break;

		default:
			s = rdg_receive_packet(rdg);
			if (s)
			{
				status = rdg_process_packet(rdg, s);
				Stream_Free(s, TRUE);
			}
	}

	return status;
}
Esempio n. 5
0
boolean rpc_ntlm_http_in_connect(rdpRpc* rpc)
{
	STREAM* s;
	int ntlm_token_length;
	uint8* ntlm_token_data;
	HttpResponse* http_response;
	rdpNtlm* ntlm = rpc->ntlm_http_in->ntlm;

	ntlm_client_init(ntlm, true, rpc->settings->username,
			rpc->settings->domain, rpc->settings->password);

	ntlm_authenticate(ntlm);

	s = rpc_ntlm_http_request(rpc, &ntlm->outputBuffer, 0, TSG_CHANNEL_IN);

	/* Send IN Channel Request */

	DEBUG_RPC("\n%s", s->data);
	tls_write_all(rpc->tls_in, s->data, s->size);
	stream_free(s);

	/* Receive IN Channel Response */

	http_response = http_response_recv(rpc->tls_in);

	ntlm_token_data = NULL;
	crypto_base64_decode((uint8*) http_response->AuthParam, strlen(http_response->AuthParam),
			&ntlm_token_data, &ntlm_token_length);

	ntlm->inputBuffer.pvBuffer = ntlm_token_data;
	ntlm->inputBuffer.cbBuffer = ntlm_token_length;

	ntlm_authenticate(ntlm);

	http_response_free(http_response);

	s = rpc_ntlm_http_request(rpc, &ntlm->outputBuffer, 0x40000000, TSG_CHANNEL_IN);

	/* Send IN Channel Request */

	DEBUG_RPC("\n%s", s->data);
	tls_write_all(rpc->tls_in, s->data, s->size);
	stream_free(s);

	ntlm_client_uninit(ntlm);
	ntlm_free(ntlm);

	return true;
}
Esempio n. 6
0
int rpc_ncacn_http_recv_in_channel_response(rdpRpc* rpc)
{
	int ntlm_token_length;
	BYTE* ntlm_token_data;
	HttpResponse* http_response;
	rdpNtlm* ntlm = rpc->NtlmHttpIn->ntlm;

	http_response = http_response_recv(rpc->TlsIn);

	ntlm_token_data = NULL;
	crypto_base64_decode((BYTE*) http_response->AuthParam, strlen(http_response->AuthParam),
			&ntlm_token_data, &ntlm_token_length);

	ntlm->inputBuffer.pvBuffer = ntlm_token_data;
	ntlm->inputBuffer.cbBuffer = ntlm_token_length;

	http_response_free(http_response);

	return 0;
}
Esempio n. 7
0
int rpc_ncacn_http_recv_out_channel_response(rdpRpc* rpc)
{
	int ntlm_token_length = 0;
	BYTE* ntlm_token_data;
	HttpResponse* http_response;
	rdpNtlm* ntlm = rpc->NtlmHttpOut->ntlm;

	http_response = http_response_recv(rpc->TlsOut);

	ntlm_token_data = NULL;
	if (http_response && http_response->AuthParam)
	{
		crypto_base64_decode((BYTE*) http_response->AuthParam, strlen(http_response->AuthParam),
				&ntlm_token_data, &ntlm_token_length);
	}

	ntlm->inputBuffer[0].pvBuffer = ntlm_token_data;
	ntlm->inputBuffer[0].cbBuffer = ntlm_token_length;

	http_response_free(http_response);

	return 0;
}
Esempio n. 8
0
static BOOL rdg_establish_data_connection(rdpRdg* rdg, rdpTls* tls,
        const char* method, const char* peerAddress, int timeout, BOOL* rpcFallback)
{
	HttpResponse* response = NULL;
	int statusCode;
	int bodyLength;

	if (!rdg_tls_connect(rdg, tls, peerAddress, timeout))
		return FALSE;

	if (rdg->extAuth == HTTP_EXTENDED_AUTH_NONE)
	{
		if (!rdg_ntlm_init(rdg, tls))
			return FALSE;

		if (!rdg_send_http_request(rdg, tls, method, NULL))
			return FALSE;

		response = http_response_recv(tls);

		if (!response)
			return FALSE;

		if (response->StatusCode == HTTP_STATUS_NOT_FOUND)
		{
			WLog_INFO(TAG, "RD Gateway does not support HTTP transport.");

			if (rpcFallback) *rpcFallback = TRUE;

			http_response_free(response);
			return FALSE;
		}

		if (!rdg_handle_ntlm_challenge(rdg->ntlm, response))
		{
			http_response_free(response);
			return FALSE;
		}

		http_response_free(response);
	}

	if (!rdg_send_http_request(rdg, tls, method, NULL))
		return FALSE;

	ntlm_free(rdg->ntlm);
	rdg->ntlm = NULL;
	response = http_response_recv(tls);

	if (!response)
		return FALSE;

	statusCode = response->StatusCode;
	bodyLength = response->BodyLength;
	http_response_free(response);
	WLog_DBG(TAG, "%s authorization result: %d", method, statusCode);

	if (statusCode != HTTP_STATUS_OK)
		return FALSE;

	if (strcmp(method, "RDG_OUT_DATA") == 0)
	{
		if (!rdg_skip_seed_payload(tls, bodyLength))
			return FALSE;
	}
	else
	{
		if (!rdg_send_http_request(rdg, tls, method, "chunked"))
			return FALSE;
	}

	return TRUE;
}
Esempio n. 9
0
File: rts.c Progetto: orosam/FreeRDP
BOOL rts_connect(rdpRpc* rpc)
{
	RPC_PDU* pdu;
	rpcconn_rts_hdr_t* rts;
	HttpResponse* http_response;
	freerdp* instance = (freerdp*) rpc->settings->instance;
	rdpContext* context = instance->context;

	/**
	 * 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;
	WLog_DBG(TAG, "VIRTUAL_CONNECTION_STATE_INITIAL");

	rpc->client->SynchronousSend = TRUE;
	rpc->client->SynchronousReceive = TRUE;

	if (!rpc_ntlm_http_out_connect(rpc))
	{
		WLog_ERR(TAG, "rpc_out_connect_http error!");
		return FALSE;
	}

	if (rts_send_CONN_A1_pdu(rpc) != 0)
	{
		WLog_ERR(TAG, "rpc_send_CONN_A1_pdu error!");
		return FALSE;
	}

	if (!rpc_ntlm_http_in_connect(rpc))
	{
		WLog_ERR(TAG, "rpc_in_connect_http error!");
		return FALSE;
	}

	if (rts_send_CONN_B1_pdu(rpc) < 0)
	{
		WLog_ERR(TAG, "rpc_send_CONN_B1_pdu error!");
		return FALSE;
	}

	rpc->VirtualConnection->State = VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT;
	WLog_DBG(TAG, "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)
	{
		WLog_ERR(TAG, "unable to retrieve OUT Channel Response!");
		return FALSE;
	}

	if (http_response->StatusCode != HTTP_STATUS_OK)
	{
		WLog_ERR(TAG, "error! Status Code: %d", 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(context))
			{
				freerdp_set_last_error(context, FREERDP_ERROR_AUTHENTICATION_FAILED);
			}
		}

		return FALSE;
	}

	if (http_response->bodyLen)
	{
		/* inject bytes we have read in the body as a received packet for the RPC client */
		rpc->client->RecvFrag = rpc_client_fragment_pool_take(rpc);
		Stream_EnsureCapacity(rpc->client->RecvFrag, http_response->bodyLen);
		CopyMemory(rpc->client->RecvFrag, http_response->BodyContent,  http_response->bodyLen);
	}

	//http_response_print(http_response);
	http_response_free(http_response);

	rpc->VirtualConnection->State = VIRTUAL_CONNECTION_STATE_WAIT_A3W;
	WLog_DBG(TAG, "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))
	{
		WLog_ERR(TAG, "unexpected RTS PDU: Expected CONN/A3");
		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;
	WLog_DBG(TAG, "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))
	{
		WLog_ERR(TAG, "unexpected RTS PDU: Expected CONN/C2");
		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;
	WLog_DBG(TAG, "VIRTUAL_CONNECTION_STATE_OPENED");

	rpc->client->SynchronousSend = TRUE;
	rpc->client->SynchronousReceive = TRUE;

	return TRUE;
}
Esempio n. 10
0
File: rpc.c Progetto: atong/FreeRDP
BOOL rpc_ntlm_http_in_connect(rdpRpc* rpc)
{
    STREAM* s;
    rdpSettings* settings;
    int ntlm_token_length;
    BYTE* ntlm_token_data;
    HttpResponse* http_response;
    rdpNtlm* ntlm = rpc->ntlm_http_in->ntlm;

    settings = rpc->settings;

    if (settings->tsg_same_credentials)
    {
        ntlm_client_init(ntlm, TRUE, settings->username,
                         settings->domain, settings->password);
        ntlm_client_make_spn(ntlm, _T("HTTP"), settings->tsg_hostname);
    }
    else
    {
        ntlm_client_init(ntlm, TRUE, settings->tsg_username,
                         settings->tsg_domain, settings->tsg_password);
        ntlm_client_make_spn(ntlm, _T("HTTP"), settings->tsg_hostname);
    }

    ntlm_authenticate(ntlm);

    s = rpc_ntlm_http_request(rpc, &ntlm->outputBuffer, 0, TSG_CHANNEL_IN);

    /* Send IN Channel Request */

    DEBUG_RPC("\n%s", s->data);
    tls_write_all(rpc->tls_in, s->data, s->size);
    stream_free(s);

    /* Receive IN Channel Response */

    http_response = http_response_recv(rpc->tls_in);

    ntlm_token_data = NULL;
    crypto_base64_decode((BYTE*) http_response->AuthParam, strlen(http_response->AuthParam),
                         &ntlm_token_data, &ntlm_token_length);

    ntlm->inputBuffer.pvBuffer = ntlm_token_data;
    ntlm->inputBuffer.cbBuffer = ntlm_token_length;

    ntlm_authenticate(ntlm);

    http_response_free(http_response);

    s = rpc_ntlm_http_request(rpc, &ntlm->outputBuffer, 0x40000000, TSG_CHANNEL_IN);

    /* Send IN Channel Request */

    DEBUG_RPC("\n%s", s->data);
    tls_write_all(rpc->tls_in, s->data, s->size);
    stream_free(s);

    ntlm_client_uninit(ntlm);
    ntlm_free(ntlm);

    return TRUE;
}