Implemented support for "Client Auto-Reconnect". This means that the

client can re-connect using a cookie, instead of going through the
normal authentication. This patch saves those cookies, and uses them
during logon. 

Note that this feature is currently unused. It remains to add support
for, say, detecting when the TCP connection has gone done and restart
a new one. 



git-svn-id: svn://svn.code.sf.net/p/rdesktop/code/rdesktop/trunk@1539 423420c4-83ab-492f-b58f-81f9feb106b5
This commit is contained in:
Peter Åstrand 2010-01-12 10:34:38 +00:00
parent d0327a9989
commit 1b4c36a45f
6 changed files with 96 additions and 7 deletions

View File

@ -121,12 +121,26 @@ enum RDP_DATA_PDU_TYPE
RDP_DATA_PDU_SYNCHRONISE = 31,
RDP_DATA_PDU_BELL = 34,
RDP_DATA_PDU_CLIENT_WINDOW_STATUS = 35,
RDP_DATA_PDU_LOGON = 38,
RDP_DATA_PDU_LOGON = 38, /* PDUTYPE2_SAVE_SESSION_INFO */
RDP_DATA_PDU_FONT2 = 39,
RDP_DATA_PDU_KEYBOARD_INDICATORS = 41,
RDP_DATA_PDU_DISCONNECT = 47
};
enum RDP_SAVE_SESSION_PDU_TYPE
{
INFOTYPE_LOGON = 0,
INFOTYPE_LOGON_LONG = 1,
INFOTYPE_LOGON_PLAINNOTIFY = 2,
INFOTYPE_LOGON_EXTENDED_INF = 3
};
enum RDP_LOGON_INFO_EXTENDED_TYPE
{
LOGON_EX_AUTORECONNECTCOOKIE = 1,
LOGON_EX_LOGONERRORS = 2
};
enum RDP_CONTROL_PDU_TYPE
{
RDP_CTL_REQUEST_CONTROL = 1,

View File

@ -103,6 +103,10 @@ char *g_redirect_username;
char g_redirect_cookie[128];
uint32 g_redirect_flags = 0;
uint32 g_reconnect_logonid = 0;
char g_reconnect_random[16];
uint8 g_client_random[SEC_RANDOM_SIZE];
#ifdef WITH_RDPSND
RD_BOOL g_rdpsnd = False;
#endif

61
rdp.c
View File

@ -67,6 +67,10 @@ extern char g_redirect_cookie[128];
extern uint32 g_redirect_flags;
/* END Session Directory support */
extern uint32 g_reconnect_logonid;
extern char g_reconnect_random[16];
extern uint8 g_client_random[SEC_RANDOM_SIZE];
#if WITH_DEBUG
static uint32 g_packetno;
#endif
@ -331,6 +335,7 @@ rdp_send_logon_info(uint32 flags, char *domain, char *user,
STREAM s;
time_t t = time(NULL);
time_t tzone;
uint8 security_verifier[16];
if (!g_use_rdp5 || 1 == g_server_rdp_version)
{
@ -456,9 +461,16 @@ rdp_send_logon_info(uint32 flags, char *domain, char *user,
/* Rest of TS_EXTENDED_INFO_PACKET */
out_uint32_le(s, 0xfffffffe); /* clientSessionId, consider changing to 0 */
out_uint32_le(s, g_rdp5_performanceflags);
out_uint16(s, 0);
/* Client Auto-Reconnect */
out_uint16_le(s, 28); /* cbAutoReconnectLen */
/* ARC_CS_PRIVATE_PACKET */
out_uint32_le(s, 28); /* cbLen */
out_uint32_le(s, 1); /* Version */
out_uint32_le(s, g_reconnect_logonid); /* LogonId */
ssl_hmac_md5(g_reconnect_random, sizeof(g_reconnect_random),
g_client_random, SEC_RANDOM_SIZE, security_verifier);
out_uint8a(s, security_verifier, sizeof(security_verifier));
}
s_mark_end(s);
sec_send(s, sec_flags);
@ -1306,6 +1318,50 @@ process_update_pdu(STREAM s)
ui_end_update();
}
/* Process a Save Session Info PDU */
void
process_pdu_logon(STREAM s)
{
uint32 infotype;
in_uint32_le(s, infotype);
if (infotype == INFOTYPE_LOGON_EXTENDED_INF)
{
uint32 fieldspresent;
in_uint8s(s, 2); /* Length */
in_uint32_le(s, fieldspresent);
if (fieldspresent & LOGON_EX_AUTORECONNECTCOOKIE)
{
uint32 len;
uint32 version;
/* TS_LOGON_INFO_FIELD */
in_uint8s(s, 4); /* cbFieldData */
/* ARC_SC_PRIVATE_PACKET */
in_uint32_le(s, len);
if (len != 28)
{
warning("Invalid length in Auto-Reconnect packet\n");
return;
}
in_uint32_le(s, version);
if (version != 1)
{
warning("Unsupported version of Auto-Reconnect packet\n");
return;
}
in_uint32_le(s, g_reconnect_logonid);
in_uint8a(s, g_reconnect_random, 16);
DEBUG(("Saving auto-reconnect cookie, id=%u\n", g_reconnect_logonid));
}
}
}
/* Process a disconnect PDU */
void
process_disconnect_pdu(STREAM s, uint32 * ext_disc_reason)
@ -1382,6 +1438,7 @@ process_data_pdu(STREAM s, uint32 * ext_disc_reason)
case RDP_DATA_PDU_LOGON:
DEBUG(("Received Logon PDU\n"));
/* User logged on */
process_pdu_logon(s);
break;
case RDP_DATA_PDU_DISCONNECT:

View File

@ -34,6 +34,7 @@ extern RD_BOOL g_console_session;
extern int g_server_depth;
extern VCHANNEL g_channels[];
extern unsigned int g_num_channels;
extern uint8 g_client_random[SEC_RANDOM_SIZE];
static int g_rc4_key_len;
static SSL_RC4 g_rc4_decrypt_key;
@ -667,7 +668,6 @@ static void
sec_process_crypt_info(STREAM s)
{
uint8 *server_random = NULL;
uint8 client_random[SEC_RANDOM_SIZE];
uint8 modulus[SEC_MAX_MODULUS_SIZE];
uint8 exponent[SEC_EXPONENT_SIZE];
uint32 rc4_key_size;
@ -680,10 +680,10 @@ sec_process_crypt_info(STREAM s)
return;
}
DEBUG(("Generating client random\n"));
generate_random(client_random);
sec_rsa_encrypt(g_sec_crypted_random, client_random, SEC_RANDOM_SIZE,
generate_random(g_client_random);
sec_rsa_encrypt(g_sec_crypted_random, g_client_random, SEC_RANDOM_SIZE,
g_server_public_key_len, modulus, exponent);
sec_generate_keys(client_random, server_random, rc4_key_size);
sec_generate_keys(g_client_random, server_random, rc4_key_size);
}

10
ssl.c
View File

@ -223,3 +223,13 @@ ssl_sig_ok(uint8 * exponent, uint32 exp_len, uint8 * modulus, uint32 mod_len,
*/
return True;
}
void
ssl_hmac_md5(const void *key, int key_len, const unsigned char *msg, int msg_len, unsigned char *md)
{
HMAC_CTX ctx;
HMAC_CTX_init(&ctx);
HMAC(EVP_md5(), key, key_len, msg, msg_len, md, NULL);
HMAC_CTX_cleanup(&ctx);
}

4
ssl.h
View File

@ -26,6 +26,7 @@
#include <openssl/sha.h>
#include <openssl/bn.h>
#include <openssl/x509v3.h>
#include <openssl/hmac.h>
#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x0090800f)
#define D2I_X509_CONST const
@ -60,4 +61,7 @@ int ssl_rkey_get_exp_mod(SSL_RKEY * rkey, uint8 * exponent, uint32 max_exp_len,
RD_BOOL ssl_sig_ok(uint8 * exponent, uint32 exp_len, uint8 * modulus, uint32 mod_len,
uint8 * signature, uint32 sig_len);
void ssl_hmac_md5(const void *key, int key_len,
const unsigned char *msg, int msg_len, unsigned char *md);
#endif