ReactOS  0.4.14-dev-323-g6fe6a88
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 */
25 static void
26 licence_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 
42 static 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 */
50 static BOOL
51 licence_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;
55  uint16 length =
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 
87  out_uint8p(s, signature, LICENCE_SIGNATURE_SIZE);
88 
89  s_mark_end(s);
90  return sec_send(This, s, sec_flags);
91 }
92 
93 /* Send a licence request packet */
94 static BOOL
95 licence_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 */
135 static BOOL
137 {
138  uint8 null_data[SEC_MODULUS_SIZE];
139  uint8 *server_random;
140  uint8 signature[LICENCE_SIGNATURE_SIZE];
141  uint8 hwid[LICENCE_HWID_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 */
176 static BOOL
177 licence_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 
200  out_uint8p(s, signature, LICENCE_SIGNATURE_SIZE);
201 
202  s_mark_end(s);
203  return sec_send(This, s, sec_flags);
204 }
205 
206 /* Parse an authentication request packet */
207 static 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 */
228 static 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];
234  uint8 sealed_buffer[LICENCE_TOKEN_SIZE + LICENCE_HWID_SIZE];
235  uint8 out_sig[LICENCE_SIGNATURE_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 */
260 static void
262 {
263  RC4_KEY crypt_key;
264  uint32 length;
265  uint16 check;
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  {
288  in_uint8s(s, length);
290  if (!s_check_rem(s, length))
291  return;
292  }
293 
294  This->licence_issued = True;
295  save_licence(This, s->p, length);
296 }
297 
298 /* Process a licence packet */
299 void
301 {
302  uint8 tag;
303 
304  in_uint8(s, tag);
305  in_uint8s(s, 3); /* version, length */
306 
307  switch (tag)
308  {
309  case LICENCE_TAG_DEMAND:
311  break;
312 
313  case LICENCE_TAG_AUTHREQ:
315  break;
316 
317  case LICENCE_TAG_ISSUE:
319  break;
320 
321  case LICENCE_TAG_REISSUE:
322  case LICENCE_TAG_RESULT:
323  break;
324 
325  default:
326  unimpl("licence tag 0x%x\n", tag);
327  }
328 }
#define out_uint16_le(s, v)
Definition: parse.h:58
void save_licence(unsigned char *data, int length)
#define out_uint8p(s, v, n)
Definition: parse.h:93
#define error(str)
Definition: mkdosfs.c:1605
#define LICENCE_TAG_USER
Definition: constants.h:103
static BOOL licence_process_demand(RDPCLIENT *This, STREAM s)
Definition: licence.c:136
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
void sec_hash_48(uint8 *out, uint8 *in, uint8 *salt1, uint8 *salt2, uint8 salt)
Definition: secure.c:155
unsigned int uint32
Definition: types.h:32
char * strncpy(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:427
#define free
Definition: debug_ros.c:5
static BOOL licence_send_request(RDPCLIENT *This, uint8 *client_random, uint8 *rsa_data, char *user, char *host)
Definition: licence.c:95
STREAM sec_init(uint32 flags, int maxlen)
Definition: secure.c:419
char * host
Definition: whois.c:55
#define out_uint32_le(s, v)
Definition: parse.h:59
#define s_check_rem(s, n)
Definition: parse.h:43
static void licence_process_issue(RDPCLIENT *This, STREAM s)
Definition: licence.c:261
Definition: ecma_167.h:138
#define out_uint16(s, v)
Definition: parse.h:84
#define LICENCE_TAG_AUTHRESP
Definition: constants.h:100
#define in_uint8p(s, v, n)
Definition: parse.h:89
#define LICENCE_SIGNATURE_SIZE
Definition: constants.h:143
void sec_hash_16(uint8 *out, uint8 *in, uint8 *salt1, uint8 *salt2)
Definition: secure.c:187
#define LICENCE_TAG_PRESENT
Definition: constants.h:98
static BOOL licence_parse_authreq(STREAM s, uint8 **token, uint8 **signature)
Definition: licence.c:208
#define out_uint8(s, v)
Definition: parse.h:92
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
unsigned int BOOL
Definition: ntddk_ex.h:94
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 LICENCE_TOKEN_SIZE
Definition: constants.h:141
static BOOL licence_send_authresp(RDPCLIENT *This, uint8 *token, uint8 *crypt_hwid, uint8 *signature)
Definition: licence.c:177
#define LICENCE_TAG_RESULT
Definition: constants.h:101
smooth NULL
Definition: ftsmooth.c:416
#define LICENCE_TAG_REISSUE
Definition: constants.h:97
#define in_uint8s(s, n)
Definition: parse.h:91
void buf_out_uint32(uint8 *buffer, uint32 value)
Definition: secure.c:304
#define out_uint8s(s, n)
Definition: parse.h:95
int load_licence(unsigned char **data)
#define s_check_end(s)
Definition: parse.h:44
#define SEC_MODULUS_SIZE
Definition: constants.h:92
#define True
Definition: types.h:24
#define False
Definition: types.h:25
#define LICENCE_TAG_REQUEST
Definition: constants.h:145
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
static void licence_generate_keys(RDPCLIENT *This, uint8 *client_random, uint8 *server_random, uint8 *pre_master_secret)
Definition: licence.c:26
#define SEC_RANDOM_SIZE
Definition: constants.h:91
#define LICENCE_TAG_HOST
Definition: constants.h:104
unsigned char uint8
Definition: types.h:28
void check(CONTEXT *pContext)
Definition: NtContinue.c:61
Definition: parse.h:22
#define LICENCE_TAG_DEMAND
Definition: constants.h:94
#define SEC_PADDING_SIZE
Definition: constants.h:94
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLdouble s
Definition: gl.h:2039
void sec_send(STREAM s, uint32 flags)
Definition: secure.c:472
#define LICENCE_TAG_ISSUE
Definition: constants.h:96
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
#define LICENCE_TAG_AUTHREQ
Definition: constants.h:95
static void licence_generate_hwid(RDPCLIENT *This, uint8 *hwid)
Definition: licence.c:43
unsigned short uint16
Definition: types.h:30
#define in_uint8(s, v)
Definition: parse.h:88
#define in_uint16(s, v)
Definition: parse.h:82
void sec_sign(uint8 *signature, int siglen, uint8 *session_key, int keylen, uint8 *data, int datalen)
Definition: secure.c:314
#define LICENCE_HWID_SIZE
Definition: constants.h:142
void unimpl(char *format,...)
Definition: uimain.c:801
#define s_mark_end(s)
Definition: parse.h:41
#define in_uint32_le(s, v)
Definition: parse.h:56
#define memset(x, y, z)
Definition: compat.h:39
void user(int argc, const char *argv[])
Definition: cmds.c:1350
#define SEC_LICENCE_NEG
Definition: constants.h:72
void licence_process(STREAM s)
Definition: licence.c:378
#define in_uint16_le(s, v)
Definition: parse.h:55
static void licence_process_authreq(RDPCLIENT *This, STREAM s)
Definition: licence.c:229
char * tag
Definition: main.c:59