ReactOS 0.4.15-dev-7958-gcd0bb1a
licence.c
Go to the documentation of this file.
1/* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 RDP licensing negotiation
4 Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
5 Copyright (C) Thomas Uhle <thomas.uhle@mailbox.tu-dresden.de> 2011
6 Copyright (C) Henrik Andersson <henrik.andersson@cendio.com> 2014
7
8
9 This program is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
21*/
22
23#include "precomp.h"
24
25void *
27void
28rdssl_rc4_info_delete(void * rc4_info);
29void
30rdssl_rc4_set_key(void * rc4_info, char * key, int len);
31void
32rdssl_rc4_crypt(void * rc4_info, char * in_data, char * out_data, int len);
33int
34rdssl_mod_exp(char* out, int out_len, char* in, int in_len,
35 char* mod, int mod_len, char* exp, int exp_len);
36
37extern char g_username[256];
38extern char g_hostname[256];
40
43
46
47/* Generate a session key and RC4 keys, given client and server randoms */
48static void
49licence_generate_keys(uint8 * client_random, uint8 * server_random, uint8 * pre_master_secret)
50{
51 uint8 master_secret[48];
52 uint8 key_block[48];
53
54 /* Generate master secret and then key material */
55 sec_hash_48(master_secret, pre_master_secret, client_random, server_random, 'A');
56 sec_hash_48(key_block, master_secret, server_random, client_random, 'A');
57
58 /* Store first 16 bytes of session key as MAC secret */
59 memcpy(g_licence_sign_key, key_block, 16);
60
61 /* Generate RC4 key from next 16 bytes */
62 sec_hash_16(g_licence_key, &key_block[16], client_random, server_random);
63}
64
65static void
67{
68 buf_out_uint32(hwid, 2);
69 strncpy((char *) (hwid + 4), g_hostname, LICENCE_HWID_SIZE - 4);
70}
71
72/* Send a lincece info packet to server */
73static void
74licence_info(uint8 * client_random, uint8 * rsa_data,
75 uint8 * licence_data, int licence_size, uint8 * hwid, uint8 * signature)
76{
77 uint32 sec_flags = SEC_LICENSE_PKT;
81 STREAM s;
82
83 s = sec_init(sec_flags, length + 2);
84
86 out_uint8(s, ((g_rdp_version >= RDP_V5) ? 3 : 2)); /* version */
88
89 out_uint32_le(s, 1);
90 out_uint16(s, 0);
91 out_uint16_le(s, 0x0201);
92
93 out_uint8p(s, client_random, SEC_RANDOM_SIZE);
94 out_uint16_le(s, 2);
96 out_uint8p(s, rsa_data, SEC_MODULUS_SIZE);
98
99 out_uint16_le(s, 1);
100 out_uint16_le(s, licence_size);
101 out_uint8p(s, licence_data, licence_size);
102
103 out_uint16_le(s, 1);
106
108
109 s_mark_end(s);
110 sec_send(s, sec_flags);
111}
112
113/* Send a new licence request packet */
114static void
115licence_send_new_licence_request(uint8 * client_random, uint8 * rsa_data, char *user, char *host)
116{
117 uint32 sec_flags = SEC_LICENSE_PKT;
118 uint16 userlen = strlen(user) + 1;
119 uint16 hostlen = strlen(host) + 1;
120 uint16 length =
121 24 + SEC_RANDOM_SIZE + SEC_MODULUS_SIZE + SEC_PADDING_SIZE + userlen + hostlen;
122 STREAM s;
123
124 s = sec_init(sec_flags, length + 2);
125
127 out_uint8(s, ((g_rdp_version >= RDP_V5) ? 3 : 2)); /* version */
129
130 out_uint32_le(s, 1); // KEY_EXCHANGE_ALG_RSA
131 out_uint16(s, 0);
132 out_uint16_le(s, 0xff01);
133
134 out_uint8p(s, client_random, SEC_RANDOM_SIZE);
135 out_uint16_le(s, 2);
137 out_uint8p(s, rsa_data, SEC_MODULUS_SIZE);
139
140 /* Username LICENSE_BINARY_BLOB */
142 out_uint16_le(s, userlen);
143 out_uint8p(s, user, userlen);
144
145 /* Machinename LICENSE_BINARY_BLOB */
147 out_uint16_le(s, hostlen);
148 out_uint8p(s, host, hostlen);
149
150 s_mark_end(s);
151 sec_send(s, sec_flags);
152}
153
154/* Process a licence request packet */
155static void
157{
158 uint8 null_data[SEC_MODULUS_SIZE];
159 uint8 *server_random;
160 uint8 signature[LICENCE_SIGNATURE_SIZE];
162 uint8 *licence_data;
163 int licence_size;
164 void * crypt_key;
165
166 /* Retrieve the server random from the incoming packet */
167 in_uint8p(s, server_random, SEC_RANDOM_SIZE);
168
169 /* We currently use null client keys. This is a bit naughty but, hey,
170 the security of licence negotiation isn't exactly paramount. */
171 memset(null_data, 0, sizeof(null_data));
172 licence_generate_keys(null_data, server_random, null_data);
173
174 licence_size = load_licence(&licence_data);
175 if (licence_size > 0)
176 {
177 /* Generate a signature for the HWID buffer */
179 sec_sign(signature, 16, g_licence_sign_key, 16, hwid, sizeof(hwid));
180
181 /* Now encrypt the HWID */
182 crypt_key = rdssl_rc4_info_create();
183 rdssl_rc4_set_key(crypt_key, (char *)g_licence_key, 16);
184 rdssl_rc4_crypt(crypt_key, (char *)hwid, (char *)hwid, sizeof(hwid));
185 rdssl_rc4_info_delete(crypt_key);
186
187#if WITH_DEBUG
188 DEBUG(("Sending licensing PDU (message type 0x%02x)\n", LICENCE_TAG_LICENCE_INFO));
189#endif
190 licence_info(null_data, null_data, licence_data, licence_size, hwid, signature);
191
192 xfree(licence_data);
193 return;
194 }
195
196#if WITH_DEBUG
197 DEBUG(("Sending licensing PDU (message type 0x%02x)\n", LICENCE_TAG_NEW_LICENCE_REQUEST));
198#endif
200}
201
202/* Send a platform challenge response packet */
203static void
205{
206 uint32 sec_flags = SEC_LICENSE_PKT;
207 uint16 length = 58;
208 STREAM s;
209
210 s = sec_init(sec_flags, length + 2);
211
213 out_uint8(s, ((g_rdp_version >= RDP_V5) ? 3 : 2)); /* version */
215
216 out_uint16_le(s, 1);
219
220 out_uint16_le(s, 1);
222 out_uint8p(s, crypt_hwid, LICENCE_HWID_SIZE);
223
225
226 s_mark_end(s);
227 sec_send(s, sec_flags);
228}
229
230/* Parse a platform challenge request packet */
231static RD_BOOL
233{
234 uint16 tokenlen;
235
236 in_uint8s(s, 6); /* unknown: f8 3d 15 00 04 f6 */
237
238 in_uint16_le(s, tokenlen);
239 if (tokenlen != LICENCE_TOKEN_SIZE)
240 {
241 error("token len %d\n", tokenlen);
242 return False;
243 }
244
245 in_uint8p(s, *token, tokenlen);
246 in_uint8p(s, *signature, LICENCE_SIGNATURE_SIZE);
247
248 return s_check_end(s);
249}
250
251/* Process a platform challenge packet */
252static void
254{
255 uint8 *in_token = NULL, *in_sig;
256 uint8 out_token[LICENCE_TOKEN_SIZE], decrypt_token[LICENCE_TOKEN_SIZE];
257 uint8 hwid[LICENCE_HWID_SIZE], crypt_hwid[LICENCE_HWID_SIZE];
260 void * crypt_key;
261
262 /* Parse incoming packet and save the encrypted token */
263 licence_parse_platform_challenge(s, &in_token, &in_sig);
264 memcpy(out_token, in_token, LICENCE_TOKEN_SIZE);
265
266 /* Decrypt the token. It should read TEST in Unicode. */
267 crypt_key = rdssl_rc4_info_create();
268 rdssl_rc4_set_key(crypt_key, (char *)g_licence_key, 16);
269 rdssl_rc4_crypt(crypt_key, (char *)in_token, (char *)decrypt_token, LICENCE_TOKEN_SIZE);
270 rdssl_rc4_info_delete(crypt_key);
271
272 /* Generate a signature for a buffer of token and HWID */
274 memcpy(sealed_buffer, decrypt_token, LICENCE_TOKEN_SIZE);
275 memcpy(sealed_buffer + LICENCE_TOKEN_SIZE, hwid, LICENCE_HWID_SIZE);
276 sec_sign(out_sig, 16, g_licence_sign_key, 16, sealed_buffer, sizeof(sealed_buffer));
277
278 /* Now encrypt the HWID */
279 crypt_key = rdssl_rc4_info_create();
280 rdssl_rc4_set_key(crypt_key, (char *)g_licence_key, 16);
281 rdssl_rc4_crypt(crypt_key, (char *)hwid, (char *)crypt_hwid, LICENCE_HWID_SIZE);
282
283 licence_send_platform_challenge_response(out_token, crypt_hwid, out_sig);
284}
285
286/* Process a new licence packet */
287static void
289{
290 void * crypt_key;
292 int i;
293
294 in_uint8s(s, 2); // Skip license binary blob type
296 if (!s_check_rem(s, length))
297 return;
298
299 crypt_key = rdssl_rc4_info_create();
300 rdssl_rc4_set_key(crypt_key, (char *)g_licence_key, 16);
301 rdssl_rc4_crypt(crypt_key, (char *)s->p, (char *)s->p, length);
302 rdssl_rc4_info_delete(crypt_key);
303
304 /* Parse NEW_LICENSE_INFO block */
305 in_uint8s(s, 4); // skip dwVersion
306
307 /* Skip strings, Scope, CompanyName and ProductId to get
308 to the LicenseInfo which we store in license blob. */
309 length = 0;
310 for (i = 0; i < 4; i++)
311 {
314 if (!s_check_rem(s, length))
315 return;
316 }
317
319 save_licence(s->p, length);
320}
321
322/* process a licence error alert packet */
323void
325{
327 uint32 state_transition;
328 uint32 error_info;
330 in_uint32(s, state_transition);
331 in_uint32(s, error_info);
332
333 /* There is a special case in the error alert handling, when licensing is all good
334 and the server is not sending a license to client, a "Server License Error PDU -
335 Valid Client" packet is sent which means, every thing is ok.
336
337 Therefor we should flag that everything is ok with license here.
338 */
339 if (error_code == 0x07)
340 {
342 return;
343 }
344
345 /* handle error codes, for now, just report them */
346 switch (error_code)
347 {
348 case 0x6: // ERR_NO_LICENSE_SERVER
349 warning("License error alert from server: No license server\n");
350 break;
351
352 case 0x8: // ERR_INVALID_CLIENT
353 warning("License error alert from server: Invalid client\n");
354 break;
355
356 case 0x4: // ERR_INVALID_SCOPE
357 case 0xb: // ERR_INVALID_PRODUCTID
358 case 0xc: // ERR_INVALID_MESSAGE_LENGTH
359 default:
360 warning("License error alert from server: code %u, state transition %u\n",
361 error_code, state_transition);
362 break;
363 }
364
365 /* handle error codes, for now, just report them */
366 switch (error_info)
367 {
368 default:
369 break;
370 }
371
373}
374
375
376/* Process a licence packet */
377void
379{
380 uint8 tag;
381
382 in_uint8(s, tag);
383 in_uint8s(s, 3); /* version, length */
384
385#if WITH_DEBUG
386 DEBUG(("Received licensing PDU (message type 0x%02x)\n", tag));
387#endif
388
389 switch (tag)
390 {
393 break;
394
397 break;
398
401 /* we can handle new and upgrades of licences the same way. */
403 break;
404
407 break;
408
409 default:
410 unimpl("licence tag 0x%02x\n", tag);
411 }
412}
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strncpy(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:427
#define LICENCE_HWID_SIZE
Definition: constants.h:142
#define LICENCE_SIGNATURE_SIZE
Definition: constants.h:143
#define LICENCE_TAG_NEW_LICENCE_REQUEST
Definition: constants.h:150
#define LICENCE_TAG_ERROR_ALERT
Definition: constants.h:152
#define LICENCE_TAG_UPGRADE_LICENCE
Definition: constants.h:148
#define LICENCE_TAG_PLATFORM_CHALLANGE_RESPONSE
Definition: constants.h:151
#define LICENCE_TAG_NEW_LICENCE
Definition: constants.h:147
#define BB_CLIENT_USER_NAME_BLOB
Definition: constants.h:154
#define LICENCE_TAG_LICENCE_INFO
Definition: constants.h:149
#define SEC_PADDING_SIZE
Definition: constants.h:94
#define SEC_LICENSE_PKT
Definition: constants.h:105
#define LICENCE_TAG_REQUEST
Definition: constants.h:145
#define LICENCE_TAG_PLATFORM_CHALLANGE
Definition: constants.h:146
#define LICENCE_TOKEN_SIZE
Definition: constants.h:141
#define BB_CLIENT_MACHINE_NAME_BLOB
Definition: constants.h:155
#define SEC_MODULUS_SIZE
Definition: constants.h:92
#define SEC_RANDOM_SIZE
Definition: constants.h:91
void rdssl_rc4_crypt(void *rc4_info, char *in_data, char *out_data, int len)
Definition: ssl_calls.c:173
static RD_BOOL licence_parse_platform_challenge(STREAM s, uint8 **token, uint8 **signature)
Definition: licence.c:232
void * rdssl_rc4_info_create(void)
Definition: ssl_calls.c:51
void rdssl_rc4_set_key(void *rc4_info, char *key, int len)
Definition: ssl_calls.c:123
static uint8 g_licence_key[16]
Definition: licence.c:41
void licence_process(STREAM s)
Definition: licence.c:378
void licence_process_error_alert(STREAM s)
Definition: licence.c:324
RD_BOOL g_licence_issued
Definition: licence.c:44
RD_BOOL g_licence_error_result
Definition: licence.c:45
static void licence_send_platform_challenge_response(uint8 *token, uint8 *crypt_hwid, uint8 *signature)
Definition: licence.c:204
static void licence_process_platform_challenge(STREAM s)
Definition: licence.c:253
RDP_VERSION g_rdp_version
Definition: uimain.c:74
static void licence_info(uint8 *client_random, uint8 *rsa_data, uint8 *licence_data, int licence_size, uint8 *hwid, uint8 *signature)
Definition: licence.c:74
char g_hostname[256]
Definition: uimain.c:26
static void licence_send_new_licence_request(uint8 *client_random, uint8 *rsa_data, char *user, char *host)
Definition: licence.c:115
char g_username[256]
Definition: uimain.c:25
static void licence_generate_hwid(uint8 *hwid)
Definition: licence.c:66
static void licence_process_request(STREAM s)
Definition: licence.c:156
static void licence_generate_keys(uint8 *client_random, uint8 *server_random, uint8 *pre_master_secret)
Definition: licence.c:49
static void licence_process_new_license(STREAM s)
Definition: licence.c:288
void rdssl_rc4_info_delete(void *rc4_info)
Definition: ssl_calls.c:90
int rdssl_mod_exp(char *out, int out_len, char *in, int in_len, char *mod, int mod_len, char *exp, int exp_len)
Definition: ssl_calls.c:1485
static uint8 g_licence_sign_key[16]
Definition: licence.c:42
#define s_mark_end(s)
Definition: parse.h:41
#define out_uint32_le(s, v)
Definition: parse.h:59
#define in_uint32(s, v)
Definition: parse.h:83
#define out_uint8(s, v)
Definition: parse.h:92
#define in_uint16_le(s, v)
Definition: parse.h:55
#define in_uint8p(s, v, n)
Definition: parse.h:89
#define s_check_end(s)
Definition: parse.h:44
#define in_uint8s(s, n)
Definition: parse.h:91
#define out_uint8s(s, n)
Definition: parse.h:95
#define in_uint8(s, v)
Definition: parse.h:88
#define out_uint16_le(s, v)
Definition: parse.h:58
#define s_check_rem(s, n)
Definition: parse.h:43
#define out_uint8p(s, v, n)
Definition: parse.h:93
#define in_uint32_le(s, v)
Definition: parse.h:56
#define out_uint16(s, v)
Definition: parse.h:84
int load_licence(unsigned char **data)
void xfree(void *mem)
Definition: uimain.c:758
void sec_hash_48(uint8 *out, uint8 *in, uint8 *salt1, uint8 *salt2, uint8 salt)
Definition: secure.c:155
void buf_out_uint32(uint8 *buffer, uint32 value)
Definition: secure.c:304
void sec_send(STREAM s, uint32 flags)
Definition: secure.c:472
void unimpl(char *format,...)
Definition: uimain.c:801
void save_licence(unsigned char *data, int length)
void sec_hash_16(uint8 *out, uint8 *in, uint8 *salt1, uint8 *salt2)
Definition: secure.c:187
STREAM sec_init(uint32 flags, int maxlen)
Definition: secure.c:419
void sec_sign(uint8 *signature, int siglen, uint8 *session_key, int keylen, uint8 *data, int datalen)
Definition: secure.c:314
#define DEBUG(args)
Definition: rdesktop.h:129
unsigned short uint16
Definition: types.h:30
unsigned int uint32
Definition: types.h:32
#define False
Definition: types.h:25
@ RDP_V5
Definition: types.h:44
enum _RDP_VERSION RDP_VERSION
int RD_BOOL
Definition: types.h:21
#define True
Definition: types.h:24
unsigned char uint8
Definition: types.h:28
void user(int argc, const char *argv[])
Definition: cmds.c:1350
#define NULL
Definition: types.h:112
GLdouble s
Definition: gl.h:2039
GLuint in
Definition: glext.h:9616
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat token
Definition: glfuncs.h:210
static int mod
Definition: i386-dis.c:1288
#define error(str)
Definition: mkdosfs.c:1605
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
DWORD exp
Definition: msg.c:16058
static FILE * out
Definition: regtests2xml.c:44
#define warning(s)
Definition: debug.h:83
#define memset(x, y, z)
Definition: compat.h:39
Definition: copy.c:22
Definition: parse.h:23
Definition: ecma_167.h:138
char * host
Definition: whois.c:55
static int error_code[8]
Definition: odbccp32.c:61