ReactOS 0.4.15-dev-7924-g5949c20
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 1999-2005
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20
21#include "rdesktop.h"
22#include <openssl/rc4.h> // TODO: remove dependency on OpenSSL
23
24/* Generate a session key and RC4 keys, given client and server randoms */
25static void
26licence_generate_keys(RDPCLIENT * This, uint8 * client_random, uint8 * server_random, uint8 * pre_master_secret)
27{
28 uint8 master_secret[48];
29 uint8 key_block[48];
30
31 /* Generate master secret and then key material */
32 sec_hash_48(master_secret, pre_master_secret, client_random, server_random, 'A');
33 sec_hash_48(key_block, master_secret, server_random, client_random, 'A');
34
35 /* Store first 16 bytes of session key as MAC secret */
36 memcpy(This->licence.sign_key, key_block, 16);
37
38 /* Generate RC4 key from next 16 bytes */
39 sec_hash_16(This->licence.key, &key_block[16], client_random, server_random);
40}
41
42static void
44{
45 buf_out_uint32(hwid, 2);
46 strncpy((char *) (hwid + 4), This->licence_hostname, LICENCE_HWID_SIZE - 4);
47}
48
49/* Present an existing licence to the server */
50static BOOL
51licence_present(RDPCLIENT * This, uint8 * client_random, uint8 * rsa_data,
52 uint8 * licence_data, int licence_size, uint8 * hwid, uint8 * signature)
53{
54 uint32 sec_flags = SEC_LICENCE_NEG;
58 STREAM s;
59
60 s = sec_init(This, sec_flags, length + 4);
61
62 if(s == NULL)
63 return False;
64
66 out_uint8(s, 2); /* version */
68
69 out_uint32_le(s, 1);
70 out_uint16(s, 0);
71 out_uint16_le(s, 0x0201);
72
73 out_uint8p(s, client_random, SEC_RANDOM_SIZE);
74 out_uint16(s, 0);
76 out_uint8p(s, rsa_data, SEC_MODULUS_SIZE);
78
79 out_uint16_le(s, 1);
80 out_uint16_le(s, licence_size);
81 out_uint8p(s, licence_data, licence_size);
82
83 out_uint16_le(s, 1);
86
88
90 return sec_send(This, s, sec_flags);
91}
92
93/* Send a licence request packet */
94static BOOL
95licence_send_request(RDPCLIENT * This, uint8 * client_random, uint8 * rsa_data, char *user, char *host)
96{
97 uint32 sec_flags = SEC_LICENCE_NEG;
98 uint16 userlen = (uint16)strlen(user) + 1;
99 uint16 hostlen = (uint16)strlen(host) + 1;
100 uint16 length = 128 + userlen + hostlen;
101 STREAM s;
102
103 s = sec_init(This, sec_flags, length + 2);
104
105 if(s == NULL)
106 return False;
107
109 out_uint8(s, 2); /* version */
111
112 out_uint32_le(s, 1);
113 out_uint16(s, 0);
114 out_uint16_le(s, 0xff01);
115
116 out_uint8p(s, client_random, SEC_RANDOM_SIZE);
117 out_uint16(s, 0);
119 out_uint8p(s, rsa_data, SEC_MODULUS_SIZE);
121
123 out_uint16_le(s, userlen);
124 out_uint8p(s, user, userlen);
125
127 out_uint16_le(s, hostlen);
128 out_uint8p(s, host, hostlen);
129
130 s_mark_end(s);
131 return sec_send(This, s, sec_flags);
132}
133
134/* Process a licence demand packet */
135static BOOL
137{
138 uint8 null_data[SEC_MODULUS_SIZE];
139 uint8 *server_random;
140 uint8 signature[LICENCE_SIGNATURE_SIZE];
142 uint8 *licence_data;
143 int licence_size;
144 RC4_KEY crypt_key;
145
146 /* Retrieve the server random from the incoming packet */
147 in_uint8p(s, server_random, SEC_RANDOM_SIZE);
148
149 /* We currently use null client keys. This is a bit naughty but, hey,
150 the security of licence negotiation isn't exactly paramount. */
151 memset(null_data, 0, sizeof(null_data));
152 licence_generate_keys(This, null_data, server_random, null_data);
153
154 licence_size = load_licence(This, &licence_data);
155 if (licence_size > 0)
156 {
157 /* Generate a signature for the HWID buffer */
159 sec_sign(signature, 16, This->licence.sign_key, 16, hwid, sizeof(hwid));
160
161 /* Now encrypt the HWID */
162 RC4_set_key(&crypt_key, 16, This->licence.key);
163 RC4(&crypt_key, sizeof(hwid), hwid, hwid);
164
165 if(!licence_present(This, null_data, null_data, licence_data, licence_size, hwid, signature))
166 return False;
167
168 free(licence_data);
169 return True;
170 }
171
172 return licence_send_request(This, null_data, null_data, This->licence_username, This->licence_hostname);
173}
174
175/* Send an authentication response packet */
176static BOOL
177licence_send_authresp(RDPCLIENT * This, uint8 * token, uint8 * crypt_hwid, uint8 * signature)
178{
179 uint32 sec_flags = SEC_LICENCE_NEG;
180 uint16 length = 58;
181 STREAM s;
182
183 s = sec_init(This, sec_flags, length + 2);
184
185 if(s == NULL)
186 return False;
187
189 out_uint8(s, 2); /* version */
191
192 out_uint16_le(s, 1);
195
196 out_uint16_le(s, 1);
198 out_uint8p(s, crypt_hwid, LICENCE_HWID_SIZE);
199
201
202 s_mark_end(s);
203 return sec_send(This, s, sec_flags);
204}
205
206/* Parse an authentication request packet */
207static BOOL
209{
210 uint16 tokenlen;
211
212 in_uint8s(s, 6); /* unknown: f8 3d 15 00 04 f6 */
213
214 in_uint16_le(s, tokenlen);
215 if (tokenlen != LICENCE_TOKEN_SIZE)
216 {
217 error("token len %d\n", tokenlen);
218 return False;
219 }
220
221 in_uint8p(s, *token, tokenlen);
222 in_uint8p(s, *signature, LICENCE_SIGNATURE_SIZE);
223
224 return s_check_end(s);
225}
226
227/* Process an authentication request packet */
228static void
230{
231 uint8 *in_token, *in_sig;
232 uint8 out_token[LICENCE_TOKEN_SIZE], decrypt_token[LICENCE_TOKEN_SIZE];
233 uint8 hwid[LICENCE_HWID_SIZE], crypt_hwid[LICENCE_HWID_SIZE];
236 RC4_KEY crypt_key;
237
238 /* Parse incoming packet and save the encrypted token */
239 licence_parse_authreq(s, &in_token, &in_sig);
240 memcpy(out_token, in_token, LICENCE_TOKEN_SIZE);
241
242 /* Decrypt the token. It should read TEST in Unicode. */
243 RC4_set_key(&crypt_key, 16, This->licence.key);
244 RC4(&crypt_key, LICENCE_TOKEN_SIZE, in_token, decrypt_token);
245
246 /* Generate a signature for a buffer of token and HWID */
248 memcpy(sealed_buffer, decrypt_token, LICENCE_TOKEN_SIZE);
249 memcpy(sealed_buffer + LICENCE_TOKEN_SIZE, hwid, LICENCE_HWID_SIZE);
250 sec_sign(out_sig, 16, This->licence.sign_key, 16, sealed_buffer, sizeof(sealed_buffer));
251
252 /* Now encrypt the HWID */
253 RC4_set_key(&crypt_key, 16, This->licence.key);
254 RC4(&crypt_key, LICENCE_HWID_SIZE, hwid, crypt_hwid);
255
256 licence_send_authresp(This, out_token, crypt_hwid, out_sig);
257}
258
259/* Process an licence issue packet */
260static void
262{
263 RC4_KEY crypt_key;
266 int i;
267
268 in_uint8s(s, 2); /* 3d 45 - unknown */
270 if (!s_check_rem(s, length))
271 return;
272
273 RC4_set_key(&crypt_key, 16, This->licence.key);
274 RC4(&crypt_key, length, s->p, s->p);
275
276 in_uint16(s, check);
277 if (check != 0)
278 return;
279
280 This->licence_issued = True;
281
282 in_uint8s(s, 2); /* pad */
283
284 /* advance to fourth string */
285 length = 0;
286 for (i = 0; i < 4; i++)
287 {
290 if (!s_check_rem(s, length))
291 return;
292 }
293
294 This->licence_issued = True;
296}
297
298/* Process a licence packet */
299void
301{
302 uint8 tag;
303
304 in_uint8(s, tag);
305 in_uint8s(s, 3); /* version, length */
306
307 switch (tag)
308 {
311 break;
312
315 break;
316
319 break;
320
323 break;
324
325 default:
326 unimpl("licence tag 0x%x\n", tag);
327 }
328}
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 SEC_PADDING_SIZE
Definition: constants.h:94
#define LICENCE_TAG_REQUEST
Definition: constants.h:145
#define LICENCE_TOKEN_SIZE
Definition: constants.h:141
#define SEC_MODULUS_SIZE
Definition: constants.h:92
#define SEC_RANDOM_SIZE
Definition: constants.h:91
void licence_process(STREAM s)
Definition: licence.c:378
static void licence_generate_hwid(uint8 *hwid)
Definition: licence.c:66
static void licence_generate_keys(uint8 *client_random, uint8 *server_random, uint8 *pre_master_secret)
Definition: licence.c:49
#define s_mark_end(s)
Definition: parse.h:41
#define out_uint32_le(s, v)
Definition: parse.h:59
#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 in_uint16(s, v)
Definition: parse.h:82
#define out_uint16(s, v)
Definition: parse.h:84
int load_licence(unsigned char **data)
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
unsigned short uint16
Definition: types.h:30
unsigned int uint32
Definition: types.h:32
#define False
Definition: types.h:25
#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 free
Definition: debug_ros.c:5
#define NULL
Definition: types.h:112
#define check(expected, result)
Definition: dplayx.c:32
unsigned int BOOL
Definition: ntddk_ex.h:94
GLdouble s
Definition: gl.h:2039
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
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
#define error(str)
Definition: mkdosfs.c:1605
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define LICENCE_TAG_DEMAND
Definition: constants.h:94
#define LICENCE_TAG_PRESENT
Definition: constants.h:98
#define SEC_LICENCE_NEG
Definition: constants.h:72
#define LICENCE_TAG_AUTHRESP
Definition: constants.h:100
#define LICENCE_TAG_AUTHREQ
Definition: constants.h:95
#define LICENCE_TAG_ISSUE
Definition: constants.h:96
#define LICENCE_TAG_HOST
Definition: constants.h:104
#define LICENCE_TAG_USER
Definition: constants.h:103
#define LICENCE_TAG_REISSUE
Definition: constants.h:97
#define LICENCE_TAG_RESULT
Definition: constants.h:101
static void licence_process_issue(RDPCLIENT *This, STREAM s)
Definition: licence.c:261
static BOOL licence_parse_authreq(STREAM s, uint8 **token, uint8 **signature)
Definition: licence.c:208
static BOOL licence_process_demand(RDPCLIENT *This, STREAM s)
Definition: licence.c:136
static BOOL licence_send_authresp(RDPCLIENT *This, uint8 *token, uint8 *crypt_hwid, uint8 *signature)
Definition: licence.c:177
static void licence_process_authreq(RDPCLIENT *This, STREAM s)
Definition: licence.c:229
static BOOL licence_present(RDPCLIENT *This, uint8 *client_random, uint8 *rsa_data, uint8 *licence_data, int licence_size, uint8 *hwid, uint8 *signature)
Definition: licence.c:51
static BOOL licence_send_request(RDPCLIENT *This, uint8 *client_random, uint8 *rsa_data, char *user, char *host)
Definition: licence.c:95
#define memset(x, y, z)
Definition: compat.h:39
Definition: parse.h:23
Definition: ecma_167.h:138
char * host
Definition: whois.c:55