From 1b4c36a45fb2c473cec06746f30f89747b4ae3f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20=C3=85strand?= Date: Tue, 12 Jan 2010 10:34:38 +0000 Subject: [PATCH] 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 --- constants.h | 16 +++++++++++++- rdesktop.c | 4 ++++ rdp.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++-- secure.c | 8 +++---- ssl.c | 10 +++++++++ ssl.h | 4 ++++ 6 files changed, 96 insertions(+), 7 deletions(-) diff --git a/constants.h b/constants.h index 9801591..f262bd1 100644 --- a/constants.h +++ b/constants.h @@ -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, diff --git a/rdesktop.c b/rdesktop.c index f7c3e90..64f4bb3 100644 --- a/rdesktop.c +++ b/rdesktop.c @@ -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 diff --git a/rdp.c b/rdp.c index f5a2742..3d880dd 100644 --- a/rdp.c +++ b/rdp.c @@ -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: diff --git a/secure.c b/secure.c index 48f8d7f..55ee69e 100644 --- a/secure.c +++ b/secure.c @@ -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); } diff --git a/ssl.c b/ssl.c index 0655680..fb1e729 100644 --- a/ssl.c +++ b/ssl.c @@ -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); +} diff --git a/ssl.h b/ssl.h index 42150e9..92ed9f1 100644 --- a/ssl.h +++ b/ssl.h @@ -26,6 +26,7 @@ #include #include #include +#include #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