--- sourceforge.net/trunk/rdesktop/licence.c 2003/04/16 08:19:15 365 +++ sourceforge.net/trunk/rdesktop/licence.c 2007/01/09 07:24:44 1374 @@ -1,8 +1,8 @@ -/* +/* -*- c-basic-offset: 8 -*- rdesktop: A Remote Desktop Protocol client. RDP licensing negotiation - Copyright (C) Matthew Chapman 1999-2002 - + Copyright (C) Matthew Chapman 1999-2007 + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or @@ -12,51 +12,46 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "rdesktop.h" +#include "ssl.h" -#ifdef WITH_OPENSSL -#include -#else -#include "crypto/rc4.h" -#endif +extern char g_username[64]; +extern char g_hostname[16]; -extern char username[16]; -extern char hostname[16]; +static uint8 g_licence_key[16]; +static uint8 g_licence_sign_key[16]; -static uint8 licence_key[16]; -static uint8 licence_sign_key[16]; - -BOOL licence_issued = False; +RD_BOOL g_licence_issued = False; /* Generate a session key and RC4 keys, given client and server randoms */ static void -licence_generate_keys(uint8 * client_key, uint8 * server_key, uint8 * client_rsa) +licence_generate_keys(uint8 * client_random, uint8 * server_random, uint8 * pre_master_secret) { - uint8 session_key[48]; - uint8 temp_hash[48]; + uint8 master_secret[48]; + uint8 key_block[48]; - /* Generate session key - two rounds of sec_hash_48 */ - sec_hash_48(temp_hash, client_rsa, client_key, server_key, 65); - sec_hash_48(session_key, temp_hash, server_key, client_key, 65); + /* Generate master secret and then key material */ + sec_hash_48(master_secret, pre_master_secret, client_random, server_random, 'A'); + sec_hash_48(key_block, master_secret, server_random, client_random, 'A'); - /* Store first 16 bytes of session key, for generating signatures */ - memcpy(licence_sign_key, session_key, 16); + /* Store first 16 bytes of session key as MAC secret */ + memcpy(g_licence_sign_key, key_block, 16); - /* Generate RC4 key */ - sec_hash_16(licence_key, &session_key[16], client_key, server_key); + /* Generate RC4 key from next 16 bytes */ + sec_hash_16(g_licence_key, &key_block[16], client_random, server_random); } static void licence_generate_hwid(uint8 * hwid) { buf_out_uint32(hwid, 2); - strncpy((char *) (hwid + 4), hostname, LICENCE_HWID_SIZE - 4); + strncpy((char *) (hwid + 4), g_hostname, LICENCE_HWID_SIZE - 4); } /* Present an existing licence to the server */ @@ -72,7 +67,8 @@ s = sec_init(sec_flags, length + 4); - out_uint16_le(s, LICENCE_TAG_PRESENT); + out_uint8(s, LICENCE_TAG_PRESENT); + out_uint8(s, 2); /* version */ out_uint16_le(s, length); out_uint32_le(s, 1); @@ -111,7 +107,8 @@ s = sec_init(sec_flags, length + 2); - out_uint16_le(s, LICENCE_TAG_REQUEST); + out_uint8(s, LICENCE_TAG_REQUEST); + out_uint8(s, 2); /* version */ out_uint16_le(s, length); out_uint32_le(s, 1); @@ -146,7 +143,7 @@ uint8 hwid[LICENCE_HWID_SIZE]; uint8 *licence_data; int licence_size; - RC4_KEY crypt_key; + SSL_RC4 crypt_key; /* Retrieve the server random from the incoming packet */ in_uint8p(s, server_random, SEC_RANDOM_SIZE); @@ -157,22 +154,22 @@ licence_generate_keys(null_data, server_random, null_data); licence_size = load_licence(&licence_data); - if (licence_size != -1) + if (licence_size > 0) { /* Generate a signature for the HWID buffer */ licence_generate_hwid(hwid); - sec_sign(signature, 16, licence_sign_key, 16, hwid, sizeof(hwid)); + sec_sign(signature, 16, g_licence_sign_key, 16, hwid, sizeof(hwid)); /* Now encrypt the HWID */ - RC4_set_key(&crypt_key, 16, licence_key); - RC4(&crypt_key, sizeof(hwid), hwid, hwid); + ssl_rc4_set_key(&crypt_key, g_licence_key, 16); + ssl_rc4_crypt(&crypt_key, hwid, hwid, sizeof(hwid)); licence_present(null_data, null_data, licence_data, licence_size, hwid, signature); xfree(licence_data); return; } - licence_send_request(null_data, null_data, username, hostname); + licence_send_request(null_data, null_data, g_username, g_hostname); } /* Send an authentication response packet */ @@ -185,7 +182,8 @@ s = sec_init(sec_flags, length + 2); - out_uint16_le(s, LICENCE_TAG_AUTHRESP); + out_uint8(s, LICENCE_TAG_AUTHRESP); + out_uint8(s, 2); /* version */ out_uint16_le(s, length); out_uint16_le(s, 1); @@ -203,7 +201,7 @@ } /* Parse an authentication request packet */ -static BOOL +static RD_BOOL licence_parse_authreq(STREAM s, uint8 ** token, uint8 ** signature) { uint16 tokenlen; @@ -227,30 +225,30 @@ static void licence_process_authreq(STREAM s) { - uint8 *in_token, *in_sig; + uint8 *in_token = NULL, *in_sig; uint8 out_token[LICENCE_TOKEN_SIZE], decrypt_token[LICENCE_TOKEN_SIZE]; uint8 hwid[LICENCE_HWID_SIZE], crypt_hwid[LICENCE_HWID_SIZE]; uint8 sealed_buffer[LICENCE_TOKEN_SIZE + LICENCE_HWID_SIZE]; uint8 out_sig[LICENCE_SIGNATURE_SIZE]; - RC4_KEY crypt_key; + SSL_RC4 crypt_key; /* Parse incoming packet and save the encrypted token */ licence_parse_authreq(s, &in_token, &in_sig); memcpy(out_token, in_token, LICENCE_TOKEN_SIZE); /* Decrypt the token. It should read TEST in Unicode. */ - RC4_set_key(&crypt_key, 16, licence_key); - RC4(&crypt_key, LICENCE_TOKEN_SIZE, in_token, decrypt_token); + ssl_rc4_set_key(&crypt_key, g_licence_key, 16); + ssl_rc4_crypt(&crypt_key, in_token, decrypt_token, LICENCE_TOKEN_SIZE); /* Generate a signature for a buffer of token and HWID */ licence_generate_hwid(hwid); memcpy(sealed_buffer, decrypt_token, LICENCE_TOKEN_SIZE); memcpy(sealed_buffer + LICENCE_TOKEN_SIZE, hwid, LICENCE_HWID_SIZE); - sec_sign(out_sig, 16, licence_sign_key, 16, sealed_buffer, sizeof(sealed_buffer)); + sec_sign(out_sig, 16, g_licence_sign_key, 16, sealed_buffer, sizeof(sealed_buffer)); /* Now encrypt the HWID */ - RC4_set_key(&crypt_key, 16, licence_key); - RC4(&crypt_key, LICENCE_HWID_SIZE, hwid, crypt_hwid); + ssl_rc4_set_key(&crypt_key, g_licence_key, 16); + ssl_rc4_crypt(&crypt_key, hwid, crypt_hwid, LICENCE_HWID_SIZE); licence_send_authresp(out_token, crypt_hwid, out_sig); } @@ -259,24 +257,39 @@ static void licence_process_issue(STREAM s) { - RC4_KEY crypt_key; + SSL_RC4 crypt_key; uint32 length; uint16 check; + int i; in_uint8s(s, 2); /* 3d 45 - unknown */ in_uint16_le(s, length); if (!s_check_rem(s, length)) return; - RC4_set_key(&crypt_key, 16, licence_key); - RC4(&crypt_key, length, s->p, s->p); + ssl_rc4_set_key(&crypt_key, g_licence_key, 16); + ssl_rc4_crypt(&crypt_key, s->p, s->p, length); in_uint16(s, check); if (check != 0) return; - licence_issued = True; - save_licence(s->p, length - 2); + g_licence_issued = True; + + in_uint8s(s, 2); /* pad */ + + /* advance to fourth string */ + length = 0; + for (i = 0; i < 4; i++) + { + in_uint8s(s, length); + in_uint32_le(s, length); + if (!s_check_rem(s, length)) + return; + } + + g_licence_issued = True; + save_licence(s->p, length); } /* Process a licence packet */