1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 RDP licensing negotiation
4 Copyright (C) Matthew Chapman 1999-2005
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.
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.
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.
22 #include <openssl/rc4.h> // TODO: remove dependency on OpenSSL
24 /* Generate a session key and RC4 keys, given client and server randoms */
26 licence_generate_keys(RDPCLIENT
* This
, uint8
* client_random
, uint8
* server_random
, uint8
* pre_master_secret
)
28 uint8 master_secret
[48];
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');
35 /* Store first 16 bytes of session key as MAC secret */
36 memcpy(This
->licence
.sign_key
, key_block
, 16);
38 /* Generate RC4 key from next 16 bytes */
39 sec_hash_16(This
->licence
.key
, &key_block
[16], client_random
, server_random
);
43 licence_generate_hwid(RDPCLIENT
* This
, uint8
* hwid
)
45 buf_out_uint32(hwid
, 2);
46 strncpy((char *) (hwid
+ 4), This
->licence_hostname
, LICENCE_HWID_SIZE
- 4);
49 /* Present an existing licence to the server */
51 licence_present(RDPCLIENT
* This
, uint8
* client_random
, uint8
* rsa_data
,
52 uint8
* licence_data
, int licence_size
, uint8
* hwid
, uint8
* signature
)
54 uint32 sec_flags
= SEC_LICENCE_NEG
;
56 16 + SEC_RANDOM_SIZE
+ SEC_MODULUS_SIZE
+ SEC_PADDING_SIZE
+
57 licence_size
+ LICENCE_HWID_SIZE
+ LICENCE_SIGNATURE_SIZE
;
60 s
= sec_init(This
, sec_flags
, length
+ 4);
65 out_uint8(s
, LICENCE_TAG_PRESENT
);
66 out_uint8(s
, 2); /* version */
67 out_uint16_le(s
, length
);
71 out_uint16_le(s
, 0x0201);
73 out_uint8p(s
, client_random
, SEC_RANDOM_SIZE
);
75 out_uint16_le(s
, (SEC_MODULUS_SIZE
+ SEC_PADDING_SIZE
));
76 out_uint8p(s
, rsa_data
, SEC_MODULUS_SIZE
);
77 out_uint8s(s
, SEC_PADDING_SIZE
);
80 out_uint16_le(s
, licence_size
);
81 out_uint8p(s
, licence_data
, licence_size
);
84 out_uint16_le(s
, LICENCE_HWID_SIZE
);
85 out_uint8p(s
, hwid
, LICENCE_HWID_SIZE
);
87 out_uint8p(s
, signature
, LICENCE_SIGNATURE_SIZE
);
90 return sec_send(This
, s
, sec_flags
);
93 /* Send a licence request packet */
95 licence_send_request(RDPCLIENT
* This
, uint8
* client_random
, uint8
* rsa_data
, char *user
, char *host
)
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
;
103 s
= sec_init(This
, sec_flags
, length
+ 2);
108 out_uint8(s
, LICENCE_TAG_REQUEST
);
109 out_uint8(s
, 2); /* version */
110 out_uint16_le(s
, length
);
114 out_uint16_le(s
, 0xff01);
116 out_uint8p(s
, client_random
, SEC_RANDOM_SIZE
);
118 out_uint16_le(s
, (SEC_MODULUS_SIZE
+ SEC_PADDING_SIZE
));
119 out_uint8p(s
, rsa_data
, SEC_MODULUS_SIZE
);
120 out_uint8s(s
, SEC_PADDING_SIZE
);
122 out_uint16_le(s
, LICENCE_TAG_USER
);
123 out_uint16_le(s
, userlen
);
124 out_uint8p(s
, user
, userlen
);
126 out_uint16_le(s
, LICENCE_TAG_HOST
);
127 out_uint16_le(s
, hostlen
);
128 out_uint8p(s
, host
, hostlen
);
131 return sec_send(This
, s
, sec_flags
);
134 /* Process a licence demand packet */
136 licence_process_demand(RDPCLIENT
* This
, STREAM s
)
138 uint8 null_data
[SEC_MODULUS_SIZE
];
139 uint8
*server_random
;
140 uint8 signature
[LICENCE_SIGNATURE_SIZE
];
141 uint8 hwid
[LICENCE_HWID_SIZE
];
146 /* Retrieve the server random from the incoming packet */
147 in_uint8p(s
, server_random
, SEC_RANDOM_SIZE
);
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
);
154 licence_size
= load_licence(This
, &licence_data
);
155 if (licence_size
> 0)
157 /* Generate a signature for the HWID buffer */
158 licence_generate_hwid(This
, hwid
);
159 sec_sign(signature
, 16, This
->licence
.sign_key
, 16, hwid
, sizeof(hwid
));
161 /* Now encrypt the HWID */
162 RC4_set_key(&crypt_key
, 16, This
->licence
.key
);
163 RC4(&crypt_key
, sizeof(hwid
), hwid
, hwid
);
165 if(!licence_present(This
, null_data
, null_data
, licence_data
, licence_size
, hwid
, signature
))
172 return licence_send_request(This
, null_data
, null_data
, This
->licence_username
, This
->licence_hostname
);
175 /* Send an authentication response packet */
177 licence_send_authresp(RDPCLIENT
* This
, uint8
* token
, uint8
* crypt_hwid
, uint8
* signature
)
179 uint32 sec_flags
= SEC_LICENCE_NEG
;
183 s
= sec_init(This
, sec_flags
, length
+ 2);
188 out_uint8(s
, LICENCE_TAG_AUTHRESP
);
189 out_uint8(s
, 2); /* version */
190 out_uint16_le(s
, length
);
193 out_uint16_le(s
, LICENCE_TOKEN_SIZE
);
194 out_uint8p(s
, token
, LICENCE_TOKEN_SIZE
);
197 out_uint16_le(s
, LICENCE_HWID_SIZE
);
198 out_uint8p(s
, crypt_hwid
, LICENCE_HWID_SIZE
);
200 out_uint8p(s
, signature
, LICENCE_SIGNATURE_SIZE
);
203 return sec_send(This
, s
, sec_flags
);
206 /* Parse an authentication request packet */
208 licence_parse_authreq(STREAM s
, uint8
** token
, uint8
** signature
)
212 in_uint8s(s
, 6); /* unknown: f8 3d 15 00 04 f6 */
214 in_uint16_le(s
, tokenlen
);
215 if (tokenlen
!= LICENCE_TOKEN_SIZE
)
217 error("token len %d\n", tokenlen
);
221 in_uint8p(s
, *token
, tokenlen
);
222 in_uint8p(s
, *signature
, LICENCE_SIGNATURE_SIZE
);
224 return s_check_end(s
);
227 /* Process an authentication request packet */
229 licence_process_authreq(RDPCLIENT
* This
, STREAM s
)
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
];
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
);
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
);
246 /* Generate a signature for a buffer of token and HWID */
247 licence_generate_hwid(This
, 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
));
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
);
256 licence_send_authresp(This
, out_token
, crypt_hwid
, out_sig
);
259 /* Process an licence issue packet */
261 licence_process_issue(RDPCLIENT
* This
, STREAM s
)
268 in_uint8s(s
, 2); /* 3d 45 - unknown */
269 in_uint16_le(s
, length
);
270 if (!s_check_rem(s
, length
))
273 RC4_set_key(&crypt_key
, 16, This
->licence
.key
);
274 RC4(&crypt_key
, length
, s
->p
, s
->p
);
280 This
->licence_issued
= True
;
282 in_uint8s(s
, 2); /* pad */
284 /* advance to fourth string */
286 for (i
= 0; i
< 4; i
++)
288 in_uint8s(s
, length
);
289 in_uint32_le(s
, length
);
290 if (!s_check_rem(s
, length
))
294 This
->licence_issued
= True
;
295 save_licence(This
, s
->p
, length
);
298 /* Process a licence packet */
300 licence_process(RDPCLIENT
* This
, STREAM s
)
305 in_uint8s(s
, 3); /* version, length */
309 case LICENCE_TAG_DEMAND
:
310 licence_process_demand(This
, s
);
313 case LICENCE_TAG_AUTHREQ
:
314 licence_process_authreq(This
, s
);
317 case LICENCE_TAG_ISSUE
:
318 licence_process_issue(This
, s
);
321 case LICENCE_TAG_REISSUE
:
322 case LICENCE_TAG_RESULT
:
326 unimpl("licence tag 0x%x\n", tag
);