Added support for protocol negotiation, this is a part of
adding Enhanced RDP Security support to rdesktop and brings support for TLSv1 tunnel functionality. git-svn-id: svn://svn.code.sf.net/p/rdesktop/code/rdesktop/trunk@1659 423420c4-83ab-492f-b58f-81f9feb106b5
This commit is contained in:
parent
cdce9aae75
commit
c44025aa18
@ -26,7 +26,7 @@
|
|||||||
#define CHANNEL_FLAG_LAST 0x02
|
#define CHANNEL_FLAG_LAST 0x02
|
||||||
#define CHANNEL_FLAG_SHOW_PROTOCOL 0x10
|
#define CHANNEL_FLAG_SHOW_PROTOCOL 0x10
|
||||||
|
|
||||||
extern RD_BOOL g_use_rdp5;
|
extern RDP_VERSION g_rdp_version;
|
||||||
extern RD_BOOL g_encryption;
|
extern RD_BOOL g_encryption;
|
||||||
|
|
||||||
VCHANNEL g_channels[MAX_CHANNELS];
|
VCHANNEL g_channels[MAX_CHANNELS];
|
||||||
@ -47,7 +47,7 @@ channel_register(char *name, uint32 flags, void (*callback) (STREAM))
|
|||||||
{
|
{
|
||||||
VCHANNEL *channel;
|
VCHANNEL *channel;
|
||||||
|
|
||||||
if (!g_use_rdp5)
|
if (g_rdp_version < RDP_V5)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (g_num_channels >= MAX_CHANNELS)
|
if (g_num_channels >= MAX_CHANNELS)
|
||||||
|
@ -103,9 +103,9 @@ AC_ARG_ENABLE(static-openssl,
|
|||||||
if test x"$static_openssl" = "xyes"; then
|
if test x"$static_openssl" = "xyes"; then
|
||||||
# OpenSSL generally relies on libz
|
# OpenSSL generally relies on libz
|
||||||
AC_SEARCH_LIBS(deflate, z)
|
AC_SEARCH_LIBS(deflate, z)
|
||||||
LIBS="-L$ssldir/lib -L$ssldir/lib64 -Wl,-Bstatic -lcrypto -Wl,-Bdynamic $LIBS"
|
LIBS="-L$ssldir/lib -L$ssldir/lib64 -Wl,-Bstatic -lcrypto -lssl -Wl,-Bdynamic $LIBS"
|
||||||
else
|
else
|
||||||
LIBS="-L$ssldir/lib -L$ssldir/lib64 -lcrypto $LIBS"
|
LIBS="-L$ssldir/lib -L$ssldir/lib64 -lcrypto -lssl $LIBS"
|
||||||
|
|
||||||
#
|
#
|
||||||
# target-specific stuff
|
# target-specific stuff
|
||||||
|
25
constants.h
25
constants.h
@ -33,6 +33,31 @@ enum ISO_PDU_CODE
|
|||||||
ISO_PDU_ER = 0x70 /* Error */
|
ISO_PDU_ER = 0x70 /* Error */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* RDP protocol negotiating constants */
|
||||||
|
enum RDP_NEG_TYPE_CODE
|
||||||
|
{
|
||||||
|
RDP_NEG_REQ = 1,
|
||||||
|
RDP_NEG_RSP = 2,
|
||||||
|
RDP_NEG_FAILURE = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
enum RDP_NEG_REQ_CODE
|
||||||
|
{
|
||||||
|
PROTOCOL_RDP = 0,
|
||||||
|
PROTOCOL_SSL = 1,
|
||||||
|
PROTOCOL_HYBRID = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
enum RDP_NEG_FAILURE_CODE
|
||||||
|
{
|
||||||
|
SSL_REQUIRED_BY_SERVER = 1,
|
||||||
|
SSL_NOT_ALLOWED_BY_SERVER = 2,
|
||||||
|
SSL_CERT_NOT_ON_SERVER = 3,
|
||||||
|
INCONSISTENT_FLAGS = 4,
|
||||||
|
HYBRID_REQUIRED_BY_SERVER = 5,
|
||||||
|
SSL_WITH_USER_AUTH_REQUIRED_BY_SERVER = 6
|
||||||
|
};
|
||||||
|
|
||||||
/* MCS PDU codes */
|
/* MCS PDU codes */
|
||||||
enum MCS_PDU_TYPE
|
enum MCS_PDU_TYPE
|
||||||
{
|
{
|
||||||
|
116
iso.c
116
iso.c
@ -20,6 +20,11 @@
|
|||||||
|
|
||||||
#include "rdesktop.h"
|
#include "rdesktop.h"
|
||||||
|
|
||||||
|
extern RD_BOOL g_encryption;
|
||||||
|
extern RDP_VERSION g_rdp_version;
|
||||||
|
|
||||||
|
static RD_BOOL g_negotiate_rdp_protocol = True;
|
||||||
|
|
||||||
/* Send a self-contained ISO PDU */
|
/* Send a self-contained ISO PDU */
|
||||||
static void
|
static void
|
||||||
iso_send_msg(uint8 code)
|
iso_send_msg(uint8 code)
|
||||||
@ -48,6 +53,9 @@ iso_send_connection_request(char *username)
|
|||||||
STREAM s;
|
STREAM s;
|
||||||
int length = 30 + strlen(username);
|
int length = 30 + strlen(username);
|
||||||
|
|
||||||
|
if (g_rdp_version >= RDP_V5 && g_negotiate_rdp_protocol)
|
||||||
|
length += 8;
|
||||||
|
|
||||||
s = tcp_init(length);
|
s = tcp_init(length);
|
||||||
|
|
||||||
out_uint8(s, 3); /* version */
|
out_uint8(s, 3); /* version */
|
||||||
@ -63,8 +71,17 @@ iso_send_connection_request(char *username)
|
|||||||
out_uint8p(s, "Cookie: mstshash=", strlen("Cookie: mstshash="));
|
out_uint8p(s, "Cookie: mstshash=", strlen("Cookie: mstshash="));
|
||||||
out_uint8p(s, username, strlen(username));
|
out_uint8p(s, username, strlen(username));
|
||||||
|
|
||||||
out_uint8(s, 0x0d); /* Unknown */
|
out_uint8(s, 0x0d); /* cookie termination string: CR+LF */
|
||||||
out_uint8(s, 0x0a); /* Unknown */
|
out_uint8(s, 0x0a);
|
||||||
|
|
||||||
|
if (g_rdp_version >= RDP_V5 && g_negotiate_rdp_protocol)
|
||||||
|
{
|
||||||
|
/* optional rdp protocol negotiation request for RDPv5 */
|
||||||
|
out_uint8(s, RDP_NEG_REQ);
|
||||||
|
out_uint8(s, 0);
|
||||||
|
out_uint16(s, 8);
|
||||||
|
out_uint32(s, PROTOCOL_SSL);
|
||||||
|
}
|
||||||
|
|
||||||
s_mark_end(s);
|
s_mark_end(s);
|
||||||
tcp_send(s);
|
tcp_send(s);
|
||||||
@ -174,9 +191,16 @@ iso_recv(uint8 * rdpver)
|
|||||||
|
|
||||||
/* Establish a connection up to the ISO layer */
|
/* Establish a connection up to the ISO layer */
|
||||||
RD_BOOL
|
RD_BOOL
|
||||||
iso_connect(char *server, char *username, RD_BOOL reconnect)
|
iso_connect(char *server, char *username, RD_BOOL reconnect, uint32 * selected_protocol)
|
||||||
{
|
{
|
||||||
uint8 code = 0;
|
STREAM s;
|
||||||
|
uint8 code;
|
||||||
|
|
||||||
|
g_negotiate_rdp_protocol = True;
|
||||||
|
|
||||||
|
retry:
|
||||||
|
*selected_protocol = PROTOCOL_RDP;
|
||||||
|
code = 0;
|
||||||
|
|
||||||
if (!tcp_connect(server))
|
if (!tcp_connect(server))
|
||||||
return False;
|
return False;
|
||||||
@ -190,7 +214,8 @@ iso_connect(char *server, char *username, RD_BOOL reconnect)
|
|||||||
iso_send_connection_request(username);
|
iso_send_connection_request(username);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iso_recv_msg(&code, NULL) == NULL)
|
s = iso_recv_msg(&code, NULL);
|
||||||
|
if (s == NULL)
|
||||||
return False;
|
return False;
|
||||||
|
|
||||||
if (code != ISO_PDU_CC)
|
if (code != ISO_PDU_CC)
|
||||||
@ -200,6 +225,87 @@ iso_connect(char *server, char *username, RD_BOOL reconnect)
|
|||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g_rdp_version >= RDP_V5 && s_check_rem(s, 8))
|
||||||
|
{
|
||||||
|
/* handle RDP_NEG_REQ response */
|
||||||
|
const char *reason = NULL;
|
||||||
|
|
||||||
|
uint8 type = 0, flags = 0;
|
||||||
|
uint16 length = 0;
|
||||||
|
uint32 data = 0;
|
||||||
|
|
||||||
|
in_uint8(s, type);
|
||||||
|
in_uint8(s, flags);
|
||||||
|
in_uint16(s, length);
|
||||||
|
in_uint32(s, data);
|
||||||
|
|
||||||
|
if (type == RDP_NEG_FAILURE)
|
||||||
|
{
|
||||||
|
switch (data)
|
||||||
|
{
|
||||||
|
case SSL_REQUIRED_BY_SERVER:
|
||||||
|
reason = "SSL required by server";
|
||||||
|
break;
|
||||||
|
case SSL_WITH_USER_AUTH_REQUIRED_BY_SERVER:
|
||||||
|
reason = "SSL with user authentication required by server";
|
||||||
|
break;
|
||||||
|
case SSL_NOT_ALLOWED_BY_SERVER:
|
||||||
|
reason = "SSL not allowed by server";
|
||||||
|
break;
|
||||||
|
case SSL_CERT_NOT_ON_SERVER:
|
||||||
|
reason = "SSL certificated not on server";
|
||||||
|
break;
|
||||||
|
case INCONSISTENT_FLAGS:
|
||||||
|
reason = "inconsistent flags";
|
||||||
|
break;
|
||||||
|
case HYBRID_REQUIRED_BY_SERVER:
|
||||||
|
reason = "hybrid authentication (CredSSP) required by server";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
reason = "unknown reason";
|
||||||
|
}
|
||||||
|
|
||||||
|
tcp_disconnect();
|
||||||
|
warning("RDP protocol negotiation failed with reason: %s (error 0x%x),\n",
|
||||||
|
reason, data);
|
||||||
|
warning("retrying without negotiation using plain RDP protocol.\n");
|
||||||
|
|
||||||
|
g_negotiate_rdp_protocol = False;
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type != RDP_NEG_RSP)
|
||||||
|
{
|
||||||
|
tcp_disconnect();
|
||||||
|
error("expected RDP_NEG_RSP, got type = 0x%x\n", type);
|
||||||
|
warning("retrying without negotiation using plain RDP protocol.\n");
|
||||||
|
|
||||||
|
g_negotiate_rdp_protocol = False;
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* handle negotiation response */
|
||||||
|
if (data == PROTOCOL_SSL)
|
||||||
|
{
|
||||||
|
if (!tcp_tls_connect())
|
||||||
|
{
|
||||||
|
tcp_disconnect();
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do not use encryption when using TLS */
|
||||||
|
g_encryption = False;
|
||||||
|
}
|
||||||
|
else if (data != PROTOCOL_RDP)
|
||||||
|
{
|
||||||
|
tcp_disconnect();
|
||||||
|
error("unexpected protocol in neqotiation response, got data = 0x%x.\n",
|
||||||
|
data);
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
|
*selected_protocol = data;
|
||||||
|
}
|
||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
10
licence.c
10
licence.c
@ -23,12 +23,13 @@
|
|||||||
|
|
||||||
extern char *g_username;
|
extern char *g_username;
|
||||||
extern char g_hostname[16];
|
extern char g_hostname[16];
|
||||||
extern RD_BOOL g_use_rdp5;
|
extern RDP_VERSION g_rdp_version;
|
||||||
|
|
||||||
static uint8 g_licence_key[16];
|
static uint8 g_licence_key[16];
|
||||||
static uint8 g_licence_sign_key[16];
|
static uint8 g_licence_sign_key[16];
|
||||||
|
|
||||||
RD_BOOL g_licence_issued = False;
|
RD_BOOL g_licence_issued = False;
|
||||||
|
RD_BOOL g_licence_error_result = False;
|
||||||
|
|
||||||
/* Generate a session key and RC4 keys, given client and server randoms */
|
/* Generate a session key and RC4 keys, given client and server randoms */
|
||||||
static void
|
static void
|
||||||
@ -69,7 +70,7 @@ licence_present(uint8 * client_random, uint8 * rsa_data,
|
|||||||
s = sec_init(sec_flags, length + 2);
|
s = sec_init(sec_flags, length + 2);
|
||||||
|
|
||||||
out_uint8(s, LICENCE_TAG_PRESENT);
|
out_uint8(s, LICENCE_TAG_PRESENT);
|
||||||
out_uint8(s, (g_use_rdp5 ? 3 : 2)); /* version */
|
out_uint8(s, ((g_rdp_version >= RDP_V5) ? 3 : 2)); /* version */
|
||||||
out_uint16_le(s, length);
|
out_uint16_le(s, length);
|
||||||
|
|
||||||
out_uint32_le(s, 1);
|
out_uint32_le(s, 1);
|
||||||
@ -110,7 +111,7 @@ licence_send_request(uint8 * client_random, uint8 * rsa_data, char *user, char *
|
|||||||
s = sec_init(sec_flags, length + 2);
|
s = sec_init(sec_flags, length + 2);
|
||||||
|
|
||||||
out_uint8(s, LICENCE_TAG_REQUEST);
|
out_uint8(s, LICENCE_TAG_REQUEST);
|
||||||
out_uint8(s, (g_use_rdp5 ? 3 : 2)); /* version */
|
out_uint8(s, ((g_rdp_version >= RDP_V5) ? 3 : 2)); /* version */
|
||||||
out_uint16_le(s, length);
|
out_uint16_le(s, length);
|
||||||
|
|
||||||
out_uint32_le(s, 1);
|
out_uint32_le(s, 1);
|
||||||
@ -192,7 +193,7 @@ licence_send_authresp(uint8 * token, uint8 * crypt_hwid, uint8 * signature)
|
|||||||
s = sec_init(sec_flags, length + 2);
|
s = sec_init(sec_flags, length + 2);
|
||||||
|
|
||||||
out_uint8(s, LICENCE_TAG_AUTHRESP);
|
out_uint8(s, LICENCE_TAG_AUTHRESP);
|
||||||
out_uint8(s, (g_use_rdp5 ? 3 : 2)); /* version */
|
out_uint8(s, ((g_rdp_version >= RDP_V5) ? 3 : 2)); /* version */
|
||||||
out_uint16_le(s, length);
|
out_uint16_le(s, length);
|
||||||
|
|
||||||
out_uint16_le(s, 1);
|
out_uint16_le(s, 1);
|
||||||
@ -333,6 +334,7 @@ licence_process(STREAM s)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case LICENCE_TAG_RESULT:
|
case LICENCE_TAG_RESULT:
|
||||||
|
g_licence_error_result = True;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
11
mcs.c
11
mcs.c
@ -373,13 +373,16 @@ mcs_recv(uint16 * channel, uint8 * rdpver)
|
|||||||
}
|
}
|
||||||
|
|
||||||
RD_BOOL
|
RD_BOOL
|
||||||
mcs_connect(char *server, STREAM mcs_data, char *username, RD_BOOL reconnect)
|
mcs_connect_start(char *server, char *username, RD_BOOL reconnect, uint32 * selected_protocol)
|
||||||
|
{
|
||||||
|
return iso_connect(server, username, reconnect, selected_protocol);
|
||||||
|
}
|
||||||
|
|
||||||
|
RD_BOOL
|
||||||
|
mcs_connect_finalize(STREAM mcs_data)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
if (!iso_connect(server, username, reconnect))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
mcs_send_connect_initial(mcs_data);
|
mcs_send_connect_initial(mcs_data);
|
||||||
if (!mcs_recv_connect_response(mcs_data))
|
if (!mcs_recv_connect_response(mcs_data))
|
||||||
goto error;
|
goto error;
|
||||||
|
4
orders.c
4
orders.c
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
extern uint8 *g_next_packet;
|
extern uint8 *g_next_packet;
|
||||||
static RDP_ORDER_STATE g_order_state;
|
static RDP_ORDER_STATE g_order_state;
|
||||||
extern RD_BOOL g_use_rdp5;
|
extern RDP_VERSION g_rdp_version;
|
||||||
|
|
||||||
/* Read field indicating which parameters are present */
|
/* Read field indicating which parameters are present */
|
||||||
static void
|
static void
|
||||||
@ -968,7 +968,7 @@ process_bmpcache(STREAM s)
|
|||||||
in_uint16_le(s, bufsize); /* bufsize */
|
in_uint16_le(s, bufsize); /* bufsize */
|
||||||
in_uint16_le(s, cache_idx);
|
in_uint16_le(s, cache_idx);
|
||||||
|
|
||||||
if (g_use_rdp5)
|
if (g_rdp_version >= RDP_V5)
|
||||||
{
|
{
|
||||||
size = bufsize;
|
size = bufsize;
|
||||||
}
|
}
|
||||||
|
6
proto.h
6
proto.h
@ -74,7 +74,7 @@ void ewmh_init(void);
|
|||||||
STREAM iso_init(int length);
|
STREAM iso_init(int length);
|
||||||
void iso_send(STREAM s);
|
void iso_send(STREAM s);
|
||||||
STREAM iso_recv(uint8 * rdpver);
|
STREAM iso_recv(uint8 * rdpver);
|
||||||
RD_BOOL iso_connect(char *server, char *username, RD_BOOL reconnect);
|
RD_BOOL iso_connect(char *server, char *username, RD_BOOL reconnect, uint32 * selected_protocol);
|
||||||
void iso_disconnect(void);
|
void iso_disconnect(void);
|
||||||
void iso_reset_state(void);
|
void iso_reset_state(void);
|
||||||
/* licence.c */
|
/* licence.c */
|
||||||
@ -84,7 +84,9 @@ STREAM mcs_init(int length);
|
|||||||
void mcs_send_to_channel(STREAM s, uint16 channel);
|
void mcs_send_to_channel(STREAM s, uint16 channel);
|
||||||
void mcs_send(STREAM s);
|
void mcs_send(STREAM s);
|
||||||
STREAM mcs_recv(uint16 * channel, uint8 * rdpver);
|
STREAM mcs_recv(uint16 * channel, uint8 * rdpver);
|
||||||
RD_BOOL mcs_connect(char *server, STREAM mcs_data, char *username, RD_BOOL reconnect);
|
RD_BOOL mcs_connect_start(char *server, char *username, RD_BOOL reconnect,
|
||||||
|
uint32 * selected_protocol);
|
||||||
|
RD_BOOL mcs_connect_finalize(STREAM s);
|
||||||
void mcs_disconnect(void);
|
void mcs_disconnect(void);
|
||||||
void mcs_reset_state(void);
|
void mcs_reset_state(void);
|
||||||
/* orders.c */
|
/* orders.c */
|
||||||
|
@ -92,7 +92,7 @@ RD_BOOL g_polygon_ellipse_orders = True; /* polygon / ellipse orders */
|
|||||||
RD_BOOL g_fullscreen = False;
|
RD_BOOL g_fullscreen = False;
|
||||||
RD_BOOL g_grab_keyboard = True;
|
RD_BOOL g_grab_keyboard = True;
|
||||||
RD_BOOL g_hide_decorations = False;
|
RD_BOOL g_hide_decorations = False;
|
||||||
RD_BOOL g_use_rdp5 = True;
|
RDP_VERSION g_rdp_version = RDP_V5; /* Default to version 5 */
|
||||||
RD_BOOL g_rdpclip = True;
|
RD_BOOL g_rdpclip = True;
|
||||||
RD_BOOL g_console_session = False;
|
RD_BOOL g_console_session = False;
|
||||||
RD_BOOL g_numlock_sync = False;
|
RD_BOOL g_numlock_sync = False;
|
||||||
@ -838,11 +838,11 @@ main(int argc, char *argv[])
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '4':
|
case '4':
|
||||||
g_use_rdp5 = False;
|
g_rdp_version = RDP_V4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '5':
|
case '5':
|
||||||
g_use_rdp5 = True;
|
g_rdp_version = RDP_V5;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'h':
|
case 'h':
|
||||||
@ -890,7 +890,7 @@ main(int argc, char *argv[])
|
|||||||
error("You cannot use -X and -A at the same time\n");
|
error("You cannot use -X and -A at the same time\n");
|
||||||
return EX_USAGE;
|
return EX_USAGE;
|
||||||
}
|
}
|
||||||
if (!g_use_rdp5)
|
if (g_rdp_version < RDP_V5)
|
||||||
{
|
{
|
||||||
error("You cannot use -4 and -A at the same time\n");
|
error("You cannot use -4 and -A at the same time\n");
|
||||||
return EX_USAGE;
|
return EX_USAGE;
|
||||||
|
24
rdp.c
24
rdp.c
@ -44,7 +44,7 @@ extern RD_BOOL g_orders;
|
|||||||
extern RD_BOOL g_encryption;
|
extern RD_BOOL g_encryption;
|
||||||
extern RD_BOOL g_desktop_save;
|
extern RD_BOOL g_desktop_save;
|
||||||
extern RD_BOOL g_polygon_ellipse_orders;
|
extern RD_BOOL g_polygon_ellipse_orders;
|
||||||
extern RD_BOOL g_use_rdp5;
|
extern RDP_VERSION g_rdp_version;
|
||||||
extern uint16 g_server_rdp_version;
|
extern uint16 g_server_rdp_version;
|
||||||
extern uint32 g_rdp5_performanceflags;
|
extern uint32 g_rdp5_performanceflags;
|
||||||
extern int g_server_depth;
|
extern int g_server_depth;
|
||||||
@ -341,7 +341,7 @@ rdp_send_logon_info(uint32 flags, char *domain, char *user,
|
|||||||
time_t tzone;
|
time_t tzone;
|
||||||
uint8 security_verifier[16];
|
uint8 security_verifier[16];
|
||||||
|
|
||||||
if (!g_use_rdp5 || 1 == g_server_rdp_version)
|
if (g_rdp_version == RDP_V4 || 1 == g_server_rdp_version)
|
||||||
{
|
{
|
||||||
DEBUG_RDP5(("Sending RDP4-style Logon packet\n"));
|
DEBUG_RDP5(("Sending RDP4-style Logon packet\n"));
|
||||||
|
|
||||||
@ -644,7 +644,7 @@ rdp_out_general_caps(STREAM s)
|
|||||||
out_uint16_le(s, 0x200); /* Protocol version */
|
out_uint16_le(s, 0x200); /* Protocol version */
|
||||||
out_uint16(s, 0); /* Pad */
|
out_uint16(s, 0); /* Pad */
|
||||||
out_uint16(s, 0); /* Compression types */
|
out_uint16(s, 0); /* Compression types */
|
||||||
out_uint16_le(s, g_use_rdp5 ? 0x40d : 0);
|
out_uint16_le(s, (g_rdp_version >= RDP_V5) ? 0x40d : 0);
|
||||||
/* Pad, according to T.128. 0x40d seems to
|
/* Pad, according to T.128. 0x40d seems to
|
||||||
trigger
|
trigger
|
||||||
the server to start sending RDP5 packets.
|
the server to start sending RDP5 packets.
|
||||||
@ -896,7 +896,7 @@ rdp_send_confirm_active(void)
|
|||||||
RDP_CAPLEN_BRUSHCACHE + 0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */ +
|
RDP_CAPLEN_BRUSHCACHE + 0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */ +
|
||||||
4 /* w2k fix, sessionid */ ;
|
4 /* w2k fix, sessionid */ ;
|
||||||
|
|
||||||
if (g_use_rdp5)
|
if (g_rdp_version >= RDP_V5)
|
||||||
{
|
{
|
||||||
caplen += RDP_CAPLEN_BMPCACHE2;
|
caplen += RDP_CAPLEN_BMPCACHE2;
|
||||||
caplen += RDP_CAPLEN_NEWPOINTER;
|
caplen += RDP_CAPLEN_NEWPOINTER;
|
||||||
@ -925,7 +925,7 @@ rdp_send_confirm_active(void)
|
|||||||
rdp_out_general_caps(s);
|
rdp_out_general_caps(s);
|
||||||
rdp_out_bitmap_caps(s);
|
rdp_out_bitmap_caps(s);
|
||||||
rdp_out_order_caps(s);
|
rdp_out_order_caps(s);
|
||||||
if (g_use_rdp5)
|
if (g_rdp_version >= RDP_V5)
|
||||||
{
|
{
|
||||||
rdp_out_bmpcache2_caps(s);
|
rdp_out_bmpcache2_caps(s);
|
||||||
rdp_out_newpointer_caps(s);
|
rdp_out_newpointer_caps(s);
|
||||||
@ -960,7 +960,7 @@ rdp_process_general_caps(STREAM s)
|
|||||||
in_uint16_le(s, pad2octetsB);
|
in_uint16_le(s, pad2octetsB);
|
||||||
|
|
||||||
if (!pad2octetsB)
|
if (!pad2octetsB)
|
||||||
g_use_rdp5 = False;
|
g_rdp_version = RDP_V4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process a bitmap capability set */
|
/* Process a bitmap capability set */
|
||||||
@ -1060,7 +1060,7 @@ process_demand_active(STREAM s)
|
|||||||
rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0,
|
rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0,
|
||||||
g_numlock_sync ? ui_get_numlock_state(read_keyboard_state()) : 0, 0);
|
g_numlock_sync ? ui_get_numlock_state(read_keyboard_state()) : 0, 0);
|
||||||
|
|
||||||
if (g_use_rdp5)
|
if (g_rdp_version >= RDP_V5)
|
||||||
{
|
{
|
||||||
rdp_enum_bmpcache2();
|
rdp_enum_bmpcache2();
|
||||||
rdp_send_fonts(3);
|
rdp_send_fonts(3);
|
||||||
@ -1633,10 +1633,20 @@ RD_BOOL
|
|||||||
rdp_connect(char *server, uint32 flags, char *domain, char *password,
|
rdp_connect(char *server, uint32 flags, char *domain, char *password,
|
||||||
char *command, char *directory, RD_BOOL reconnect)
|
char *command, char *directory, RD_BOOL reconnect)
|
||||||
{
|
{
|
||||||
|
RD_BOOL deactivated = False;
|
||||||
|
uint32 ext_disc_reason = 0;
|
||||||
|
|
||||||
if (!sec_connect(server, g_username, reconnect))
|
if (!sec_connect(server, g_username, reconnect))
|
||||||
return False;
|
return False;
|
||||||
|
|
||||||
rdp_send_logon_info(flags, domain, g_username, password, command, directory);
|
rdp_send_logon_info(flags, domain, g_username, password, command, directory);
|
||||||
|
|
||||||
|
/* run RDP loop until first licence demand active PDU */
|
||||||
|
while (!g_rdp_shareid)
|
||||||
|
{
|
||||||
|
if (!rdp_loop(&deactivated, &ext_disc_reason))
|
||||||
|
return False;
|
||||||
|
}
|
||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
51
secure.c
51
secure.c
@ -30,7 +30,8 @@ extern int g_keyboard_subtype;
|
|||||||
extern int g_keyboard_functionkeys;
|
extern int g_keyboard_functionkeys;
|
||||||
extern RD_BOOL g_encryption;
|
extern RD_BOOL g_encryption;
|
||||||
extern RD_BOOL g_licence_issued;
|
extern RD_BOOL g_licence_issued;
|
||||||
extern RD_BOOL g_use_rdp5;
|
extern RD_BOOL g_licence_error_result;
|
||||||
|
extern RDP_VERSION g_rdp_version;
|
||||||
extern RD_BOOL g_console_session;
|
extern RD_BOOL g_console_session;
|
||||||
extern int g_server_depth;
|
extern int g_server_depth;
|
||||||
extern VCHANNEL g_channels[];
|
extern VCHANNEL g_channels[];
|
||||||
@ -316,7 +317,7 @@ sec_init(uint32 flags, int maxlen)
|
|||||||
int hdrlen;
|
int hdrlen;
|
||||||
STREAM s;
|
STREAM s;
|
||||||
|
|
||||||
if (!g_licence_issued)
|
if (!g_licence_issued && !g_licence_error_result)
|
||||||
hdrlen = (flags & SEC_ENCRYPT) ? 12 : 4;
|
hdrlen = (flags & SEC_ENCRYPT) ? 12 : 4;
|
||||||
else
|
else
|
||||||
hdrlen = (flags & SEC_ENCRYPT) ? 12 : 0;
|
hdrlen = (flags & SEC_ENCRYPT) ? 12 : 0;
|
||||||
@ -337,7 +338,7 @@ sec_send_to_channel(STREAM s, uint32 flags, uint16 channel)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
s_pop_layer(s, sec_hdr);
|
s_pop_layer(s, sec_hdr);
|
||||||
if (!g_licence_issued || (flags & SEC_ENCRYPT))
|
if ((!g_licence_issued && !g_licence_error_result) || (flags & SEC_ENCRYPT))
|
||||||
out_uint32_le(s, flags);
|
out_uint32_le(s, flags);
|
||||||
|
|
||||||
if (flags & SEC_ENCRYPT)
|
if (flags & SEC_ENCRYPT)
|
||||||
@ -390,10 +391,10 @@ sec_establish_key(void)
|
|||||||
|
|
||||||
/* Output connect initial data blob */
|
/* Output connect initial data blob */
|
||||||
static void
|
static void
|
||||||
sec_out_mcs_data(STREAM s)
|
sec_out_mcs_data(STREAM s, uint32 selected_protocol)
|
||||||
{
|
{
|
||||||
int hostlen = 2 * strlen(g_hostname);
|
int hostlen = 2 * strlen(g_hostname);
|
||||||
int length = 158 + 76 + 12 + 4;
|
int length = 162 + 76 + 12 + 4;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
if (g_num_channels > 0)
|
if (g_num_channels > 0)
|
||||||
@ -421,8 +422,8 @@ sec_out_mcs_data(STREAM s)
|
|||||||
|
|
||||||
/* Client information */
|
/* Client information */
|
||||||
out_uint16_le(s, SEC_TAG_CLI_INFO);
|
out_uint16_le(s, SEC_TAG_CLI_INFO);
|
||||||
out_uint16_le(s, 212); /* length */
|
out_uint16_le(s, 216); /* length */
|
||||||
out_uint16_le(s, g_use_rdp5 ? 4 : 1); /* RDP version. 1 == RDP4, 4 == RDP5. */
|
out_uint16_le(s, (g_rdp_version >= RDP_V5) ? 4 : 1); /* RDP version. 1 == RDP4, 4 >= RDP5 to RDP8 */
|
||||||
out_uint16_le(s, 8);
|
out_uint16_le(s, 8);
|
||||||
out_uint16_le(s, g_width);
|
out_uint16_le(s, g_width);
|
||||||
out_uint16_le(s, g_height);
|
out_uint16_le(s, g_height);
|
||||||
@ -449,7 +450,8 @@ sec_out_mcs_data(STREAM s)
|
|||||||
out_uint16_le(s, 0x0700);
|
out_uint16_le(s, 0x0700);
|
||||||
out_uint8(s, 0);
|
out_uint8(s, 0);
|
||||||
out_uint32_le(s, 1);
|
out_uint32_le(s, 1);
|
||||||
out_uint8s(s, 64); /* End of client info */
|
out_uint8s(s, 64);
|
||||||
|
out_uint32_le(s, selected_protocol); /* End of client info */
|
||||||
|
|
||||||
out_uint16_le(s, SEC_TAG_CLI_4);
|
out_uint16_le(s, SEC_TAG_CLI_4);
|
||||||
out_uint16_le(s, 12);
|
out_uint16_le(s, 12);
|
||||||
@ -541,8 +543,12 @@ sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
|
|||||||
|
|
||||||
in_uint32_le(s, *rc4_key_size); /* 1 = 40-bit, 2 = 128-bit */
|
in_uint32_le(s, *rc4_key_size); /* 1 = 40-bit, 2 = 128-bit */
|
||||||
in_uint32_le(s, crypt_level); /* 1 = low, 2 = medium, 3 = high */
|
in_uint32_le(s, crypt_level); /* 1 = low, 2 = medium, 3 = high */
|
||||||
if (crypt_level == 0) /* no encryption */
|
if (crypt_level == 0)
|
||||||
|
{
|
||||||
|
/* no encryption */
|
||||||
return False;
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
in_uint32_le(s, random_len);
|
in_uint32_le(s, random_len);
|
||||||
in_uint32_le(s, rsa_info_len);
|
in_uint32_le(s, rsa_info_len);
|
||||||
|
|
||||||
@ -721,7 +727,7 @@ sec_process_srv_info(STREAM s)
|
|||||||
DEBUG_RDP5(("Server RDP version is %d\n", g_server_rdp_version));
|
DEBUG_RDP5(("Server RDP version is %d\n", g_server_rdp_version));
|
||||||
if (1 == g_server_rdp_version)
|
if (1 == g_server_rdp_version)
|
||||||
{
|
{
|
||||||
g_use_rdp5 = 0;
|
g_rdp_version = RDP_V4;
|
||||||
g_server_depth = 8;
|
g_server_depth = 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -796,10 +802,12 @@ sec_recv(uint8 * rdpver)
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (g_encryption || !g_licence_issued)
|
if (g_encryption || (!g_licence_issued && !g_licence_error_result))
|
||||||
{
|
{
|
||||||
in_uint32_le(s, sec_flags);
|
in_uint32_le(s, sec_flags);
|
||||||
|
|
||||||
|
if (g_encryption)
|
||||||
|
{
|
||||||
if (sec_flags & SEC_ENCRYPT)
|
if (sec_flags & SEC_ENCRYPT)
|
||||||
{
|
{
|
||||||
in_uint8s(s, 8); /* signature */
|
in_uint8s(s, 8); /* signature */
|
||||||
@ -845,7 +853,16 @@ sec_recv(uint8 * rdpver)
|
|||||||
hexdump(s->p, s->end - s->p);
|
hexdump(s->p, s->end - s->p);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((sec_flags & 0xffff) == SEC_LICENCE_NEG)
|
||||||
|
{
|
||||||
|
licence_process(s);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
s->p -= 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (channel != MCS_GLOBAL_CHANNEL)
|
if (channel != MCS_GLOBAL_CHANNEL)
|
||||||
@ -866,14 +883,20 @@ sec_recv(uint8 * rdpver)
|
|||||||
RD_BOOL
|
RD_BOOL
|
||||||
sec_connect(char *server, char *username, RD_BOOL reconnect)
|
sec_connect(char *server, char *username, RD_BOOL reconnect)
|
||||||
{
|
{
|
||||||
|
uint32 selected_proto;
|
||||||
struct stream mcs_data;
|
struct stream mcs_data;
|
||||||
|
|
||||||
|
/* Start a MCS connect sequence */
|
||||||
|
if (!mcs_connect_start(server, username, reconnect, &selected_proto))
|
||||||
|
return False;
|
||||||
|
|
||||||
/* We exchange some RDP data during the MCS-Connect */
|
/* We exchange some RDP data during the MCS-Connect */
|
||||||
mcs_data.size = 512;
|
mcs_data.size = 512;
|
||||||
mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
|
mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
|
||||||
sec_out_mcs_data(&mcs_data);
|
sec_out_mcs_data(&mcs_data, selected_proto);
|
||||||
|
|
||||||
if (!mcs_connect(server, &mcs_data, username, reconnect))
|
/* finialize the MCS connect sequence */
|
||||||
|
if (!mcs_connect_finalize(&mcs_data))
|
||||||
return False;
|
return False;
|
||||||
|
|
||||||
/* sec_process_mcs_data(&mcs_data); */
|
/* sec_process_mcs_data(&mcs_data); */
|
||||||
|
170
tcp.c
170
tcp.c
@ -29,6 +29,10 @@
|
|||||||
#include <errno.h> /* errno */
|
#include <errno.h> /* errno */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
#include <openssl/x509.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
|
||||||
#include "rdesktop.h"
|
#include "rdesktop.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@ -52,6 +56,8 @@
|
|||||||
#define STREAM_COUNT 1
|
#define STREAM_COUNT 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static SSL *g_ssl = NULL;
|
||||||
|
static SSL_CTX *g_ssl_ctx = NULL;
|
||||||
static int g_sock;
|
static int g_sock;
|
||||||
static struct stream g_in;
|
static struct stream g_in;
|
||||||
static struct stream g_out[STREAM_COUNT];
|
static struct stream g_out[STREAM_COUNT];
|
||||||
@ -109,6 +115,7 @@ tcp_init(uint32 maxlen)
|
|||||||
void
|
void
|
||||||
tcp_send(STREAM s)
|
tcp_send(STREAM s)
|
||||||
{
|
{
|
||||||
|
int ssl_err;
|
||||||
int length = s->end - s->data;
|
int length = s->end - s->data;
|
||||||
int sent, total = 0;
|
int sent, total = 0;
|
||||||
|
|
||||||
@ -116,6 +123,27 @@ tcp_send(STREAM s)
|
|||||||
scard_lock(SCARD_LOCK_TCP);
|
scard_lock(SCARD_LOCK_TCP);
|
||||||
#endif
|
#endif
|
||||||
while (total < length)
|
while (total < length)
|
||||||
|
{
|
||||||
|
if (g_ssl)
|
||||||
|
{
|
||||||
|
sent = SSL_write(g_ssl, s->data + total, length - total);
|
||||||
|
if (sent <= 0)
|
||||||
|
{
|
||||||
|
ssl_err = SSL_get_error(g_ssl, sent);
|
||||||
|
if (sent < 0 && (ssl_err == SSL_ERROR_WANT_READ ||
|
||||||
|
ssl_err == SSL_ERROR_WANT_WRITE))
|
||||||
|
{
|
||||||
|
tcp_can_send(g_sock, 100);
|
||||||
|
sent = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error("SSL_write: %d (%s)\n", ssl_err, TCP_STRERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
sent = send(g_sock, s->data + total, length - total, 0);
|
sent = send(g_sock, s->data + total, length - total, 0);
|
||||||
if (sent <= 0)
|
if (sent <= 0)
|
||||||
@ -131,6 +159,7 @@ tcp_send(STREAM s)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
total += sent;
|
total += sent;
|
||||||
}
|
}
|
||||||
#ifdef WITH_SCARD
|
#ifdef WITH_SCARD
|
||||||
@ -143,7 +172,7 @@ STREAM
|
|||||||
tcp_recv(STREAM s, uint32 length)
|
tcp_recv(STREAM s, uint32 length)
|
||||||
{
|
{
|
||||||
uint32 new_length, end_offset, p_offset;
|
uint32 new_length, end_offset, p_offset;
|
||||||
int rcvd = 0;
|
int rcvd = 0, ssl_err;
|
||||||
|
|
||||||
if (s == NULL)
|
if (s == NULL)
|
||||||
{
|
{
|
||||||
@ -173,13 +202,37 @@ tcp_recv(STREAM s, uint32 length)
|
|||||||
|
|
||||||
while (length > 0)
|
while (length > 0)
|
||||||
{
|
{
|
||||||
if (!ui_select(g_sock))
|
if ((!g_ssl || SSL_pending(g_ssl) <= 0) && !ui_select(g_sock))
|
||||||
{
|
{
|
||||||
/* User quit */
|
/* User quit */
|
||||||
g_user_quit = True;
|
g_user_quit = True;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g_ssl)
|
||||||
|
{
|
||||||
|
rcvd = SSL_read(g_ssl, s->end, length);
|
||||||
|
ssl_err = SSL_get_error(g_ssl, rcvd);
|
||||||
|
|
||||||
|
if (ssl_err == SSL_ERROR_SSL)
|
||||||
|
{
|
||||||
|
ERR_print_errors_fp(stdout);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ssl_err == SSL_ERROR_WANT_READ || ssl_err == SSL_ERROR_WANT_WRITE)
|
||||||
|
{
|
||||||
|
rcvd = 0;
|
||||||
|
}
|
||||||
|
else if (ssl_err != SSL_ERROR_NONE)
|
||||||
|
{
|
||||||
|
error("SSL_read: %d (%s)\n", ssl_err, TCP_STRERROR);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
rcvd = recv(g_sock, s->end, length, 0);
|
rcvd = recv(g_sock, s->end, length, 0);
|
||||||
if (rcvd < 0)
|
if (rcvd < 0)
|
||||||
{
|
{
|
||||||
@ -198,6 +251,7 @@ tcp_recv(STREAM s, uint32 length)
|
|||||||
error("Connection closed\n");
|
error("Connection closed\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
s->end += rcvd;
|
s->end += rcvd;
|
||||||
length -= rcvd;
|
length -= rcvd;
|
||||||
@ -206,6 +260,108 @@ tcp_recv(STREAM s, uint32 length)
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Establish a SSL/TLS 1.0 connection */
|
||||||
|
RD_BOOL
|
||||||
|
tcp_tls_connect(void)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
SSL_load_error_strings();
|
||||||
|
SSL_library_init();
|
||||||
|
|
||||||
|
g_ssl_ctx = SSL_CTX_new(TLSv1_client_method());
|
||||||
|
if (g_ssl_ctx == NULL)
|
||||||
|
{
|
||||||
|
error("tcp_tls_connect: SSL_CTX_new() failed to create TLS v1.0 context\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
SSL_CTX_set_options(g_ssl_ctx, SSL_OP_ALL);
|
||||||
|
|
||||||
|
g_ssl = SSL_new(g_ssl_ctx);
|
||||||
|
if (g_ssl == NULL)
|
||||||
|
{
|
||||||
|
error("tcp_tls_connect: SSL_new() failed\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SSL_set_fd(g_ssl, g_sock) < 1)
|
||||||
|
{
|
||||||
|
error("tcp_tls_connect: SSL_set_fd() failed\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
err = SSL_connect(g_ssl);
|
||||||
|
}
|
||||||
|
while (SSL_get_error(g_ssl, err) == SSL_ERROR_WANT_READ);
|
||||||
|
|
||||||
|
if (err < 0)
|
||||||
|
{
|
||||||
|
ERR_print_errors_fp(stdout);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
return True;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (g_ssl)
|
||||||
|
SSL_free(g_ssl);
|
||||||
|
if (g_ssl_ctx)
|
||||||
|
SSL_CTX_free(g_ssl_ctx);
|
||||||
|
|
||||||
|
g_ssl = NULL;
|
||||||
|
g_ssl_ctx = NULL;
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get public key from server of TLS 1.0 connection */
|
||||||
|
RD_BOOL
|
||||||
|
tcp_tls_get_server_pubkey(STREAM s)
|
||||||
|
{
|
||||||
|
X509 *cert = NULL;
|
||||||
|
EVP_PKEY *pkey = NULL;
|
||||||
|
|
||||||
|
s->data = s->p = NULL;
|
||||||
|
s->size = 0;
|
||||||
|
|
||||||
|
if (g_ssl == NULL)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
cert = SSL_get_peer_certificate(g_ssl);
|
||||||
|
if (cert == NULL)
|
||||||
|
{
|
||||||
|
error("tcp_tls_get_server_pubkey: SSL_get_peer_certificate() failed\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
pkey = X509_get_pubkey(cert);
|
||||||
|
if (pkey == NULL)
|
||||||
|
{
|
||||||
|
error("tcp_tls_get_server_pubkey: X509_get_pubkey() failed\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
s->size = i2d_PublicKey(pkey, NULL);
|
||||||
|
if (s->size < 1)
|
||||||
|
{
|
||||||
|
error("tcp_tls_get_server_pubkey: i2d_PublicKey() failed\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
s->data = s->p = xmalloc(s->size + 1);
|
||||||
|
i2d_PublicKey(pkey, &s->p);
|
||||||
|
s->end = s->p;
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (cert)
|
||||||
|
X509_free(cert);
|
||||||
|
if (pkey)
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
return (s->size != 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Establish a connection on the TCP layer */
|
/* Establish a connection on the TCP layer */
|
||||||
RD_BOOL
|
RD_BOOL
|
||||||
tcp_connect(char *server)
|
tcp_connect(char *server)
|
||||||
@ -318,6 +474,16 @@ tcp_connect(char *server)
|
|||||||
void
|
void
|
||||||
tcp_disconnect(void)
|
tcp_disconnect(void)
|
||||||
{
|
{
|
||||||
|
int err;
|
||||||
|
if (g_ssl)
|
||||||
|
{
|
||||||
|
err = SSL_shutdown(g_ssl);
|
||||||
|
SSL_free(g_ssl);
|
||||||
|
g_ssl = NULL;
|
||||||
|
SSL_CTX_free(g_ssl_ctx);
|
||||||
|
g_ssl_ctx = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
TCP_CLOSE(g_sock);
|
TCP_CLOSE(g_sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
9
types.h
9
types.h
@ -36,6 +36,15 @@ typedef void *RD_HGLYPH;
|
|||||||
typedef void *RD_HCOLOURMAP;
|
typedef void *RD_HCOLOURMAP;
|
||||||
typedef void *RD_HCURSOR;
|
typedef void *RD_HCURSOR;
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum _RDP_VERSION
|
||||||
|
{
|
||||||
|
RDP_V4 = 4,
|
||||||
|
RDP_V5 = 5,
|
||||||
|
RDP_V6 = 6
|
||||||
|
} RDP_VERSION;
|
||||||
|
|
||||||
|
|
||||||
typedef struct _RD_POINT
|
typedef struct _RD_POINT
|
||||||
{
|
{
|
||||||
sint16 x, y;
|
sint16 x, y;
|
||||||
|
@ -47,7 +47,7 @@ extern int g_keyboard_subtype;
|
|||||||
extern int g_keyboard_functionkeys;
|
extern int g_keyboard_functionkeys;
|
||||||
extern int g_win_button_size;
|
extern int g_win_button_size;
|
||||||
extern RD_BOOL g_enable_compose;
|
extern RD_BOOL g_enable_compose;
|
||||||
extern RD_BOOL g_use_rdp5;
|
extern RDP_VERSION g_rdp_version;
|
||||||
extern RD_BOOL g_numlock_sync;
|
extern RD_BOOL g_numlock_sync;
|
||||||
|
|
||||||
static RD_BOOL keymap_loaded;
|
static RD_BOOL keymap_loaded;
|
||||||
@ -467,7 +467,7 @@ send_winkey(uint32 ev_time, RD_BOOL pressed, RD_BOOL leftkey)
|
|||||||
|
|
||||||
if (pressed)
|
if (pressed)
|
||||||
{
|
{
|
||||||
if (g_use_rdp5)
|
if (g_rdp_version >= RDP_V5)
|
||||||
{
|
{
|
||||||
rdp_send_scancode(ev_time, RDP_KEYPRESS, winkey);
|
rdp_send_scancode(ev_time, RDP_KEYPRESS, winkey);
|
||||||
}
|
}
|
||||||
@ -481,7 +481,7 @@ send_winkey(uint32 ev_time, RD_BOOL pressed, RD_BOOL leftkey)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* key released */
|
/* key released */
|
||||||
if (g_use_rdp5)
|
if (g_rdp_version >= RDP_V5)
|
||||||
{
|
{
|
||||||
rdp_send_scancode(ev_time, RDP_KEYRELEASE, winkey);
|
rdp_send_scancode(ev_time, RDP_KEYRELEASE, winkey);
|
||||||
}
|
}
|
||||||
@ -496,7 +496,7 @@ send_winkey(uint32 ev_time, RD_BOOL pressed, RD_BOOL leftkey)
|
|||||||
static void
|
static void
|
||||||
reset_winkey(uint32 ev_time)
|
reset_winkey(uint32 ev_time)
|
||||||
{
|
{
|
||||||
if (g_use_rdp5)
|
if (g_rdp_version >= RDP_V5)
|
||||||
{
|
{
|
||||||
/* For some reason, it seems to suffice to release
|
/* For some reason, it seems to suffice to release
|
||||||
*either* the left or right winkey. */
|
*either* the left or right winkey. */
|
||||||
|
Loading…
Reference in New Issue
Block a user