secure.c revision 6e9aa255e3376b2da5824c09c4c62bc233463bfe
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/* -*- c-basic-offset: 8 -*-
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdesktop: A Remote Desktop Protocol client.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync Protocol services - RDP encryption and licensing
a180a41bba1d50822df23fff0099e90b86638b89vboxsync Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
a180a41bba1d50822df23fff0099e90b86638b89vboxsync Copyright 2005-2011 Peter Astrand <astrand@cendio.se> for Cendio AB
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync This program is free software: you can redistribute it and/or modify
a180a41bba1d50822df23fff0099e90b86638b89vboxsync it under the terms of the GNU General Public License as published by
a180a41bba1d50822df23fff0099e90b86638b89vboxsync the Free Software Foundation, either version 3 of the License, or
a180a41bba1d50822df23fff0099e90b86638b89vboxsync (at your option) any later version.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync This program is distributed in the hope that it will be useful,
a180a41bba1d50822df23fff0099e90b86638b89vboxsync but WITHOUT ANY WARRANTY; without even the implied warranty of
a180a41bba1d50822df23fff0099e90b86638b89vboxsync MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
a180a41bba1d50822df23fff0099e90b86638b89vboxsync GNU General Public License for more details.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync You should have received a copy of the GNU General Public License
a180a41bba1d50822df23fff0099e90b86638b89vboxsync along with this program. If not, see <http://www.gnu.org/licenses/>.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync*/
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
6e9aa255e3376b2da5824c09c4c62bc233463bfevboxsync/*
6e9aa255e3376b2da5824c09c4c62bc233463bfevboxsync * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
6e9aa255e3376b2da5824c09c4c62bc233463bfevboxsync * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
6e9aa255e3376b2da5824c09c4c62bc233463bfevboxsync * the General Public License version 2 (GPLv2) at this time for any software where
6e9aa255e3376b2da5824c09c4c62bc233463bfevboxsync * a choice of GPL license versions is made available with the language indicating
6e9aa255e3376b2da5824c09c4c62bc233463bfevboxsync * that GPLv2 or any later version may be used, or where a choice of which version
6e9aa255e3376b2da5824c09c4c62bc233463bfevboxsync * of the GPL is applied is otherwise unspecified.
6e9aa255e3376b2da5824c09c4c62bc233463bfevboxsync */
6e9aa255e3376b2da5824c09c4c62bc233463bfevboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync#include "rdesktop.h"
a180a41bba1d50822df23fff0099e90b86638b89vboxsync#include "ssl.h"
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncextern char g_hostname[16];
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncextern int g_width;
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncextern int g_height;
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncextern unsigned int g_keylayout;
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncextern int g_keyboard_type;
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncextern int g_keyboard_subtype;
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncextern int g_keyboard_functionkeys;
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncextern RD_BOOL g_encryption;
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncextern RD_BOOL g_licence_issued;
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncextern RD_BOOL g_licence_error_result;
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncextern RDP_VERSION g_rdp_version;
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncextern RD_BOOL g_console_session;
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncextern uint32 g_redirect_session_id;
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncextern int g_server_depth;
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncextern VCHANNEL g_channels[];
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncextern unsigned int g_num_channels;
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncextern uint8 g_client_random[SEC_RANDOM_SIZE];
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic int g_rc4_key_len;
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic RDSSL_RC4 g_rc4_decrypt_key;
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic RDSSL_RC4 g_rc4_encrypt_key;
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic uint32 g_server_public_key_len;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic uint8 g_sec_sign_key[16];
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic uint8 g_sec_decrypt_key[16];
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic uint8 g_sec_encrypt_key[16];
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic uint8 g_sec_decrypt_update_key[16];
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic uint8 g_sec_encrypt_update_key[16];
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic uint8 g_sec_crypted_random[SEC_MAX_MODULUS_SIZE];
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncuint16 g_server_rdp_version = 0;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/* These values must be available to reset state - Session Directory */
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic int g_sec_encrypt_use_count = 0;
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic int g_sec_decrypt_use_count = 0;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/*
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * I believe this is based on SSLv3 with the following differences:
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * MAC algorithm (5.2.3.1) uses only 32-bit length in place of seq_num/type/length fields
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * MAC algorithm uses SHA1 and MD5 for the two hash functions instead of one or other
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * key_block algorithm (6.2.2) uses 'X', 'YY', 'ZZZ' instead of 'A', 'BB', 'CCC'
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * key_block partitioning is different (16 bytes each: MAC secret, decrypt key, encrypt key)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * encryption/decryption keys updated every 4096 packets
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * See http://wp.netscape.com/eng/ssl3/draft302.txt
a180a41bba1d50822df23fff0099e90b86638b89vboxsync */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/*
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * 48-byte transformation used to generate master secret (6.1) and key material (6.2.2).
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * Both SHA1 and MD5 algorithms are used.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync */
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncvoid
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncsec_hash_48(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2, uint8 salt)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint8 shasig[20];
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint8 pad[4];
a180a41bba1d50822df23fff0099e90b86638b89vboxsync RDSSL_SHA1 sha1;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync RDSSL_MD5 md5;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync int i;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync for (i = 0; i < 3; i++)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync memset(pad, salt + i, i + 1);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_sha1_init(&sha1);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_sha1_update(&sha1, pad, i + 1);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_sha1_update(&sha1, in, 48);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_sha1_update(&sha1, salt1, 32);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_sha1_update(&sha1, salt2, 32);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_sha1_final(&sha1, shasig);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_md5_init(&md5);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_md5_update(&md5, in, 48);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_md5_update(&md5, shasig, 20);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_md5_final(&md5, &out[i * 16]);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/*
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * 16-byte transformation used to generate export keys (6.2.2).
a180a41bba1d50822df23fff0099e90b86638b89vboxsync */
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncvoid
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncsec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync RDSSL_MD5 md5;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_md5_init(&md5);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_md5_update(&md5, in, 16);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_md5_update(&md5, salt1, 32);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_md5_update(&md5, salt2, 32);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_md5_final(&md5, out);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/*
a180a41bba1d50822df23fff0099e90b86638b89vboxsync * 16-byte sha1 hash
a180a41bba1d50822df23fff0099e90b86638b89vboxsync */
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncvoid
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncsec_hash_sha1_16(uint8 * out, uint8 * in, uint8 * salt1)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync RDSSL_SHA1 sha1;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_sha1_init(&sha1);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_sha1_update(&sha1, in, 16);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_sha1_update(&sha1, salt1, 16);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_sha1_final(&sha1, out);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/* create string from hash */
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncvoid
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncsec_hash_to_string(char *out, int out_size, uint8 * in, int in_size)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync int k;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync memset(out, 0, out_size);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync for (k = 0; k < in_size; k++, out += 2)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync sprintf(out, "%.2x", in[k]);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/* Reduce key entropy from 64 to 40 bits */
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic void
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncsec_make_40bit(uint8 * key)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync key[0] = 0xd1;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync key[1] = 0x26;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync key[2] = 0x9e;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/* Generate encryption keys given client and server randoms */
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic void
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncsec_generate_keys(uint8 * client_random, uint8 * server_random, int rc4_key_size)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint8 pre_master_secret[48];
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint8 master_secret[48];
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint8 key_block[48];
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* Construct pre-master secret */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync memcpy(pre_master_secret, client_random, 24);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync memcpy(pre_master_secret + 24, server_random, 24);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* Generate master secret and then key material */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync sec_hash_48(master_secret, pre_master_secret, client_random, server_random, 'A');
a180a41bba1d50822df23fff0099e90b86638b89vboxsync sec_hash_48(key_block, master_secret, client_random, server_random, 'X');
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* First 16 bytes of key material is MAC secret */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync memcpy(g_sec_sign_key, key_block, 16);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* Generate export keys from next two blocks of 16 bytes */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync sec_hash_16(g_sec_decrypt_key, &key_block[16], client_random, server_random);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync sec_hash_16(g_sec_encrypt_key, &key_block[32], client_random, server_random);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (rc4_key_size == 1)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync DEBUG(("40-bit encryption enabled\n"));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync sec_make_40bit(g_sec_sign_key);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync sec_make_40bit(g_sec_decrypt_key);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync sec_make_40bit(g_sec_encrypt_key);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync g_rc4_key_len = 8;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync else
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync DEBUG(("rc_4_key_size == %d, 128-bit encryption enabled\n", rc4_key_size));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync g_rc4_key_len = 16;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* Save initial RC4 keys as update keys */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync memcpy(g_sec_decrypt_update_key, g_sec_decrypt_key, 16);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync memcpy(g_sec_encrypt_update_key, g_sec_encrypt_key, 16);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* Initialise RC4 state arrays */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_rc4_set_key(&g_rc4_decrypt_key, g_sec_decrypt_key, g_rc4_key_len);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_rc4_set_key(&g_rc4_encrypt_key, g_sec_encrypt_key, g_rc4_key_len);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic uint8 pad_54[40] = {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
a180a41bba1d50822df23fff0099e90b86638b89vboxsync 54, 54, 54,
a180a41bba1d50822df23fff0099e90b86638b89vboxsync 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
a180a41bba1d50822df23fff0099e90b86638b89vboxsync 54, 54, 54
a180a41bba1d50822df23fff0099e90b86638b89vboxsync};
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic uint8 pad_92[48] = {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
a180a41bba1d50822df23fff0099e90b86638b89vboxsync 92, 92, 92, 92, 92, 92, 92,
a180a41bba1d50822df23fff0099e90b86638b89vboxsync 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
a180a41bba1d50822df23fff0099e90b86638b89vboxsync 92, 92, 92, 92, 92, 92, 92
a180a41bba1d50822df23fff0099e90b86638b89vboxsync};
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/* Output a uint32 into a buffer (little-endian) */
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncvoid
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncbuf_out_uint32(uint8 * buffer, uint32 value)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync buffer[0] = (value) & 0xff;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync buffer[1] = (value >> 8) & 0xff;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync buffer[2] = (value >> 16) & 0xff;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync buffer[3] = (value >> 24) & 0xff;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/* Generate a MAC hash (5.2.3.1), using a combination of SHA1 and MD5 */
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncvoid
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncsec_sign(uint8 * signature, int siglen, uint8 * session_key, int keylen, uint8 * data, int datalen)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint8 shasig[20];
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint8 md5sig[16];
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint8 lenhdr[4];
a180a41bba1d50822df23fff0099e90b86638b89vboxsync RDSSL_SHA1 sha1;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync RDSSL_MD5 md5;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync buf_out_uint32(lenhdr, datalen);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_sha1_init(&sha1);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_sha1_update(&sha1, session_key, keylen);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_sha1_update(&sha1, pad_54, 40);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_sha1_update(&sha1, lenhdr, 4);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_sha1_update(&sha1, data, datalen);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_sha1_final(&sha1, shasig);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_md5_init(&md5);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_md5_update(&md5, session_key, keylen);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_md5_update(&md5, pad_92, 48);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_md5_update(&md5, shasig, 20);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_md5_final(&md5, md5sig);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync memcpy(signature, md5sig, siglen);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/* Update an encryption key */
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic void
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncsec_update(uint8 * key, uint8 * update_key)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint8 shasig[20];
a180a41bba1d50822df23fff0099e90b86638b89vboxsync RDSSL_SHA1 sha1;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync RDSSL_MD5 md5;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync RDSSL_RC4 update;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_sha1_init(&sha1);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_sha1_update(&sha1, update_key, g_rc4_key_len);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_sha1_update(&sha1, pad_54, 40);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_sha1_update(&sha1, key, g_rc4_key_len);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_sha1_final(&sha1, shasig);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_md5_init(&md5);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_md5_update(&md5, update_key, g_rc4_key_len);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_md5_update(&md5, pad_92, 48);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_md5_update(&md5, shasig, 20);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_md5_final(&md5, key);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_rc4_set_key(&update, key, g_rc4_key_len);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_rc4_crypt(&update, key, key, g_rc4_key_len);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (g_rc4_key_len == 8)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync sec_make_40bit(key);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/* Encrypt data using RC4 */
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic void
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncsec_encrypt(uint8 * data, int length)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (g_sec_encrypt_use_count == 4096)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync sec_update(g_sec_encrypt_key, g_sec_encrypt_update_key);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_rc4_set_key(&g_rc4_encrypt_key, g_sec_encrypt_key, g_rc4_key_len);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync g_sec_encrypt_use_count = 0;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_rc4_crypt(&g_rc4_encrypt_key, data, data, length);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync g_sec_encrypt_use_count++;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/* Decrypt data using RC4 */
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncvoid
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncsec_decrypt(uint8 * data, int length)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (g_sec_decrypt_use_count == 4096)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync sec_update(g_sec_decrypt_key, g_sec_decrypt_update_key);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_rc4_set_key(&g_rc4_decrypt_key, g_sec_decrypt_key, g_rc4_key_len);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync g_sec_decrypt_use_count = 0;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_rc4_crypt(&g_rc4_decrypt_key, data, data, length);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync g_sec_decrypt_use_count++;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/* Perform an RSA public key encryption operation */
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic void
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncsec_rsa_encrypt(uint8 * out, uint8 * in, int len, uint32 modulus_size, uint8 * modulus,
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint8 * exponent)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_rsa_encrypt(out, in, len, modulus_size, modulus, exponent);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/* Initialise secure transport packet */
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncSTREAM
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncsec_init(uint32 flags, int maxlen)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync int hdrlen;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync STREAM s;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (!g_licence_issued && !g_licence_error_result)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync hdrlen = (flags & SEC_ENCRYPT) ? 12 : 4;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync else
a180a41bba1d50822df23fff0099e90b86638b89vboxsync hdrlen = (flags & SEC_ENCRYPT) ? 12 : 0;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync s = mcs_init(maxlen + hdrlen);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync s_push_layer(s, sec_hdr, hdrlen);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync return s;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/* Transmit secure transport packet over specified channel */
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncvoid
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncsec_send_to_channel(STREAM s, uint32 flags, uint16 channel)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync int datalen;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync#ifdef WITH_SCARD
a180a41bba1d50822df23fff0099e90b86638b89vboxsync scard_lock(SCARD_LOCK_SEC);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync#endif
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync s_pop_layer(s, sec_hdr);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if ((!g_licence_issued && !g_licence_error_result) || (flags & SEC_ENCRYPT))
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint32_le(s, flags);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (flags & SEC_ENCRYPT)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync flags &= ~SEC_ENCRYPT;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync datalen = s->end - s->p - 8;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync#if WITH_DEBUG
a180a41bba1d50822df23fff0099e90b86638b89vboxsync DEBUG(("Sending encrypted packet:\n"));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync hexdump(s->p + 8, datalen);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync#endif
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync sec_sign(s->p, 8, g_sec_sign_key, g_rc4_key_len, s->p + 8, datalen);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync sec_encrypt(s->p + 8, datalen);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync mcs_send_to_channel(s, channel);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync#ifdef WITH_SCARD
a180a41bba1d50822df23fff0099e90b86638b89vboxsync scard_unlock(SCARD_LOCK_SEC);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync#endif
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/* Transmit secure transport packet */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncvoid
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncsec_send(STREAM s, uint32 flags)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync sec_send_to_channel(s, flags, MCS_GLOBAL_CHANNEL);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/* Transfer the client random to the server */
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic void
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncsec_establish_key(void)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint32 length = g_server_public_key_len + SEC_PADDING_SIZE;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint32 flags = SEC_CLIENT_RANDOM;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync STREAM s;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync s = sec_init(flags, length + 4);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint32_le(s, length);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint8p(s, g_sec_crypted_random, g_server_public_key_len);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint8s(s, SEC_PADDING_SIZE);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync s_mark_end(s);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync sec_send(s, flags);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/* Output connect initial data blob */
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic void
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncsec_out_mcs_data(STREAM s, uint32 selected_protocol)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync int hostlen = 2 * strlen(g_hostname);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync int length = 162 + 76 + 12 + 4;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync unsigned int i;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (g_num_channels > 0)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync length += g_num_channels * 12 + 8;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (hostlen > 30)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync hostlen = 30;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* Generic Conference Control (T.124) ConferenceCreateRequest */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint16_be(s, 5);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint16_be(s, 0x14);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint8(s, 0x7c);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint16_be(s, 1);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint16_be(s, (length | 0x8000)); /* remaining length */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint16_be(s, 8); /* length? */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint16_be(s, 16);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint8(s, 0);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint16_le(s, 0xc001);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint8(s, 0);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint32_le(s, 0x61637544); /* OEM ID: "Duca", as in Ducati. */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint16_be(s, ((length - 14) | 0x8000)); /* remaining length */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* Client information */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint16_le(s, SEC_TAG_CLI_INFO);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint16_le(s, 216); /* length */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint16_le(s, (g_rdp_version >= RDP_V5) ? 4 : 1); /* RDP version. 1 == RDP4, 4 >= RDP5 to RDP8 */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint16_le(s, 8);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint16_le(s, g_width);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint16_le(s, g_height);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint16_le(s, 0xca01);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint16_le(s, 0xaa03);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint32_le(s, g_keylayout);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint32_le(s, 2600); /* Client build. We are now 2600 compatible :-) */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* Unicode name of client, padded to 32 bytes */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdp_out_unistr(s, g_hostname, hostlen);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint8s(s, 30 - hostlen);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* See
a180a41bba1d50822df23fff0099e90b86638b89vboxsync http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wceddk40/html/cxtsksupportingremotedesktopprotocol.asp */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint32_le(s, g_keyboard_type);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint32_le(s, g_keyboard_subtype);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint32_le(s, g_keyboard_functionkeys);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint8s(s, 64); /* reserved? 4 + 12 doublewords */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint16_le(s, 0xca01); /* colour depth? */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint16_le(s, 1);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint32(s, 0);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint8(s, g_server_depth);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint16_le(s, 0x0700);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint8(s, 0);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint32_le(s, 1);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint8s(s, 64);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint32_le(s, selected_protocol); /* End of client info */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* Write a Client Cluster Data (TS_UD_CS_CLUSTER) */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint32 cluster_flags = 0;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint16_le(s, SEC_TAG_CLI_CLUSTER); /* header.type */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint16_le(s, 12); /* length */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync cluster_flags |= SEC_CC_REDIRECTION_SUPPORTED;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync cluster_flags |= (SEC_CC_REDIRECT_VERSION_3 << 2);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (g_console_session || g_redirect_session_id != 0)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync cluster_flags |= SEC_CC_REDIRECT_SESSIONID_FIELD_VALID;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint32_le(s, cluster_flags);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint32(s, g_redirect_session_id);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* Client encryption settings */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint16_le(s, SEC_TAG_CLI_CRYPT);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint16_le(s, 12); /* length */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint32_le(s, g_encryption ? 0x3 : 0); /* encryption supported, 128-bit supported */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint32(s, 0); /* Unknown */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync DEBUG_RDP5(("g_num_channels is %d\n", g_num_channels));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (g_num_channels > 0)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint16_le(s, SEC_TAG_CLI_CHANNELS);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint16_le(s, g_num_channels * 12 + 8); /* length */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint32_le(s, g_num_channels); /* number of virtual channels */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync for (i = 0; i < g_num_channels; i++)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync DEBUG_RDP5(("Requesting channel %s\n", g_channels[i].name));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint8a(s, g_channels[i].name, 8);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint32_be(s, g_channels[i].flags);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync s_mark_end(s);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/* Parse a public key structure */
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic RD_BOOL
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncsec_parse_public_key(STREAM s, uint8 * modulus, uint8 * exponent)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint32 magic, modulus_len;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint32_le(s, magic);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (magic != SEC_RSA_MAGIC)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync error("RSA magic 0x%x\n", magic);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync return False;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint32_le(s, modulus_len);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync modulus_len -= SEC_PADDING_SIZE;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if ((modulus_len < SEC_MODULUS_SIZE) || (modulus_len > SEC_MAX_MODULUS_SIZE))
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync error("Bad server public key size (%u bits)\n", modulus_len * 8);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync return False;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint8s(s, 8); /* modulus_bits, unknown */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint8a(s, exponent, SEC_EXPONENT_SIZE);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint8a(s, modulus, modulus_len);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint8s(s, SEC_PADDING_SIZE);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync g_server_public_key_len = modulus_len;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync return s_check(s);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/* Parse a public signature structure */
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic RD_BOOL
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncsec_parse_public_sig(STREAM s, uint32 len, uint8 * modulus, uint8 * exponent)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint8 signature[SEC_MAX_MODULUS_SIZE];
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint32 sig_len;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (len != 72)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync return True;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync memset(signature, 0, sizeof(signature));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync sig_len = len - 8;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint8a(s, signature, sig_len);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync return rdssl_sig_ok(exponent, SEC_EXPONENT_SIZE, modulus, g_server_public_key_len,
a180a41bba1d50822df23fff0099e90b86638b89vboxsync signature, sig_len);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/* Parse a crypto information structure */
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic RD_BOOL
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncsec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint8 ** server_random, uint8 * modulus, uint8 * exponent)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint32 crypt_level, random_len, rsa_info_len;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint32 cacert_len, cert_len, flags;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync RDSSL_CERT *cacert, *server_cert;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync RDSSL_RKEY *server_public_key;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint16 tag, length;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint8 *next_tag, *end;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint32_le(s, *rc4_key_size); /* 1 = 40-bit, 2 = 128-bit */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint32_le(s, crypt_level); /* 1 = low, 2 = medium, 3 = high */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (crypt_level == 0)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* no encryption */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync return False;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint32_le(s, random_len);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint32_le(s, rsa_info_len);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (random_len != SEC_RANDOM_SIZE)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync error("random len %d, expected %d\n", random_len, SEC_RANDOM_SIZE);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync return False;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint8p(s, *server_random, random_len);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* RSA info */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync end = s->p + rsa_info_len;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (end > s->end)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync return False;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint32_le(s, flags); /* 1 = RDP4-style, 0x80000002 = X.509 */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (flags & 1)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync DEBUG_RDP5(("We're going for the RDP4-style encryption\n"));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint8s(s, 8); /* unknown */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync while (s->p < end)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint16_le(s, tag);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint16_le(s, length);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync next_tag = s->p + length;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync switch (tag)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync case SEC_TAG_PUBKEY:
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (!sec_parse_public_key(s, modulus, exponent))
a180a41bba1d50822df23fff0099e90b86638b89vboxsync return False;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync DEBUG_RDP5(("Got Public key, RDP4-style\n"));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync break;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync case SEC_TAG_KEYSIG:
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (!sec_parse_public_sig(s, length, modulus, exponent))
a180a41bba1d50822df23fff0099e90b86638b89vboxsync return False;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync break;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync default:
a180a41bba1d50822df23fff0099e90b86638b89vboxsync unimpl("crypt tag 0x%x\n", tag);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync s->p = next_tag;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync else
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint32 certcount;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync DEBUG_RDP5(("We're going for the RDP5-style encryption\n"));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint32_le(s, certcount); /* Number of certificates */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (certcount < 2)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync error("Server didn't send enough X509 certificates\n");
a180a41bba1d50822df23fff0099e90b86638b89vboxsync return False;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync for (; certcount > 2; certcount--)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync { /* ignore all the certificates between the root and the signing CA */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint32 ignorelen;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync RDSSL_CERT *ignorecert;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync DEBUG_RDP5(("Ignored certs left: %d\n", certcount));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint32_le(s, ignorelen);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync DEBUG_RDP5(("Ignored Certificate length is %d\n", ignorelen));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync ignorecert = rdssl_cert_read(s->p, ignorelen);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint8s(s, ignorelen);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (ignorecert == NULL)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync { /* XXX: error out? */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync DEBUG_RDP5(("got a bad cert: this will probably screw up the rest of the communication\n"));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync#ifdef WITH_DEBUG_RDP5
a180a41bba1d50822df23fff0099e90b86638b89vboxsync DEBUG_RDP5(("cert #%d (ignored):\n", certcount));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_cert_print_fp(stdout, ignorecert);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync#endif
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* Do da funky X.509 stuffy
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync "How did I find out about this? I looked up and saw a
a180a41bba1d50822df23fff0099e90b86638b89vboxsync bright light and when I came to I had a scar on my forehead
a180a41bba1d50822df23fff0099e90b86638b89vboxsync and knew about X.500"
a180a41bba1d50822df23fff0099e90b86638b89vboxsync - Peter Gutman in a early version of
a180a41bba1d50822df23fff0099e90b86638b89vboxsync http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
a180a41bba1d50822df23fff0099e90b86638b89vboxsync */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint32_le(s, cacert_len);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync DEBUG_RDP5(("CA Certificate length is %d\n", cacert_len));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync cacert = rdssl_cert_read(s->p, cacert_len);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint8s(s, cacert_len);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (NULL == cacert)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync error("Couldn't load CA Certificate from server\n");
a180a41bba1d50822df23fff0099e90b86638b89vboxsync return False;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint32_le(s, cert_len);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync DEBUG_RDP5(("Certificate length is %d\n", cert_len));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync server_cert = rdssl_cert_read(s->p, cert_len);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint8s(s, cert_len);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (NULL == server_cert)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_cert_free(cacert);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync error("Couldn't load Certificate from server\n");
a180a41bba1d50822df23fff0099e90b86638b89vboxsync return False;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (!rdssl_certs_ok(server_cert, cacert))
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_cert_free(server_cert);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_cert_free(cacert);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync error("Security error CA Certificate invalid\n");
a180a41bba1d50822df23fff0099e90b86638b89vboxsync return False;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_cert_free(cacert);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint8s(s, 16); /* Padding */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync server_public_key = rdssl_cert_to_rkey(server_cert, &g_server_public_key_len);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (NULL == server_public_key)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync DEBUG_RDP5(("Didn't parse X509 correctly\n"));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_cert_free(server_cert);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync return False;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_cert_free(server_cert);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if ((g_server_public_key_len < SEC_MODULUS_SIZE) ||
a180a41bba1d50822df23fff0099e90b86638b89vboxsync (g_server_public_key_len > SEC_MAX_MODULUS_SIZE))
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync error("Bad server public key size (%u bits)\n",
a180a41bba1d50822df23fff0099e90b86638b89vboxsync g_server_public_key_len * 8);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_rkey_free(server_public_key);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync return False;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (rdssl_rkey_get_exp_mod(server_public_key, exponent, SEC_EXPONENT_SIZE,
a180a41bba1d50822df23fff0099e90b86638b89vboxsync modulus, SEC_MAX_MODULUS_SIZE) != 0)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync error("Problem extracting RSA exponent, modulus");
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_rkey_free(server_public_key);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync return False;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_rkey_free(server_public_key);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync return True; /* There's some garbage here we don't care about */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync return s_check_end(s);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/* Process crypto information blob */
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic void
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncsec_process_crypt_info(STREAM s)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint8 *server_random = NULL;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint8 modulus[SEC_MAX_MODULUS_SIZE];
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint8 exponent[SEC_EXPONENT_SIZE];
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint32 rc4_key_size;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync memset(modulus, 0, sizeof(modulus));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync memset(exponent, 0, sizeof(exponent));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random, modulus, exponent))
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync DEBUG(("Failed to parse crypt info\n"));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync return;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync DEBUG(("Generating client random\n"));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync generate_random(g_client_random);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync sec_rsa_encrypt(g_sec_crypted_random, g_client_random, SEC_RANDOM_SIZE,
a180a41bba1d50822df23fff0099e90b86638b89vboxsync g_server_public_key_len, modulus, exponent);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync sec_generate_keys(g_client_random, server_random, rc4_key_size);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/* Process SRV_INFO, find RDP version supported by server */
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic void
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncsec_process_srv_info(STREAM s)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint16_le(s, g_server_rdp_version);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync DEBUG_RDP5(("Server RDP version is %d\n", g_server_rdp_version));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (1 == g_server_rdp_version)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync g_rdp_version = RDP_V4;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync g_server_depth = 8;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/* Process connect response data blob */
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncvoid
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncsec_process_mcs_data(STREAM s)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint16 tag, length;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint8 *next_tag;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint8 len;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint8s(s, 21); /* header (T.124 ConferenceCreateResponse) */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint8(s, len);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (len & 0x80)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint8(s, len);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync while (s->p < s->end)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint16_le(s, tag);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint16_le(s, length);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (length <= 4)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync return;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync next_tag = s->p + length - 4;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync switch (tag)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync case SEC_TAG_SRV_INFO:
a180a41bba1d50822df23fff0099e90b86638b89vboxsync sec_process_srv_info(s);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync break;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync case SEC_TAG_SRV_CRYPT:
a180a41bba1d50822df23fff0099e90b86638b89vboxsync sec_process_crypt_info(s);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync break;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync case SEC_TAG_SRV_CHANNELS:
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* FIXME: We should parse this information and
a180a41bba1d50822df23fff0099e90b86638b89vboxsync use it to map RDP5 channels to MCS
a180a41bba1d50822df23fff0099e90b86638b89vboxsync channels */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync break;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync default:
a180a41bba1d50822df23fff0099e90b86638b89vboxsync unimpl("response tag 0x%x\n", tag);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync s->p = next_tag;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/* Receive secure transport packet */
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncSTREAM
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncsec_recv(uint8 * rdpver)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint32 sec_flags;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint16 channel;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync STREAM s;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync while ((s = mcs_recv(&channel, rdpver)) != NULL)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (rdpver != NULL)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (*rdpver != 3)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (*rdpver & 0x80)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint8s(s, 8); /* signature */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync sec_decrypt(s->p, s->end - s->p);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync return s;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (g_encryption || (!g_licence_issued && !g_licence_error_result))
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint32_le(s, sec_flags);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (g_encryption)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (sec_flags & SEC_ENCRYPT)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint8s(s, 8); /* signature */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync sec_decrypt(s->p, s->end - s->p);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (sec_flags & SEC_LICENCE_NEG)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync licence_process(s);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync continue;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (sec_flags & 0x0400) /* SEC_REDIRECT_ENCRYPT */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint8 swapbyte;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint8s(s, 8); /* signature */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync sec_decrypt(s->p, s->end - s->p);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* Check for a redirect packet, starts with 00 04 */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (s->p[0] == 0 && s->p[1] == 4)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* for some reason the PDU and the length seem to be swapped.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync This isn't good, but we're going to do a byte for byte
a180a41bba1d50822df23fff0099e90b86638b89vboxsync swap. So the first foure value appear as: 00 04 XX YY,
a180a41bba1d50822df23fff0099e90b86638b89vboxsync where XX YY is the little endian length. We're going to
a180a41bba1d50822df23fff0099e90b86638b89vboxsync use 04 00 as the PDU type, so after our swap this will look
a180a41bba1d50822df23fff0099e90b86638b89vboxsync like: XX YY 04 00 */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync swapbyte = s->p[0];
a180a41bba1d50822df23fff0099e90b86638b89vboxsync s->p[0] = s->p[2];
a180a41bba1d50822df23fff0099e90b86638b89vboxsync s->p[2] = swapbyte;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync swapbyte = s->p[1];
a180a41bba1d50822df23fff0099e90b86638b89vboxsync s->p[1] = s->p[3];
a180a41bba1d50822df23fff0099e90b86638b89vboxsync s->p[3] = swapbyte;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync swapbyte = s->p[2];
a180a41bba1d50822df23fff0099e90b86638b89vboxsync s->p[2] = s->p[3];
a180a41bba1d50822df23fff0099e90b86638b89vboxsync s->p[3] = swapbyte;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync#ifdef WITH_DEBUG
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* warning! this debug statement will show passwords in the clear! */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync hexdump(s->p, s->end - s->p);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync#endif
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync else
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if ((sec_flags & 0xffff) == SEC_LICENCE_NEG)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync licence_process(s);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync continue;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync s->p -= 4;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (channel != MCS_GLOBAL_CHANNEL)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync channel_process(s, channel);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (rdpver != NULL)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync *rdpver = 0xff;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync return s;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync return s;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync return NULL;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/* Establish a secure connection */
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncRD_BOOL
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncsec_connect(char *server, char *username, char *domain, char *password, RD_BOOL reconnect)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint32 selected_proto;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync struct stream mcs_data;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* Start a MCS connect sequence */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (!mcs_connect_start(server, username, domain, password, reconnect, &selected_proto))
a180a41bba1d50822df23fff0099e90b86638b89vboxsync return False;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* We exchange some RDP data during the MCS-Connect */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync mcs_data.size = 512;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync sec_out_mcs_data(&mcs_data, selected_proto);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* finialize the MCS connect sequence */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (!mcs_connect_finalize(&mcs_data))
a180a41bba1d50822df23fff0099e90b86638b89vboxsync return False;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* sec_process_mcs_data(&mcs_data); */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (g_encryption)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync sec_establish_key();
a180a41bba1d50822df23fff0099e90b86638b89vboxsync xfree(mcs_data.data);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync return True;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/* Disconnect a connection */
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncvoid
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncsec_disconnect(void)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync mcs_disconnect();
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/* reset the state of the sec layer */
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncvoid
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncsec_reset_state(void)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync g_server_rdp_version = 0;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync g_sec_encrypt_use_count = 0;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync g_sec_decrypt_use_count = 0;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync g_licence_issued = 0;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync g_licence_error_result = 0;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync mcs_reset_state();
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}