Merge branch 'master' of git@github.com:FreeRDP/FreeRDP-1.0
This commit is contained in:
commit
9c5eecff3d
@ -61,16 +61,19 @@ static int test_finished = 0;
|
||||
static int
|
||||
packet_received(rdpTransport * transport, STREAM * stream, void * extra)
|
||||
{
|
||||
#if 0
|
||||
uint16 length;
|
||||
length = tpkt_read_header(stream);
|
||||
CU_ASSERT(length == 19);
|
||||
freerdp_hexdump(stream->data, length);
|
||||
test_finished = 1;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_transport(void)
|
||||
{
|
||||
#if 0
|
||||
rdpTransport * transport;
|
||||
STREAM * stream;
|
||||
int r;
|
||||
@ -96,4 +99,5 @@ void test_transport(void)
|
||||
CU_ASSERT(r == True);
|
||||
|
||||
transport_free(transport);
|
||||
#endif
|
||||
}
|
||||
|
@ -37,6 +37,8 @@ set(LIBFREERDP_CORE_SRCS
|
||||
settings.c
|
||||
connection.c
|
||||
connection.h
|
||||
rdp.c
|
||||
rdp.h
|
||||
per.c
|
||||
per.h
|
||||
tcp.c
|
||||
|
@ -34,14 +34,28 @@
|
||||
* |<-----------------------MCS Channel Join Confirm PDU---------------------|
|
||||
* |----------------------------Security Exchange PDU----------------------->|
|
||||
* |-------------------------------Client Info PDU-------------------------->|
|
||||
* |<---------------------License Error PDU - Valid Client-------------------|
|
||||
* |<-----------------------------Demand Active PDU--------------------------|
|
||||
* |------------------------------Confirm Active PDU------------------------>|
|
||||
* |-------------------------------Synchronize PDU-------------------------->|
|
||||
* |---------------------------Control PDU - Cooperate---------------------->|
|
||||
* |------------------------Control PDU - Request Control------------------->|
|
||||
* |--------------------------Persistent Key List PDU(s)-------------------->|
|
||||
* |--------------------------------Font List PDU--------------------------->|
|
||||
* |<------------------------------Synchronize PDU---------------------------|
|
||||
* |<--------------------------Control PDU - Cooperate-----------------------|
|
||||
* |<-----------------------Control PDU - Granted Control--------------------|
|
||||
* |<-------------------------------Font Map PDU-----------------------------|
|
||||
*
|
||||
*/
|
||||
|
||||
void connection_client_connect(rdpConnection* connection)
|
||||
{
|
||||
int i;
|
||||
STREAM* s;
|
||||
uint16 channelId;
|
||||
|
||||
connection->settings->autologon = 1;
|
||||
connection->transport = transport_new(connection->settings);
|
||||
connection->nego = nego_new(connection->transport);
|
||||
|
||||
@ -74,7 +88,8 @@ void connection_client_connect(rdpConnection* connection)
|
||||
|
||||
connection_send_client_info(connection);
|
||||
|
||||
mcs_recv(connection->mcs);
|
||||
s = transport_recv_stream_init(connection->transport, 4096);
|
||||
transport_read(connection->transport, s);
|
||||
}
|
||||
|
||||
void connection_write_system_time(STREAM* s, SYSTEM_TIME* system_time)
|
||||
@ -251,15 +266,21 @@ void connection_write_info_packet(STREAM* s, rdpSettings* settings)
|
||||
uint8* workingDir;
|
||||
uint16 cbWorkingDir;
|
||||
|
||||
flags = INFO_UNICODE |
|
||||
flags = INFO_MOUSE |
|
||||
INFO_UNICODE |
|
||||
INFO_LOGONERRORS |
|
||||
INFO_LOGONNOTIFY |
|
||||
INFO_MAXIMIZESHELL |
|
||||
INFO_ENABLEWINDOWSKEY |
|
||||
INFO_DISABLECTRLALTDEL |
|
||||
RNS_INFO_AUDIOCAPTURE;
|
||||
|
||||
if (settings->autologon)
|
||||
flags |= INFO_AUTOLOGON;
|
||||
|
||||
if (settings->console_audio)
|
||||
flags |= INFO_REMOTECONSOLEAUDIO;
|
||||
|
||||
if (settings->compression)
|
||||
flags |= INFO_COMPRESSION | PACKET_COMPR_TYPE_64K;
|
||||
|
||||
@ -321,17 +342,14 @@ void connection_send_client_info(rdpConnection* connection)
|
||||
{
|
||||
STREAM* s;
|
||||
int length;
|
||||
s = stream_new(1024);
|
||||
|
||||
uint8 *bm, *em;
|
||||
|
||||
s = transport_send_stream_init(connection->transport, 1024);
|
||||
|
||||
stream_get_mark(s, bm);
|
||||
stream_seek(s, 15);
|
||||
|
||||
/* security header */
|
||||
stream_write_uint16(s, SEC_INFO_PKT); /* flags */
|
||||
stream_write_uint16(s, 0); /* flagsHi */
|
||||
|
||||
rdp_write_security_header(s, SEC_INFO_PKT);
|
||||
connection_write_info_packet(s, connection->settings);
|
||||
|
||||
stream_get_mark(s, em);
|
||||
@ -348,7 +366,7 @@ void connection_send_client_info(rdpConnection* connection)
|
||||
|
||||
stream_set_mark(s, em);
|
||||
|
||||
tls_write(connection->transport->tls, s->data, stream_get_length(s));
|
||||
transport_write(connection->transport, s);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -20,6 +20,7 @@
|
||||
#ifndef __CONNECTION_H
|
||||
#define __CONNECTION_H
|
||||
|
||||
#include "rdp.h"
|
||||
#include "tpkt.h"
|
||||
#include "tpdu.h"
|
||||
#include "nego.h"
|
||||
@ -58,19 +59,6 @@
|
||||
#define PACKET_COMPR_TYPE_RDP6 0x00000300
|
||||
#define PACKET_COMPR_TYPE_RDP61 0x00000400
|
||||
|
||||
/* Security Header Flags */
|
||||
#define SEC_EXCHANGE_PKT 0x0001
|
||||
#define SEC_ENCRYPT 0x0008
|
||||
#define SEC_RESET_SEQNO 0x0010
|
||||
#define SEC_IGNORE_SEQNO 0x0020
|
||||
#define SEC_INFO_PKT 0x0040
|
||||
#define SEC_LICENSE_PKT 0x0080
|
||||
#define SEC_LICENSE_ENCRYPT_CS 0x0200
|
||||
#define SEC_LICENSE_ENCRYPT_SC 0x0200
|
||||
#define SEC_REDIRECTION_PKT 0x0400
|
||||
#define SEC_SECURE_CHECKSUM 0x0800
|
||||
#define SEC_FLAGSHI_VALID 0x8000
|
||||
|
||||
struct rdp_connection
|
||||
{
|
||||
struct rdp_mcs* mcs;
|
||||
|
@ -340,13 +340,12 @@ void credssp_encode_ts_credentials(rdpCredssp* credssp)
|
||||
|
||||
void credssp_send(rdpCredssp* credssp, BLOB* negoToken, BLOB* pubKeyAuth, BLOB* authInfo)
|
||||
{
|
||||
STREAM* s;
|
||||
size_t size;
|
||||
TSRequest_t *ts_request;
|
||||
OCTET_STRING_t *nego_token;
|
||||
asn_enc_rval_t enc_rval;
|
||||
|
||||
char* buffer;
|
||||
size_t size;
|
||||
|
||||
ts_request = calloc(1, sizeof(TSRequest_t));
|
||||
ts_request->version = 2;
|
||||
|
||||
@ -380,17 +379,17 @@ void credssp_send(rdpCredssp* credssp, BLOB* negoToken, BLOB* pubKeyAuth, BLOB*
|
||||
if (enc_rval.encoded != -1)
|
||||
{
|
||||
size = enc_rval.encoded;
|
||||
buffer = xmalloc(size);
|
||||
s = transport_send_stream_init(credssp->transport, size);
|
||||
|
||||
enc_rval = der_encode_to_buffer(&asn_DEF_TSRequest, ts_request, buffer, size);
|
||||
enc_rval = der_encode_to_buffer(&asn_DEF_TSRequest, ts_request, s->data, size);
|
||||
|
||||
if (enc_rval.encoded != -1)
|
||||
{
|
||||
tls_write(credssp->transport->tls, buffer, size);
|
||||
s->p = s->data + size;
|
||||
transport_write(credssp->transport, s);
|
||||
}
|
||||
|
||||
asn_DEF_TSRequest.free_struct(&asn_DEF_TSRequest, ts_request, 0);
|
||||
xfree(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -405,19 +404,18 @@ void credssp_send(rdpCredssp* credssp, BLOB* negoToken, BLOB* pubKeyAuth, BLOB*
|
||||
|
||||
int credssp_recv(rdpCredssp* credssp, BLOB* negoToken, BLOB* pubKeyAuth, BLOB* authInfo)
|
||||
{
|
||||
int bytes_read;
|
||||
int size = 2048;
|
||||
char *recv_buffer;
|
||||
STREAM* s;
|
||||
int status;
|
||||
asn_dec_rval_t dec_rval;
|
||||
TSRequest_t *ts_request = 0;
|
||||
|
||||
recv_buffer = xmalloc(size);
|
||||
bytes_read = tls_read(credssp->transport->tls, recv_buffer, size);
|
||||
s = transport_recv_stream_init(credssp->transport, 2048);
|
||||
status = transport_read(credssp->transport, s);
|
||||
|
||||
if (bytes_read < 0)
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
dec_rval = ber_decode(0, &asn_DEF_TSRequest, (void **)&ts_request, recv_buffer, bytes_read);
|
||||
dec_rval = ber_decode(0, &asn_DEF_TSRequest, (void **)&ts_request, s->data, status);
|
||||
|
||||
if(dec_rval.code == RC_OK)
|
||||
{
|
||||
@ -444,7 +442,6 @@ int credssp_recv(rdpCredssp* credssp, BLOB* negoToken, BLOB* pubKeyAuth, BLOB* a
|
||||
asn_DEF_TSRequest.free_struct(&asn_DEF_TSRequest, ts_request, 0);
|
||||
}
|
||||
|
||||
xfree(recv_buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -303,7 +303,7 @@ void mcs_send_connect_initial(rdpMcs* mcs)
|
||||
gcc_write_conference_create_request(gcc_CCrq, client_data);
|
||||
length = stream_get_length(gcc_CCrq) + 7;
|
||||
|
||||
s = stream_new(512);
|
||||
s = transport_send_stream_init(mcs->transport, 1024);
|
||||
stream_get_mark(s, bm);
|
||||
stream_seek(s, 7);
|
||||
|
||||
@ -316,7 +316,7 @@ void mcs_send_connect_initial(rdpMcs* mcs)
|
||||
tpdu_write_data(s);
|
||||
stream_set_mark(s, em);
|
||||
|
||||
tls_write(mcs->transport->tls, s->data, stream_get_length(s));
|
||||
transport_write(mcs->transport, s);
|
||||
}
|
||||
|
||||
void mcs_recv_connect_response(rdpMcs* mcs)
|
||||
@ -326,8 +326,8 @@ void mcs_recv_connect_response(rdpMcs* mcs)
|
||||
uint8 result;
|
||||
uint32 calledConnectId;
|
||||
|
||||
s = stream_new(1024);
|
||||
tls_read(mcs->transport->tls, s->data, s->size);
|
||||
s = transport_recv_stream_init(mcs->transport, 1024);
|
||||
transport_read(mcs->transport, s);
|
||||
|
||||
tpkt_read_header(s);
|
||||
tpdu_read_data(s);
|
||||
@ -347,7 +347,7 @@ void mcs_send_erect_domain_request(rdpMcs* mcs)
|
||||
{
|
||||
STREAM* s;
|
||||
int length = 12;
|
||||
s = stream_new(length);
|
||||
s = transport_send_stream_init(mcs->transport, length);
|
||||
|
||||
tpkt_write_header(s, length);
|
||||
tpdu_write_data(s);
|
||||
@ -357,14 +357,14 @@ void mcs_send_erect_domain_request(rdpMcs* mcs)
|
||||
per_write_integer(s, 0); /* subHeight (INTEGER) */
|
||||
per_write_integer(s, 0); /* subInterval (INTEGER) */
|
||||
|
||||
tls_write(mcs->transport->tls, s->data, stream_get_length(s));
|
||||
transport_write(mcs->transport, s);
|
||||
}
|
||||
|
||||
void mcs_send_attach_user_request(rdpMcs* mcs)
|
||||
{
|
||||
STREAM* s;
|
||||
int length = 8;
|
||||
s = stream_new(length);
|
||||
s = transport_send_stream_init(mcs->transport, length);
|
||||
|
||||
tpkt_write_header(s, length);
|
||||
tpdu_write_data(s);
|
||||
@ -372,7 +372,7 @@ void mcs_send_attach_user_request(rdpMcs* mcs)
|
||||
/* DomainMCSPDU, AttachUserRequest */
|
||||
per_write_choice(s, DomainMCSPDU_AttachUserRequest << 2);
|
||||
|
||||
tls_write(mcs->transport->tls, s->data, stream_get_length(s));
|
||||
transport_write(mcs->transport, s);
|
||||
}
|
||||
|
||||
void mcs_recv_attach_user_confirm(rdpMcs* mcs)
|
||||
@ -382,8 +382,8 @@ void mcs_recv_attach_user_confirm(rdpMcs* mcs)
|
||||
uint8 result;
|
||||
uint8 choice;
|
||||
|
||||
s = stream_new(32);
|
||||
tls_read(mcs->transport->tls, s->data, s->size);
|
||||
s = transport_recv_stream_init(mcs->transport, 32);
|
||||
transport_read(mcs->transport, s);
|
||||
|
||||
tpkt_read_header(s);
|
||||
tpdu_read_data(s);
|
||||
@ -397,7 +397,7 @@ void mcs_send_channel_join_request(rdpMcs* mcs, uint16 channel_id)
|
||||
{
|
||||
STREAM* s;
|
||||
int length = 12;
|
||||
s = stream_new(length);
|
||||
s = transport_send_stream_init(mcs->transport, 12);
|
||||
|
||||
tpkt_write_header(s, length);
|
||||
tpdu_write_data(s);
|
||||
@ -407,7 +407,7 @@ void mcs_send_channel_join_request(rdpMcs* mcs, uint16 channel_id)
|
||||
per_write_integer16(s, mcs->user_id, MCS_BASE_CHANNEL_ID);
|
||||
per_write_integer16(s, channel_id + MCS_BASE_CHANNEL_ID, 0);
|
||||
|
||||
tls_write(mcs->transport->tls, s->data, stream_get_length(s));
|
||||
transport_write(mcs->transport, s);
|
||||
}
|
||||
|
||||
void mcs_recv_channel_join_confirm(rdpMcs* mcs)
|
||||
@ -420,8 +420,8 @@ void mcs_recv_channel_join_confirm(rdpMcs* mcs)
|
||||
uint16 requested;
|
||||
uint16 channelId;
|
||||
|
||||
s = stream_new(32);
|
||||
tls_read(mcs->transport->tls, s->data, s->size);
|
||||
s = transport_recv_stream_init(mcs->transport, 32);
|
||||
transport_read(mcs->transport, s);
|
||||
|
||||
tpkt_read_header(s);
|
||||
tpdu_read_data(s);
|
||||
@ -440,8 +440,8 @@ void mcs_recv(rdpMcs* mcs)
|
||||
uint8 result;
|
||||
uint8 choice;
|
||||
|
||||
s = stream_new(32);
|
||||
tls_read(mcs->transport->tls, s->data, s->size);
|
||||
s = transport_recv_stream_init(mcs->transport, 1024);
|
||||
transport_read(mcs->transport, s);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -210,10 +210,9 @@ void nego_attempt_rdp(rdpNego* nego)
|
||||
|
||||
void nego_recv_response(rdpNego* nego)
|
||||
{
|
||||
while (nego->state != NEGO_STATE_FINAL && nego->state != NEGO_STATE_FAIL)
|
||||
{
|
||||
transport_check_fds(nego->transport);
|
||||
}
|
||||
STREAM* s = transport_recv_stream_init(nego->transport, 1024);
|
||||
transport_read(nego->transport, s);
|
||||
nego_recv(nego->transport, s, nego->transport->recv_extra);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -325,7 +324,7 @@ void nego_send_negotiation_request(rdpNego* nego)
|
||||
tpdu_write_connection_request(s, length - 5);
|
||||
stream_set_mark(s, em);
|
||||
|
||||
transport_send(nego->transport, s);
|
||||
transport_write(nego->transport, s);
|
||||
}
|
||||
|
||||
/**
|
||||
|
27
libfreerdp-core/rdp.c
Normal file
27
libfreerdp-core/rdp.c
Normal file
@ -0,0 +1,27 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Client
|
||||
* RDP Core
|
||||
*
|
||||
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "rdp.h"
|
||||
|
||||
void rdp_write_security_header(STREAM* s, uint16 flags)
|
||||
{
|
||||
/* Basic Security Header */
|
||||
stream_write_uint16(s, flags); /* flags */
|
||||
stream_write_uint16(s, 0); /* flagsHi (unused) */
|
||||
}
|
41
libfreerdp-core/rdp.h
Normal file
41
libfreerdp-core/rdp.h
Normal file
@ -0,0 +1,41 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Client
|
||||
* RDP Core
|
||||
*
|
||||
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __RDP_H
|
||||
#define __RDP_H
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
|
||||
/* Security Header Flags */
|
||||
#define SEC_EXCHANGE_PKT 0x0001
|
||||
#define SEC_ENCRYPT 0x0008
|
||||
#define SEC_RESET_SEQNO 0x0010
|
||||
#define SEC_IGNORE_SEQNO 0x0020
|
||||
#define SEC_INFO_PKT 0x0040
|
||||
#define SEC_LICENSE_PKT 0x0080
|
||||
#define SEC_LICENSE_ENCRYPT_CS 0x0200
|
||||
#define SEC_LICENSE_ENCRYPT_SC 0x0200
|
||||
#define SEC_REDIRECTION_PKT 0x0400
|
||||
#define SEC_SECURE_CHECKSUM 0x0800
|
||||
#define SEC_FLAGSHI_VALID 0x8000
|
||||
|
||||
void rdp_write_security_header(STREAM* s, uint16 flags);
|
||||
|
||||
#endif /* __RDP_H */
|
@ -56,7 +56,7 @@ static void tcp_get_ip_address(rdpTcp * tcp)
|
||||
tcp->settings->ip_address = tcp->ip_address;
|
||||
}
|
||||
|
||||
boolean tcp_connect(rdpTcp* tcp, const char* hostname, int port)
|
||||
boolean tcp_connect(rdpTcp* tcp, const uint8* hostname, uint16 port)
|
||||
{
|
||||
int status;
|
||||
int sockfd = -1;
|
||||
@ -105,6 +105,51 @@ boolean tcp_connect(rdpTcp* tcp, const char* hostname, int port)
|
||||
return True;
|
||||
}
|
||||
|
||||
int tcp_read(rdpTcp* tcp, uint8* data, int length)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = recv(tcp->sockfd, data, length, 0);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
return 0;
|
||||
|
||||
perror("recv");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int tcp_write(rdpTcp* tcp, uint8* data, int length)
|
||||
{
|
||||
int status;
|
||||
int sent = 0;
|
||||
|
||||
while (sent < length)
|
||||
{
|
||||
status = send(tcp->sockfd, data, (length - sent), MSG_NOSIGNAL);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
continue;
|
||||
|
||||
perror("send");
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sent += status;
|
||||
data += status;
|
||||
}
|
||||
}
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
boolean tcp_disconnect(rdpTcp * tcp)
|
||||
{
|
||||
if (tcp->sockfd != -1)
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include <freerdp/utils/stream.h>
|
||||
|
||||
typedef struct rdp_tcp rdpTcp;
|
||||
typedef boolean (*TcpConnect) (rdpTcp* tcp, const char* hostname, int port);
|
||||
typedef boolean (*TcpConnect) (rdpTcp* tcp, const uint8* hostname, uint16 port);
|
||||
typedef boolean (*TcpDisconnect) (rdpTcp* tcp);
|
||||
typedef boolean (*TcpSetBlockingMode) (rdpTcp* tcp, boolean blocking);
|
||||
|
||||
@ -40,8 +40,10 @@ struct rdp_tcp
|
||||
TcpSetBlockingMode set_blocking_mode;
|
||||
};
|
||||
|
||||
boolean tcp_connect(rdpTcp* tcp, const char* hostname, int port);
|
||||
boolean tcp_connect(rdpTcp* tcp, const uint8* hostname, uint16 port);
|
||||
boolean tcp_disconnect(rdpTcp* tcp);
|
||||
int tcp_read(rdpTcp* tcp, uint8* data, int length);
|
||||
int tcp_write(rdpTcp* tcp, uint8* data, int length);
|
||||
boolean tcp_set_blocking_mode(rdpTcp* tcp, boolean blocking);
|
||||
|
||||
rdpTcp* tcp_new(rdpSettings* settings);
|
||||
|
@ -63,7 +63,7 @@ boolean tls_disconnect(rdpTls* tls)
|
||||
return True;
|
||||
}
|
||||
|
||||
int tls_read(rdpTls* tls, char* data, int length)
|
||||
int tls_read(rdpTls* tls, uint8* data, int length)
|
||||
{
|
||||
int status;
|
||||
|
||||
@ -91,19 +91,20 @@ int tls_read(rdpTls* tls, char* data, int length)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tls_write(rdpTls* tls, char* data, int length)
|
||||
int tls_write(rdpTls* tls, uint8* data, int length)
|
||||
{
|
||||
int bytes = 0;
|
||||
int write_status;
|
||||
int status;
|
||||
int sent = 0;
|
||||
|
||||
while (bytes < length)
|
||||
while (sent < length)
|
||||
{
|
||||
write_status = SSL_write(tls->ssl, data, length);
|
||||
status = SSL_write(tls->ssl, data, length);
|
||||
|
||||
switch (SSL_get_error(tls->ssl, write_status))
|
||||
switch (SSL_get_error(tls->ssl, status))
|
||||
{
|
||||
case SSL_ERROR_NONE:
|
||||
bytes += write_status;
|
||||
sent += status;
|
||||
data += status;
|
||||
break;
|
||||
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
@ -111,12 +112,13 @@ int tls_write(rdpTls* tls, char* data, int length)
|
||||
break;
|
||||
|
||||
default:
|
||||
tls_print_error("SSL_write", tls->ssl, write_status);
|
||||
tls_print_error("SSL_write", tls->ssl, status);
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return bytes;
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
boolean tls_print_error(char *func, SSL *connection, int value)
|
||||
|
@ -45,8 +45,8 @@ struct rdp_tls
|
||||
|
||||
boolean tls_connect(rdpTls* tls);
|
||||
boolean tls_disconnect(rdpTls* tls);
|
||||
int tls_read(rdpTls* tls, char* data, int length);
|
||||
int tls_write(rdpTls* tls, char* data, int length);
|
||||
int tls_read(rdpTls* tls, uint8* data, int length);
|
||||
int tls_write(rdpTls* tls, uint8* data, int length);
|
||||
CryptoCert tls_get_certificate(rdpTls* tls);
|
||||
boolean tls_print_error(char* func, SSL* connection, int value);
|
||||
|
||||
|
@ -39,9 +39,25 @@
|
||||
|
||||
#define BUFFER_SIZE 16384
|
||||
|
||||
boolean transport_connect(rdpTransport* transport, const char* server, int port)
|
||||
STREAM* transport_recv_stream_init(rdpTransport* transport, int size)
|
||||
{
|
||||
return transport->tcp->connect(transport->tcp, server, port);
|
||||
STREAM* s = transport->recv_stream;
|
||||
stream_check_size(s, size);
|
||||
stream_set_pos(s, 0);
|
||||
return s;
|
||||
}
|
||||
|
||||
STREAM* transport_send_stream_init(rdpTransport* transport, int size)
|
||||
{
|
||||
STREAM* s = transport->send_stream;
|
||||
stream_check_size(s, size);
|
||||
stream_set_pos(s, 0);
|
||||
return s;
|
||||
}
|
||||
|
||||
boolean transport_connect(rdpTransport* transport, const uint8* hostname, uint16 port)
|
||||
{
|
||||
return transport->tcp->connect(transport->tcp, hostname, port);
|
||||
}
|
||||
|
||||
boolean transport_disconnect(rdpTransport* transport)
|
||||
@ -63,8 +79,8 @@ boolean transport_connect_tls(rdpTransport* transport)
|
||||
if (transport->tls == NULL)
|
||||
transport->tls = tls_new();
|
||||
|
||||
transport->layer = TRANSPORT_LAYER_TLS;
|
||||
transport->state = TRANSPORT_STATE_TLS;
|
||||
|
||||
transport->tls->sockfd = transport->tcp->sockfd;
|
||||
|
||||
if (tls_connect(transport->tls) != True)
|
||||
@ -78,8 +94,8 @@ boolean transport_connect_nla(rdpTransport* transport)
|
||||
if (transport->tls == NULL)
|
||||
transport->tls = tls_new();
|
||||
|
||||
transport->layer = TRANSPORT_LAYER_TLS;
|
||||
transport->state = TRANSPORT_STATE_NLA;
|
||||
|
||||
transport->tls->sockfd = transport->tcp->sockfd;
|
||||
|
||||
if (tls_connect(transport->tls) != True)
|
||||
@ -104,100 +120,35 @@ boolean transport_connect_nla(rdpTransport* transport)
|
||||
return True;
|
||||
}
|
||||
|
||||
static int transport_read(rdpTransport* transport);
|
||||
|
||||
static int transport_delay(rdpTransport* transport)
|
||||
int transport_delay(rdpTransport* transport, STREAM* s)
|
||||
{
|
||||
transport_read(transport);
|
||||
transport_read(transport, s);
|
||||
nanosleep(&transport->ts, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int transport_send_tls(rdpTransport* transport, STREAM * stream)
|
||||
int transport_read(rdpTransport* transport, STREAM* s)
|
||||
{
|
||||
return 0;
|
||||
int status = -1;
|
||||
|
||||
if (transport->layer == TRANSPORT_LAYER_TLS)
|
||||
status = tls_read(transport->tls, s->data, s->size);
|
||||
else if (transport->layer == TRANSPORT_LAYER_TCP)
|
||||
status = tcp_read(transport->tcp, s->data, s->size);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int transport_send_tcp(rdpTransport* transport, STREAM * stream)
|
||||
int transport_write(rdpTransport* transport, STREAM* s)
|
||||
{
|
||||
int bytes;
|
||||
uint8 * head;
|
||||
uint8 * tail;
|
||||
int status = -1;
|
||||
|
||||
head = stream_get_head(stream);
|
||||
tail = stream_get_tail(stream);
|
||||
if (transport->layer == TRANSPORT_LAYER_TLS)
|
||||
status = tls_write(transport->tls, s->data, stream_get_length(s));
|
||||
else if (transport->layer == TRANSPORT_LAYER_TCP)
|
||||
status = tcp_write(transport->tcp, s->data, stream_get_length(s));
|
||||
|
||||
while (head < tail)
|
||||
{
|
||||
bytes = send(transport->tcp->sockfd, head, tail - head, MSG_NOSIGNAL);
|
||||
|
||||
if (bytes < 0)
|
||||
{
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
{
|
||||
if (transport_delay(transport) != 0)
|
||||
return -1;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
perror("send");
|
||||
return -1;
|
||||
}
|
||||
head += bytes;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int transport_send(rdpTransport* transport, STREAM * stream)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (transport->state == TRANSPORT_STATE_TLS)
|
||||
r = transport_send_tls(transport, stream);
|
||||
else
|
||||
r = transport_send_tcp(transport, stream);
|
||||
|
||||
if (r == 0)
|
||||
r = transport_check_fds(transport);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int transport_read_tls(rdpTransport* transport)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int transport_read_tcp(rdpTransport* transport)
|
||||
{
|
||||
int bytes;
|
||||
|
||||
stream_check_size(transport->recv_buffer, BUFFER_SIZE);
|
||||
|
||||
bytes = recv(transport->tcp->sockfd, transport->recv_buffer->p, BUFFER_SIZE, 0);
|
||||
|
||||
if (bytes == -1)
|
||||
{
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
return 0;
|
||||
|
||||
perror("recv");
|
||||
return -1;
|
||||
}
|
||||
|
||||
stream_seek(transport->recv_buffer, bytes);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static int transport_read(rdpTransport* transport)
|
||||
{
|
||||
if (transport->state == TRANSPORT_STATE_TLS)
|
||||
return transport_read_tls(transport);
|
||||
else
|
||||
return transport_read_tcp(transport);
|
||||
return status;
|
||||
}
|
||||
|
||||
int transport_check_fds(rdpTransport* transport)
|
||||
@ -207,7 +158,7 @@ int transport_check_fds(rdpTransport* transport)
|
||||
uint16 length;
|
||||
STREAM* received;
|
||||
|
||||
bytes = transport_read(transport);
|
||||
bytes = transport_read(transport, transport->recv_buffer);
|
||||
|
||||
if (bytes <= 0)
|
||||
return bytes;
|
||||
@ -260,6 +211,7 @@ int transport_check_fds(rdpTransport* transport)
|
||||
|
||||
void transport_init(rdpTransport* transport)
|
||||
{
|
||||
transport->layer = TRANSPORT_LAYER_TCP;
|
||||
transport->state = TRANSPORT_STATE_NEGO;
|
||||
}
|
||||
|
||||
@ -280,6 +232,10 @@ rdpTransport* transport_new(rdpSettings* settings)
|
||||
|
||||
/* receive buffer for non-blocking read. */
|
||||
transport->recv_buffer = stream_new(BUFFER_SIZE);
|
||||
|
||||
/* buffers for blocking read/write */
|
||||
transport->recv_stream = stream_new(BUFFER_SIZE);
|
||||
transport->send_stream = stream_new(BUFFER_SIZE);
|
||||
}
|
||||
|
||||
return transport;
|
||||
@ -290,6 +246,8 @@ void transport_free(rdpTransport* transport)
|
||||
if (transport != NULL)
|
||||
{
|
||||
stream_free(transport->recv_buffer);
|
||||
stream_free(transport->recv_stream);
|
||||
stream_free(transport->send_stream);
|
||||
tcp_free(transport->tcp);
|
||||
xfree(transport);
|
||||
}
|
||||
|
@ -20,6 +20,22 @@
|
||||
#ifndef __TRANSPORT_H
|
||||
#define __TRANSPORT_H
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TRANSPORT_LAYER_TCP,
|
||||
TRANSPORT_LAYER_TLS
|
||||
} TRANSPORT_LAYER;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TRANSPORT_STATE_INITIAL,
|
||||
TRANSPORT_STATE_NEGO,
|
||||
TRANSPORT_STATE_RDP,
|
||||
TRANSPORT_STATE_TLS,
|
||||
TRANSPORT_STATE_NLA,
|
||||
TRANSPORT_STATE_FINAL
|
||||
} TRANSPORT_STATE;
|
||||
|
||||
typedef struct rdp_transport rdpTransport;
|
||||
|
||||
#include "tcp.h"
|
||||
@ -31,21 +47,13 @@ typedef struct rdp_transport rdpTransport;
|
||||
#include <freerdp/settings.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
|
||||
enum _TRANSPORT_STATE
|
||||
{
|
||||
TRANSPORT_STATE_INITIAL,
|
||||
TRANSPORT_STATE_NEGO,
|
||||
TRANSPORT_STATE_RDP,
|
||||
TRANSPORT_STATE_TLS,
|
||||
TRANSPORT_STATE_NLA,
|
||||
TRANSPORT_STATE_FINAL
|
||||
};
|
||||
typedef enum _TRANSPORT_STATE TRANSPORT_STATE;
|
||||
|
||||
typedef int (*TransportRecv) (rdpTransport* transport, STREAM* stream, void* extra);
|
||||
|
||||
struct rdp_transport
|
||||
{
|
||||
STREAM* recv_stream;
|
||||
STREAM* send_stream;
|
||||
TRANSPORT_LAYER layer;
|
||||
TRANSPORT_STATE state;
|
||||
struct rdp_tcp* tcp;
|
||||
struct rdp_tls* tls;
|
||||
@ -57,14 +65,17 @@ struct rdp_transport
|
||||
TransportRecv recv_callback;
|
||||
};
|
||||
|
||||
rdpTransport* transport_new(rdpSettings* settings);
|
||||
void transport_free(rdpTransport* transport);
|
||||
boolean transport_connect(rdpTransport* transport, const char* server, int port);
|
||||
STREAM* transport_recv_stream_init(rdpTransport* transport, int size);
|
||||
STREAM* transport_send_stream_init(rdpTransport* transport, int size);
|
||||
boolean transport_connect(rdpTransport* transport, const uint8* hostname, uint16 port);
|
||||
boolean transport_disconnect(rdpTransport* transport);
|
||||
boolean transport_connect_rdp(rdpTransport* transport);
|
||||
boolean transport_connect_tls(rdpTransport* transport);
|
||||
boolean transport_connect_nla(rdpTransport* transport);
|
||||
int transport_send(rdpTransport* transport, STREAM* stream);
|
||||
int transport_read(rdpTransport* transport, STREAM* s);
|
||||
int transport_write(rdpTransport* transport, STREAM* s);
|
||||
int transport_check_fds(rdpTransport* transport);
|
||||
rdpTransport* transport_new(rdpSettings* settings);
|
||||
void transport_free(rdpTransport* transport);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user