ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

licence.c
Go to the documentation of this file.
00001 /* -*- c-basic-offset: 8 -*-
00002    rdesktop: A Remote Desktop Protocol client.
00003    RDP licensing negotiation
00004    Copyright (C) Matthew Chapman 1999-2005
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010 
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015 
00016    You should have received a copy of the GNU General Public License along
00017    with this program; if not, write to the Free Software Foundation, Inc.,
00018    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00019 */
00020 
00021 #include <precomp.h>
00022 //#include <openssl/rc4.h>
00023 
00024 void *
00025 ssl_rc4_info_create(void);
00026 void
00027 ssl_rc4_info_delete(void * rc4_info);
00028 void
00029 ssl_rc4_set_key(void * rc4_info, char * key, int len);
00030 void
00031 ssl_rc4_crypt(void * rc4_info, char * in_data, char * out_data, int len);
00032 int
00033 ssl_mod_exp(char* out, int out_len, char* in, int in_len,
00034             char* mod, int mod_len, char* exp, int exp_len);
00035 
00036 extern char g_username[];
00037 extern char g_hostname[];
00038 
00039 static uint8 g_licence_key[16];
00040 static uint8 g_licence_sign_key[16];
00041 
00042 BOOL g_licence_issued = False;
00043 
00044 /* Generate a session key and RC4 keys, given client and server randoms */
00045 static void
00046 licence_generate_keys(uint8 * client_random, uint8 * server_random, uint8 * pre_master_secret)
00047 {
00048     uint8 master_secret[48];
00049     uint8 key_block[48];
00050 
00051     /* Generate master secret and then key material */
00052     sec_hash_48(master_secret, pre_master_secret, client_random, server_random, 'A');
00053     sec_hash_48(key_block, master_secret, server_random, client_random, 'A');
00054 
00055     /* Store first 16 bytes of session key as MAC secret */
00056     memcpy(g_licence_sign_key, key_block, 16);
00057 
00058     /* Generate RC4 key from next 16 bytes */
00059     sec_hash_16(g_licence_key, &key_block[16], client_random, server_random);
00060 }
00061 
00062 static void
00063 licence_generate_hwid(uint8 * hwid)
00064 {
00065     buf_out_uint32(hwid, 2);
00066     strncpy((char *) (hwid + 4), g_hostname, LICENCE_HWID_SIZE - 4);
00067 }
00068 
00069 /* Present an existing licence to the server */
00070 static void
00071 licence_present(uint8 * client_random, uint8 * rsa_data,
00072         uint8 * licence_data, int licence_size, uint8 * hwid, uint8 * signature)
00073 {
00074     uint32 sec_flags = SEC_LICENCE_NEG;
00075     uint16 length =
00076         16 + SEC_RANDOM_SIZE + SEC_MODULUS_SIZE + SEC_PADDING_SIZE +
00077         licence_size + LICENCE_HWID_SIZE + LICENCE_SIGNATURE_SIZE;
00078     STREAM s;
00079 
00080     s = sec_init(sec_flags, length + 4);
00081 
00082     out_uint8(s, LICENCE_TAG_PRESENT);
00083     out_uint8(s, 2);    /* version */
00084     out_uint16_le(s, length);
00085 
00086     out_uint32_le(s, 1);
00087     out_uint16(s, 0);
00088     out_uint16_le(s, 0x0201);
00089 
00090     out_uint8p(s, client_random, SEC_RANDOM_SIZE);
00091     out_uint16(s, 0);
00092     out_uint16_le(s, (SEC_MODULUS_SIZE + SEC_PADDING_SIZE));
00093     out_uint8p(s, rsa_data, SEC_MODULUS_SIZE);
00094     out_uint8s(s, SEC_PADDING_SIZE);
00095 
00096     out_uint16_le(s, 1);
00097     out_uint16_le(s, licence_size);
00098     out_uint8p(s, licence_data, licence_size);
00099 
00100     out_uint16_le(s, 1);
00101     out_uint16_le(s, LICENCE_HWID_SIZE);
00102     out_uint8p(s, hwid, LICENCE_HWID_SIZE);
00103 
00104     out_uint8p(s, signature, LICENCE_SIGNATURE_SIZE);
00105 
00106     s_mark_end(s);
00107     sec_send(s, sec_flags);
00108 }
00109 
00110 /* Send a licence request packet */
00111 static void
00112 licence_send_request(uint8 * client_random, uint8 * rsa_data, char *user, char *host)
00113 {
00114     uint32 sec_flags = SEC_LICENCE_NEG;
00115     uint16 userlen = strlen(user) + 1;
00116     uint16 hostlen = strlen(host) + 1;
00117     uint16 length = 128 + userlen + hostlen;
00118     STREAM s;
00119 
00120     s = sec_init(sec_flags, length + 2);
00121 
00122     out_uint8(s, LICENCE_TAG_REQUEST);
00123     out_uint8(s, 2);    /* version */
00124     out_uint16_le(s, length);
00125 
00126     out_uint32_le(s, 1);
00127     out_uint16(s, 0);
00128     out_uint16_le(s, 0xff01);
00129 
00130     out_uint8p(s, client_random, SEC_RANDOM_SIZE);
00131     out_uint16(s, 0);
00132     out_uint16_le(s, (SEC_MODULUS_SIZE + SEC_PADDING_SIZE));
00133     out_uint8p(s, rsa_data, SEC_MODULUS_SIZE);
00134     out_uint8s(s, SEC_PADDING_SIZE);
00135 
00136     out_uint16_le(s, LICENCE_TAG_USER);
00137     out_uint16_le(s, userlen);
00138     out_uint8p(s, user, userlen);
00139 
00140     out_uint16_le(s, LICENCE_TAG_HOST);
00141     out_uint16_le(s, hostlen);
00142     out_uint8p(s, host, hostlen);
00143 
00144     s_mark_end(s);
00145     sec_send(s, sec_flags);
00146 }
00147 
00148 /* Process a licence demand packet */
00149 static void
00150 licence_process_demand(STREAM s)
00151 {
00152     uint8 null_data[SEC_MODULUS_SIZE];
00153     uint8 *server_random;
00154     uint8 signature[LICENCE_SIGNATURE_SIZE];
00155     uint8 hwid[LICENCE_HWID_SIZE];
00156     uint8 *licence_data;
00157     int licence_size;
00158     void * crypt_key;
00159 
00160     /* Retrieve the server random from the incoming packet */
00161     in_uint8p(s, server_random, SEC_RANDOM_SIZE);
00162 
00163     /* We currently use null client keys. This is a bit naughty but, hey,
00164        the security of licence negotiation isn't exactly paramount. */
00165     memset(null_data, 0, sizeof(null_data));
00166     licence_generate_keys(null_data, server_random, null_data);
00167 
00168     licence_size = load_licence(&licence_data);
00169     if (licence_size > 0)
00170     {
00171         /* Generate a signature for the HWID buffer */
00172         licence_generate_hwid(hwid);
00173         sec_sign(signature, 16, g_licence_sign_key, 16, hwid, sizeof(hwid));
00174 
00175         /* Now encrypt the HWID */
00176         crypt_key = ssl_rc4_info_create();
00177         ssl_rc4_set_key(crypt_key, (char *)g_licence_key, 16);
00178         ssl_rc4_crypt(crypt_key, (char *)hwid, (char *)hwid, sizeof(hwid));
00179         ssl_rc4_info_delete(crypt_key);
00180 
00181         licence_present(null_data, null_data, licence_data, licence_size, hwid, signature);
00182         xfree(licence_data);
00183         return;
00184     }
00185 
00186     licence_send_request(null_data, null_data, g_username, g_hostname);
00187 }
00188 
00189 /* Send an authentication response packet */
00190 static void
00191 licence_send_authresp(uint8 * token, uint8 * crypt_hwid, uint8 * signature)
00192 {
00193     uint32 sec_flags = SEC_LICENCE_NEG;
00194     uint16 length = 58;
00195     STREAM s;
00196 
00197     s = sec_init(sec_flags, length + 2);
00198 
00199     out_uint8(s, LICENCE_TAG_AUTHRESP);
00200     out_uint8(s, 2);    /* version */
00201     out_uint16_le(s, length);
00202 
00203     out_uint16_le(s, 1);
00204     out_uint16_le(s, LICENCE_TOKEN_SIZE);
00205     out_uint8p(s, token, LICENCE_TOKEN_SIZE);
00206 
00207     out_uint16_le(s, 1);
00208     out_uint16_le(s, LICENCE_HWID_SIZE);
00209     out_uint8p(s, crypt_hwid, LICENCE_HWID_SIZE);
00210 
00211     out_uint8p(s, signature, LICENCE_SIGNATURE_SIZE);
00212 
00213     s_mark_end(s);
00214     sec_send(s, sec_flags);
00215 }
00216 
00217 /* Parse an authentication request packet */
00218 static BOOL
00219 licence_parse_authreq(STREAM s, uint8 ** token, uint8 ** signature)
00220 {
00221     uint16 tokenlen;
00222 
00223     in_uint8s(s, 6);    /* unknown: f8 3d 15 00 04 f6 */
00224 
00225     in_uint16_le(s, tokenlen);
00226     if (tokenlen != LICENCE_TOKEN_SIZE)
00227     {
00228         error("token len %d\n", tokenlen);
00229         return False;
00230     }
00231 
00232     in_uint8p(s, *token, tokenlen);
00233     in_uint8p(s, *signature, LICENCE_SIGNATURE_SIZE);
00234 
00235     return s_check_end(s);
00236 }
00237 
00238 /* Process an authentication request packet */
00239 static void
00240 licence_process_authreq(STREAM s)
00241 {
00242     uint8 *in_token = NULL, *in_sig;
00243     uint8 out_token[LICENCE_TOKEN_SIZE], decrypt_token[LICENCE_TOKEN_SIZE];
00244     uint8 hwid[LICENCE_HWID_SIZE], crypt_hwid[LICENCE_HWID_SIZE];
00245     uint8 sealed_buffer[LICENCE_TOKEN_SIZE + LICENCE_HWID_SIZE];
00246     uint8 out_sig[LICENCE_SIGNATURE_SIZE];
00247     void * crypt_key;
00248 
00249     /* Parse incoming packet and save the encrypted token */
00250     licence_parse_authreq(s, &in_token, &in_sig);
00251     memcpy(out_token, in_token, LICENCE_TOKEN_SIZE);
00252 
00253     /* Decrypt the token. It should read TEST in Unicode. */
00254     crypt_key = ssl_rc4_info_create();
00255     ssl_rc4_set_key(crypt_key, (char *)g_licence_key, 16);
00256     ssl_rc4_crypt(crypt_key, (char *)in_token, (char *)decrypt_token, LICENCE_TOKEN_SIZE);
00257     ssl_rc4_info_delete(crypt_key);
00258     
00259     /* Generate a signature for a buffer of token and HWID */
00260     licence_generate_hwid(hwid);
00261     memcpy(sealed_buffer, decrypt_token, LICENCE_TOKEN_SIZE);
00262     memcpy(sealed_buffer + LICENCE_TOKEN_SIZE, hwid, LICENCE_HWID_SIZE);
00263     sec_sign(out_sig, 16, g_licence_sign_key, 16, sealed_buffer, sizeof(sealed_buffer));
00264 
00265     /* Now encrypt the HWID */
00266     crypt_key = ssl_rc4_info_create();
00267     ssl_rc4_set_key(crypt_key, (char *)g_licence_key, 16);
00268     ssl_rc4_crypt(crypt_key, (char *)hwid, (char *)crypt_hwid, LICENCE_HWID_SIZE);
00269     ssl_rc4_info_delete(crypt_key);
00270 
00271     licence_send_authresp(out_token, crypt_hwid, out_sig);
00272 }
00273 
00274 /* Process an licence issue packet */
00275 static void
00276 licence_process_issue(STREAM s)
00277 {
00278     void * crypt_key;
00279     uint32 length;
00280     uint16 check;
00281     int i;
00282 
00283     in_uint8s(s, 2);    /* 3d 45 - unknown */
00284     in_uint16_le(s, length);
00285     if (!s_check_rem(s, length))
00286         return;
00287 
00288     crypt_key = ssl_rc4_info_create();
00289     ssl_rc4_set_key(crypt_key, (char *)g_licence_key, 16);
00290     ssl_rc4_crypt(crypt_key, (char *)s->p, (char *)s->p, length);
00291     ssl_rc4_info_delete(crypt_key);
00292 
00293     in_uint16(s, check);
00294     if (check != 0)
00295         return;
00296 
00297     g_licence_issued = True;
00298 
00299     in_uint8s(s, 2);    /* pad */
00300 
00301     /* advance to fourth string */
00302     length = 0;
00303     for (i = 0; i < 4; i++)
00304     {
00305         in_uint8s(s, length);
00306         in_uint32_le(s, length);
00307         if (!s_check_rem(s, length))
00308             return;
00309     }
00310 
00311     g_licence_issued = True;
00312     save_licence(s->p, length);
00313 }
00314 
00315 /* Process a licence packet */
00316 void
00317 licence_process(STREAM s)
00318 {
00319     uint8 tag;
00320 
00321     in_uint8(s, tag);
00322     in_uint8s(s, 3);    /* version, length */
00323 
00324     switch (tag)
00325     {
00326         case LICENCE_TAG_DEMAND:
00327             licence_process_demand(s);
00328             break;
00329 
00330         case LICENCE_TAG_AUTHREQ:
00331             licence_process_authreq(s);
00332             break;
00333 
00334         case LICENCE_TAG_ISSUE:
00335             licence_process_issue(s);
00336             break;
00337 
00338         case LICENCE_TAG_REISSUE:
00339         case LICENCE_TAG_RESULT:
00340             break;
00341 
00342         default:
00343             unimpl("licence tag 0x%x\n", tag);
00344     }
00345 }

Generated on Sun May 27 2012 04:17:10 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.