1 /**
2  * FreeRDP: A Remote Desktop Protocol Implementation
3  * RDP Licensing
4  *
5  * Copyright 2011-2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6  * Copyright 2014 Norbert Federa <norbert.federa@thincast.com>
7  * Copyright 2018 David Fort <contact@hardening-consulting.com>
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *     http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21 
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 
26 #include <winpr/crt.h>
27 #include <winpr/crypto.h>
28 #include <winpr/shell.h>
29 #include <winpr/path.h>
30 #include <winpr/file.h>
31 
32 #include <freerdp/log.h>
33 
34 #include "redirection.h"
35 #include "certificate.h"
36 
37 #include "license.h"
38 
39 #define TAG FREERDP_TAG("core.license")
40 
41 #if 0
42 #define LICENSE_NULL_CLIENT_RANDOM 1
43 #define LICENSE_NULL_PREMASTER_SECRET 1
44 #endif
45 
46 static wStream* license_send_stream_init(rdpLicense* license);
47 
48 static void license_generate_randoms(rdpLicense* license);
49 static BOOL license_generate_keys(rdpLicense* license);
50 static BOOL license_generate_hwid(rdpLicense* license);
51 static BOOL license_encrypt_premaster_secret(rdpLicense* license);
52 
53 static LICENSE_PRODUCT_INFO* license_new_product_info(void);
54 static void license_free_product_info(LICENSE_PRODUCT_INFO* productInfo);
55 static BOOL license_read_product_info(wStream* s, LICENSE_PRODUCT_INFO* productInfo);
56 
57 static LICENSE_BLOB* license_new_binary_blob(UINT16 type);
58 static void license_free_binary_blob(LICENSE_BLOB* blob);
59 static BOOL license_read_binary_blob(wStream* s, LICENSE_BLOB* blob);
60 static BOOL license_write_binary_blob(wStream* s, const LICENSE_BLOB* blob);
61 
62 static SCOPE_LIST* license_new_scope_list(void);
63 static void license_free_scope_list(SCOPE_LIST* scopeList);
64 static BOOL license_read_scope_list(wStream* s, SCOPE_LIST* scopeList);
65 
66 static BOOL license_read_license_request_packet(rdpLicense* license, wStream* s);
67 static BOOL license_read_platform_challenge_packet(rdpLicense* license, wStream* s);
68 static BOOL license_read_new_or_upgrade_license_packet(rdpLicense* license, wStream* s);
69 static BOOL license_read_error_alert_packet(rdpLicense* license, wStream* s);
70 
71 static BOOL license_write_new_license_request_packet(rdpLicense* license, wStream* s);
72 static BOOL license_answer_license_request(rdpLicense* license);
73 
74 static BOOL license_write_platform_challenge_response_packet(rdpLicense* license, wStream* s,
75                                                              const BYTE* mac_data);
76 static BOOL license_send_platform_challenge_response_packet(rdpLicense* license);
77 static BOOL license_send_client_info(rdpLicense* license, const LICENSE_BLOB* calBlob,
78                                      BYTE* signature);
79 
80 #define PLATFORMID (CLIENT_OS_ID_WINNT_POST_52 | CLIENT_IMAGE_ID_MICROSOFT)
81 
82 #ifdef WITH_DEBUG_LICENSE
83 
84 static const char* const LICENSE_MESSAGE_STRINGS[] = { "",
85 	                                                   "License Request",
86 	                                                   "Platform Challenge",
87 	                                                   "New License",
88 	                                                   "Upgrade License",
89 	                                                   "",
90 	                                                   "",
91 	                                                   "",
92 	                                                   "",
93 	                                                   "",
94 	                                                   "",
95 	                                                   "",
96 	                                                   "",
97 	                                                   "",
98 	                                                   "",
99 	                                                   "",
100 	                                                   "",
101 	                                                   "",
102 	                                                   "License Info",
103 	                                                   "New License Request",
104 	                                                   "",
105 	                                                   "Platform Challenge Response",
106 	                                                   "",
107 	                                                   "",
108 	                                                   "",
109 	                                                   "",
110 	                                                   "",
111 	                                                   "",
112 	                                                   "",
113 	                                                   "",
114 	                                                   "",
115 	                                                   "Error Alert" };
116 
117 static const char* const error_codes[] = { "ERR_UNKNOWN",
118 	                                       "ERR_INVALID_SERVER_CERTIFICATE",
119 	                                       "ERR_NO_LICENSE",
120 	                                       "ERR_INVALID_MAC",
121 	                                       "ERR_INVALID_SCOPE",
122 	                                       "ERR_UNKNOWN",
123 	                                       "ERR_NO_LICENSE_SERVER",
124 	                                       "STATUS_VALID_CLIENT",
125 	                                       "ERR_INVALID_CLIENT",
126 	                                       "ERR_UNKNOWN",
127 	                                       "ERR_UNKNOWN",
128 	                                       "ERR_INVALID_PRODUCT_ID",
129 	                                       "ERR_INVALID_MESSAGE_LENGTH" };
130 
131 static const char* const state_transitions[] = { "ST_UNKNOWN", "ST_TOTAL_ABORT", "ST_NO_TRANSITION",
132 	                                             "ST_RESET_PHASE_TO_START",
133 	                                             "ST_RESEND_LAST_MESSAGE" };
134 
license_print_product_info(const LICENSE_PRODUCT_INFO * productInfo)135 static void license_print_product_info(const LICENSE_PRODUCT_INFO* productInfo)
136 {
137 	char* CompanyName = NULL;
138 	char* ProductId = NULL;
139 	ConvertFromUnicode(CP_UTF8, 0, (WCHAR*)productInfo->pbCompanyName,
140 	                   productInfo->cbCompanyName / 2, &CompanyName, 0, NULL, NULL);
141 	ConvertFromUnicode(CP_UTF8, 0, (WCHAR*)productInfo->pbProductId, productInfo->cbProductId / 2,
142 	                   &ProductId, 0, NULL, NULL);
143 	WLog_INFO(TAG, "ProductInfo:");
144 	WLog_INFO(TAG, "\tdwVersion: 0x%08" PRIX32 "", productInfo->dwVersion);
145 	WLog_INFO(TAG, "\tCompanyName: %s", CompanyName);
146 	WLog_INFO(TAG, "\tProductId: %s", ProductId);
147 	free(CompanyName);
148 	free(ProductId);
149 }
150 
license_print_scope_list(const SCOPE_LIST * scopeList)151 static void license_print_scope_list(const SCOPE_LIST* scopeList)
152 {
153 	UINT32 index;
154 	const LICENSE_BLOB* scope;
155 	WLog_INFO(TAG, "ScopeList (%" PRIu32 "):", scopeList->count);
156 
157 	for (index = 0; index < scopeList->count; index++)
158 	{
159 		scope = &scopeList->array[index];
160 		WLog_INFO(TAG, "\t%s", (const char*)scope->data);
161 	}
162 }
163 #endif
164 
165 static const char licenseStore[] = "licenses";
166 
computeCalHash(const char * hostname,char * hashStr)167 static BOOL computeCalHash(const char* hostname, char* hashStr)
168 {
169 	WINPR_DIGEST_CTX* sha1 = NULL;
170 	BOOL ret = FALSE;
171 	BYTE hash[20];
172 	size_t i;
173 
174 	if (!(sha1 = winpr_Digest_New()))
175 		goto out;
176 	if (!winpr_Digest_Init(sha1, WINPR_MD_SHA1))
177 		goto out;
178 	if (!winpr_Digest_Update(sha1, (const BYTE*)hostname, strlen(hostname)))
179 		goto out;
180 	if (!winpr_Digest_Final(sha1, hash, sizeof(hash)))
181 		goto out;
182 
183 	for (i = 0; i < sizeof(hash); i++, hashStr += 2)
184 		sprintf_s(hashStr, 3, "%.2x", hash[i]);
185 
186 	ret = TRUE;
187 out:
188 	winpr_Digest_Free(sha1);
189 	return ret;
190 }
191 
saveCal(rdpSettings * settings,const BYTE * data,size_t length,const char * hostname)192 static BOOL saveCal(rdpSettings* settings, const BYTE* data, size_t length, const char* hostname)
193 {
194 	char hash[41];
195 	FILE* fp;
196 	char* licenseStorePath = NULL;
197 	char filename[MAX_PATH], filenameNew[MAX_PATH];
198 	char *filepath = NULL, *filepathNew = NULL;
199 	WCHAR* wFilepathNew = NULL;
200 	WCHAR* wFilepath = NULL;
201 	size_t written;
202 	BOOL ret = FALSE;
203 
204 	if (!winpr_PathFileExists(settings->ConfigPath))
205 	{
206 		if (!winpr_PathMakePath(settings->ConfigPath, 0))
207 		{
208 			WLog_ERR(TAG, "error creating directory '%s'", settings->ConfigPath);
209 			goto out;
210 		}
211 		WLog_INFO(TAG, "creating directory %s", settings->ConfigPath);
212 	}
213 
214 	if (!(licenseStorePath = GetCombinedPath(settings->ConfigPath, licenseStore)))
215 		goto out;
216 
217 	if (!winpr_PathFileExists(licenseStorePath))
218 	{
219 		if (!winpr_PathMakePath(licenseStorePath, 0))
220 		{
221 			WLog_ERR(TAG, "error creating directory '%s'", licenseStorePath);
222 			goto out;
223 		}
224 		WLog_INFO(TAG, "creating directory %s", licenseStorePath);
225 	}
226 
227 	if (!computeCalHash(hostname, hash))
228 		goto out;
229 	sprintf_s(filename, sizeof(filename) - 1, "%s.cal", hash);
230 	sprintf_s(filenameNew, sizeof(filenameNew) - 1, "%s.cal.new", hash);
231 
232 	if (!(filepath = GetCombinedPath(licenseStorePath, filename)))
233 		goto out;
234 
235 	if (!(filepathNew = GetCombinedPath(licenseStorePath, filenameNew)))
236 		goto out;
237 	if (ConvertToUnicode(CP_UTF8, 0, filepathNew, -1, &wFilepathNew, 0) <= 0)
238 		goto out;
239 	if (ConvertToUnicode(CP_UTF8, 0, filepath, -1, &wFilepath, 0) <= 0)
240 		goto out;
241 
242 	fp = winpr_fopen(filepathNew, "wb");
243 	if (!fp)
244 		goto out;
245 
246 	written = fwrite(data, length, 1, fp);
247 	fclose(fp);
248 
249 	if (written != 1)
250 	{
251 		DeleteFileW(wFilepathNew);
252 		goto out;
253 	}
254 
255 	ret = MoveFileExW(wFilepathNew, wFilepath, MOVEFILE_REPLACE_EXISTING);
256 
257 out:
258 	free(wFilepathNew);
259 	free(filepathNew);
260 	free(wFilepath);
261 	free(filepath);
262 	free(licenseStorePath);
263 	return ret;
264 }
265 
loadCalFile(rdpSettings * settings,const char * hostname,size_t * dataLen)266 static BYTE* loadCalFile(rdpSettings* settings, const char* hostname, size_t* dataLen)
267 {
268 	char *licenseStorePath = NULL, *calPath = NULL;
269 	char calFilename[MAX_PATH];
270 	char hash[41];
271 	size_t length;
272 	int status;
273 	FILE* fp;
274 	BYTE* ret = NULL;
275 
276 	if (!computeCalHash(hostname, hash))
277 	{
278 		WLog_ERR(TAG, "loadCalFile: unable to compute hostname hash");
279 		return NULL;
280 	}
281 
282 	sprintf_s(calFilename, sizeof(calFilename) - 1, "%s.cal", hash);
283 
284 	if (!(licenseStorePath = GetCombinedPath(settings->ConfigPath, licenseStore)))
285 		return NULL;
286 
287 	if (!(calPath = GetCombinedPath(licenseStorePath, calFilename)))
288 		goto error_path;
289 
290 	fp = winpr_fopen(calPath, "rb");
291 	if (!fp)
292 		goto error_open;
293 
294 	_fseeki64(fp, 0, SEEK_END);
295 	length = _ftelli64(fp);
296 	_fseeki64(fp, 0, SEEK_SET);
297 
298 	ret = (BYTE*)malloc(length);
299 	if (!ret)
300 		goto error_malloc;
301 
302 	status = fread(ret, length, 1, fp);
303 	if (status <= 0)
304 		goto error_read;
305 
306 	*dataLen = length;
307 
308 	fclose(fp);
309 	free(calPath);
310 	free(licenseStorePath);
311 	return ret;
312 
313 error_read:
314 	free(ret);
315 error_malloc:
316 	fclose(fp);
317 error_open:
318 	free(calPath);
319 error_path:
320 	free(licenseStorePath);
321 	return NULL;
322 }
323 
324 /**
325  * Read a licensing preamble.\n
326  * @msdn{cc240480}
327  * @param s stream
328  * @param bMsgType license message type
329  * @param flags message flags
330  * @param wMsgSize message size
331  * @return if the operation completed successfully
332  */
333 
license_read_preamble(wStream * s,BYTE * bMsgType,BYTE * flags,UINT16 * wMsgSize)334 static BOOL license_read_preamble(wStream* s, BYTE* bMsgType, BYTE* flags, UINT16* wMsgSize)
335 {
336 	/* preamble (4 bytes) */
337 	if (Stream_GetRemainingLength(s) < 4)
338 		return FALSE;
339 
340 	Stream_Read_UINT8(s, *bMsgType);  /* bMsgType (1 byte) */
341 	Stream_Read_UINT8(s, *flags);     /* flags (1 byte) */
342 	Stream_Read_UINT16(s, *wMsgSize); /* wMsgSize (2 bytes) */
343 	return TRUE;
344 }
345 
346 /**
347  * Write a licensing preamble.\n
348  * @msdn{cc240480}
349  * @param s stream
350  * @param bMsgType license message type
351  * @param flags message flags
352  * @param wMsgSize message size
353  */
354 
license_write_preamble(wStream * s,BYTE bMsgType,BYTE flags,UINT16 wMsgSize)355 static BOOL license_write_preamble(wStream* s, BYTE bMsgType, BYTE flags, UINT16 wMsgSize)
356 {
357 	if (!Stream_EnsureRemainingCapacity(s, 4))
358 		return FALSE;
359 
360 	/* preamble (4 bytes) */
361 	Stream_Write_UINT8(s, bMsgType);  /* bMsgType (1 byte) */
362 	Stream_Write_UINT8(s, flags);     /* flags (1 byte) */
363 	Stream_Write_UINT16(s, wMsgSize); /* wMsgSize (2 bytes) */
364 	return TRUE;
365 }
366 
367 /**
368  * Initialize a license packet stream.\n
369  * @param license license module
370  * @return stream
371  */
372 
license_send_stream_init(rdpLicense * license)373 wStream* license_send_stream_init(rdpLicense* license)
374 {
375 	wStream* s;
376 	BOOL do_crypt = license->rdp->do_crypt;
377 
378 	license->rdp->sec_flags = SEC_LICENSE_PKT;
379 
380 	/**
381 	 * Encryption of licensing packets is optional even if the rdp security
382 	 * layer is used. If the peer has not indicated that it is capable of
383 	 * processing encrypted licensing packets (rdp->do_crypt_license) we turn
384 	 * off encryption (via rdp->do_crypt) before initializing the rdp stream
385 	 * and reenable it afterwards.
386 	 */
387 
388 	if (do_crypt)
389 	{
390 		license->rdp->sec_flags |= SEC_LICENSE_ENCRYPT_CS;
391 		license->rdp->do_crypt = license->rdp->do_crypt_license;
392 	}
393 
394 	s = rdp_send_stream_init(license->rdp);
395 	if (!s)
396 		return NULL;
397 
398 	license->rdp->do_crypt = do_crypt;
399 	license->PacketHeaderLength = Stream_GetPosition(s);
400 	if (!Stream_SafeSeek(s, LICENSE_PREAMBLE_LENGTH))
401 		goto fail;
402 	return s;
403 
404 fail:
405 	Stream_Release(s);
406 	return NULL;
407 }
408 
409 /**
410  * Send an RDP licensing packet.\n
411  * @msdn{cc240479}
412  * @param license license module
413  * @param s stream
414  */
415 
license_send(rdpLicense * license,wStream * s,BYTE type)416 static BOOL license_send(rdpLicense* license, wStream* s, BYTE type)
417 {
418 	size_t length;
419 	BYTE flags;
420 	UINT16 wMsgSize;
421 	rdpRdp* rdp = license->rdp;
422 	BOOL ret;
423 
424 	DEBUG_LICENSE("Sending %s Packet", LICENSE_MESSAGE_STRINGS[type & 0x1F]);
425 	length = Stream_GetPosition(s);
426 	wMsgSize = length - license->PacketHeaderLength;
427 	Stream_SetPosition(s, license->PacketHeaderLength);
428 	flags = PREAMBLE_VERSION_3_0;
429 
430 	/**
431 	 * Using EXTENDED_ERROR_MSG_SUPPORTED here would cause mstsc to crash when
432 	 * running in server mode! This flag seems to be incorrectly documented.
433 	 */
434 
435 	if (!rdp->settings->ServerMode)
436 		flags |= EXTENDED_ERROR_MSG_SUPPORTED;
437 
438 	if (!license_write_preamble(s, type, flags, wMsgSize))
439 		return FALSE;
440 
441 #ifdef WITH_DEBUG_LICENSE
442 	WLog_DBG(TAG, "Sending %s Packet, length %" PRIu16 "", LICENSE_MESSAGE_STRINGS[type & 0x1F],
443 	         wMsgSize);
444 	winpr_HexDump(TAG, WLOG_DEBUG, Stream_Pointer(s) - LICENSE_PREAMBLE_LENGTH, wMsgSize);
445 #endif
446 	Stream_SetPosition(s, length);
447 	ret = rdp_send(rdp, s, MCS_GLOBAL_CHANNEL_ID);
448 	rdp->sec_flags = 0;
449 	return ret;
450 }
451 
452 /**
453  * Receive an RDP licensing packet.\n
454  * @msdn{cc240479}
455  * @param license license module
456  * @param s stream
457  * @return if the operation completed successfully
458  */
459 
license_recv(rdpLicense * license,wStream * s)460 int license_recv(rdpLicense* license, wStream* s)
461 {
462 	BYTE flags;
463 	BYTE bMsgType;
464 	UINT16 wMsgSize;
465 	UINT16 length;
466 	UINT16 channelId;
467 	UINT16 securityFlags = 0;
468 
469 	if (!rdp_read_header(license->rdp, s, &length, &channelId))
470 	{
471 		WLog_ERR(TAG, "Incorrect RDP header.");
472 		return -1;
473 	}
474 
475 	if (!rdp_read_security_header(s, &securityFlags, &length))
476 		return -1;
477 
478 	if (securityFlags & SEC_ENCRYPT)
479 	{
480 		if (!rdp_decrypt(license->rdp, s, &length, securityFlags))
481 		{
482 			WLog_ERR(TAG, "rdp_decrypt failed");
483 			return -1;
484 		}
485 	}
486 
487 	if (!(securityFlags & SEC_LICENSE_PKT))
488 	{
489 		int status;
490 
491 		if (!(securityFlags & SEC_ENCRYPT))
492 			Stream_Rewind(s, RDP_SECURITY_HEADER_LENGTH);
493 
494 		status = rdp_recv_out_of_sequence_pdu(license->rdp, s);
495 		if (status < 0)
496 		{
497 			WLog_ERR(TAG, "unexpected license packet.");
498 			return status;
499 		}
500 
501 		return 0;
502 	}
503 
504 	if (!license_read_preamble(s, &bMsgType, &flags, &wMsgSize)) /* preamble (4 bytes) */
505 		return -1;
506 
507 	DEBUG_LICENSE("Receiving %s Packet", LICENSE_MESSAGE_STRINGS[bMsgType & 0x1F]);
508 
509 	switch (bMsgType)
510 	{
511 		case LICENSE_REQUEST:
512 			if (!license_read_license_request_packet(license, s))
513 				return -1;
514 
515 			if (!license_answer_license_request(license))
516 				return -1;
517 			break;
518 
519 		case PLATFORM_CHALLENGE:
520 			if (!license_read_platform_challenge_packet(license, s))
521 				return -1;
522 
523 			if (!license_send_platform_challenge_response_packet(license))
524 				return -1;
525 			break;
526 
527 		case NEW_LICENSE:
528 		case UPGRADE_LICENSE:
529 			if (!license_read_new_or_upgrade_license_packet(license, s))
530 				return -1;
531 			break;
532 
533 		case ERROR_ALERT:
534 			if (!license_read_error_alert_packet(license, s))
535 				return -1;
536 			break;
537 
538 		default:
539 			WLog_ERR(TAG, "invalid bMsgType:%" PRIu8 "", bMsgType);
540 			return -1;
541 	}
542 
543 	if (!tpkt_ensure_stream_consumed(s, length))
544 		return -1;
545 	return 0;
546 }
547 
license_generate_randoms(rdpLicense * license)548 void license_generate_randoms(rdpLicense* license)
549 {
550 #ifdef LICENSE_NULL_CLIENT_RANDOM
551 	ZeroMemory(license->ClientRandom, CLIENT_RANDOM_LENGTH); /* ClientRandom */
552 #else
553 	winpr_RAND(license->ClientRandom, CLIENT_RANDOM_LENGTH);       /* ClientRandom */
554 #endif
555 
556 #ifdef LICENSE_NULL_PREMASTER_SECRET
557 	ZeroMemory(license->PremasterSecret, PREMASTER_SECRET_LENGTH); /* PremasterSecret */
558 #else
559 	winpr_RAND(license->PremasterSecret, PREMASTER_SECRET_LENGTH); /* PremasterSecret */
560 #endif
561 }
562 
563 /**
564  * Generate License Cryptographic Keys.
565  * @param license license module
566  */
567 
license_generate_keys(rdpLicense * license)568 static BOOL license_generate_keys(rdpLicense* license)
569 {
570 	BOOL ret;
571 
572 	if (
573 	    /* MasterSecret */
574 	    !security_master_secret(license->PremasterSecret, license->ClientRandom,
575 	                            license->ServerRandom, license->MasterSecret) ||
576 	    /* SessionKeyBlob */
577 	    !security_session_key_blob(license->MasterSecret, license->ClientRandom,
578 	                               license->ServerRandom, license->SessionKeyBlob))
579 	{
580 		return FALSE;
581 	}
582 	security_mac_salt_key(license->SessionKeyBlob, license->ClientRandom, license->ServerRandom,
583 	                      license->MacSaltKey); /* MacSaltKey */
584 	ret = security_licensing_encryption_key(
585 	    license->SessionKeyBlob, license->ClientRandom, license->ServerRandom,
586 	    license->LicensingEncryptionKey); /* LicensingEncryptionKey */
587 #ifdef WITH_DEBUG_LICENSE
588 	WLog_DBG(TAG, "ClientRandom:");
589 	winpr_HexDump(TAG, WLOG_DEBUG, license->ClientRandom, CLIENT_RANDOM_LENGTH);
590 	WLog_DBG(TAG, "ServerRandom:");
591 	winpr_HexDump(TAG, WLOG_DEBUG, license->ServerRandom, SERVER_RANDOM_LENGTH);
592 	WLog_DBG(TAG, "PremasterSecret:");
593 	winpr_HexDump(TAG, WLOG_DEBUG, license->PremasterSecret, PREMASTER_SECRET_LENGTH);
594 	WLog_DBG(TAG, "MasterSecret:");
595 	winpr_HexDump(TAG, WLOG_DEBUG, license->MasterSecret, MASTER_SECRET_LENGTH);
596 	WLog_DBG(TAG, "SessionKeyBlob:");
597 	winpr_HexDump(TAG, WLOG_DEBUG, license->SessionKeyBlob, SESSION_KEY_BLOB_LENGTH);
598 	WLog_DBG(TAG, "MacSaltKey:");
599 	winpr_HexDump(TAG, WLOG_DEBUG, license->MacSaltKey, MAC_SALT_KEY_LENGTH);
600 	WLog_DBG(TAG, "LicensingEncryptionKey:");
601 	winpr_HexDump(TAG, WLOG_DEBUG, license->LicensingEncryptionKey,
602 	              LICENSING_ENCRYPTION_KEY_LENGTH);
603 #endif
604 	return ret;
605 }
606 
607 /**
608  * Generate Unique Hardware Identifier (CLIENT_HARDWARE_ID).\n
609  * @param license license module
610  */
611 
license_generate_hwid(rdpLicense * license)612 BOOL license_generate_hwid(rdpLicense* license)
613 {
614 	const BYTE* hashTarget;
615 	size_t targetLen;
616 	BYTE macAddress[6];
617 
618 	ZeroMemory(license->HardwareId, HWID_LENGTH);
619 
620 	if (license->rdp->settings->OldLicenseBehaviour)
621 	{
622 		ZeroMemory(macAddress, sizeof(macAddress));
623 		hashTarget = macAddress;
624 		targetLen = sizeof(macAddress);
625 	}
626 	else
627 	{
628 		wStream s;
629 		const char* hostname = license->rdp->settings->ClientHostname;
630 		Stream_StaticInit(&s, license->HardwareId, 4);
631 		Stream_Write_UINT32(&s, PLATFORMID);
632 		Stream_Free(&s, TRUE);
633 
634 		hashTarget = (const BYTE*)hostname;
635 		targetLen = strlen(hostname);
636 	}
637 
638 	/* Allow FIPS override for use of MD5 here, really this does not have to be MD5 as we are just
639 	 * taking a MD5 hash of the 6 bytes of 0's(macAddress) */
640 	/* and filling in the Data1-Data4 fields of the CLIENT_HARDWARE_ID structure(from MS-RDPELE
641 	 * section 2.2.2.3.1). This is for RDP licensing packets */
642 	/* which will already be encrypted under FIPS, so the use of MD5 here is not for sensitive data
643 	 * protection. */
644 	return winpr_Digest_Allow_FIPS(WINPR_MD_MD5, hashTarget, targetLen,
645 	                               &license->HardwareId[HWID_PLATFORM_ID_LENGTH],
646 	                               WINPR_MD5_DIGEST_LENGTH);
647 }
648 
license_get_server_rsa_public_key(rdpLicense * license)649 static BOOL license_get_server_rsa_public_key(rdpLicense* license)
650 {
651 	BYTE* Exponent;
652 	BYTE* Modulus;
653 	int ModulusLength;
654 	rdpSettings* settings = license->rdp->settings;
655 
656 	if (license->ServerCertificate->length < 1)
657 	{
658 		if (!certificate_read_server_certificate(license->certificate, settings->ServerCertificate,
659 		                                         settings->ServerCertificateLength))
660 			return FALSE;
661 	}
662 
663 	Exponent = license->certificate->cert_info.exponent;
664 	Modulus = license->certificate->cert_info.Modulus;
665 	ModulusLength = license->certificate->cert_info.ModulusLength;
666 	CopyMemory(license->Exponent, Exponent, 4);
667 	license->ModulusLength = ModulusLength;
668 	license->Modulus = (BYTE*)malloc(ModulusLength);
669 	if (!license->Modulus)
670 		return FALSE;
671 	CopyMemory(license->Modulus, Modulus, ModulusLength);
672 	return TRUE;
673 }
674 
license_encrypt_premaster_secret(rdpLicense * license)675 BOOL license_encrypt_premaster_secret(rdpLicense* license)
676 {
677 	BYTE* EncryptedPremasterSecret;
678 
679 	if (!license_get_server_rsa_public_key(license))
680 		return FALSE;
681 
682 #ifdef WITH_DEBUG_LICENSE
683 	WLog_DBG(TAG, "Modulus (%" PRIu32 " bits):", license->ModulusLength * 8);
684 	winpr_HexDump(TAG, WLOG_DEBUG, license->Modulus, license->ModulusLength);
685 	WLog_DBG(TAG, "Exponent:");
686 	winpr_HexDump(TAG, WLOG_DEBUG, license->Exponent, 4);
687 #endif
688 
689 	EncryptedPremasterSecret = (BYTE*)calloc(1, license->ModulusLength);
690 	if (!EncryptedPremasterSecret)
691 		return FALSE;
692 
693 	license->EncryptedPremasterSecret->type = BB_RANDOM_BLOB;
694 	license->EncryptedPremasterSecret->length = PREMASTER_SECRET_LENGTH;
695 #ifndef LICENSE_NULL_PREMASTER_SECRET
696 	{
697 		SSIZE_T length = crypto_rsa_public_encrypt(
698 		    license->PremasterSecret, PREMASTER_SECRET_LENGTH, license->ModulusLength,
699 		    license->Modulus, license->Exponent, EncryptedPremasterSecret);
700 		if ((length < 0) || (length > UINT16_MAX))
701 			return FALSE;
702 		license->EncryptedPremasterSecret->length = (UINT16)length;
703 	}
704 #endif
705 	license->EncryptedPremasterSecret->data = EncryptedPremasterSecret;
706 	return TRUE;
707 }
708 
license_rc4_with_licenseKey(const rdpLicense * license,const BYTE * input,size_t len,LICENSE_BLOB * target)709 static BOOL license_rc4_with_licenseKey(const rdpLicense* license, const BYTE* input, size_t len,
710                                         LICENSE_BLOB* target)
711 {
712 	WINPR_RC4_CTX* rc4;
713 	BYTE* buffer = NULL;
714 
715 	rc4 =
716 	    winpr_RC4_New_Allow_FIPS(license->LicensingEncryptionKey, LICENSING_ENCRYPTION_KEY_LENGTH);
717 	if (!rc4)
718 		return FALSE;
719 
720 	buffer = (BYTE*)realloc(target->data, len);
721 	if (!buffer)
722 		goto error_buffer;
723 
724 	target->data = buffer;
725 	target->length = len;
726 
727 	if (!winpr_RC4_Update(rc4, len, input, buffer))
728 		goto error_buffer;
729 
730 	winpr_RC4_Free(rc4);
731 	return TRUE;
732 
733 error_buffer:
734 	winpr_RC4_Free(rc4);
735 	return FALSE;
736 }
737 
738 /**
739  * Encrypt the input using the license key and MAC the input for a signature
740  *
741  * @param license rdpLicense to get keys and salt from
742  * @param input the input data to encrypt and MAC
743  * @param len size of input
744  * @param target a target LICENSE_BLOB where the encrypted input will be stored
745  * @param mac the signature buffer (16 bytes)
746  * @return if the operation completed successfully
747  */
license_encrypt_and_MAC(rdpLicense * license,const BYTE * input,size_t len,LICENSE_BLOB * target,BYTE * mac)748 static BOOL license_encrypt_and_MAC(rdpLicense* license, const BYTE* input, size_t len,
749                                     LICENSE_BLOB* target, BYTE* mac)
750 {
751 	return license_rc4_with_licenseKey(license, input, len, target) &&
752 	       security_mac_data(license->MacSaltKey, input, len, mac);
753 }
754 
755 /**
756  * Decrypt the input using the license key and check the MAC
757  *
758  * @param license rdpLicense to get keys and salt from
759  * @param input the input data to decrypt and MAC
760  * @param len size of input
761  * @param target a target LICENSE_BLOB where the decrypted input will be stored
762  * @param mac the signature buffer (16 bytes)
763  * @return if the operation completed successfully
764  */
license_decrypt_and_check_MAC(rdpLicense * license,const BYTE * input,size_t len,LICENSE_BLOB * target,const BYTE * packetMac)765 static BOOL license_decrypt_and_check_MAC(rdpLicense* license, const BYTE* input, size_t len,
766                                           LICENSE_BLOB* target, const BYTE* packetMac)
767 {
768 	BYTE macData[16];
769 
770 	return license_rc4_with_licenseKey(license, input, len, target) &&
771 	       security_mac_data(license->MacSaltKey, target->data, len, macData) &&
772 	       (memcmp(packetMac, macData, sizeof(macData)) == 0);
773 }
774 
775 /**
776  * Read Product Information (PRODUCT_INFO).\n
777  * @msdn{cc241915}
778  * @param s stream
779  * @param productInfo product information
780  */
781 
license_read_product_info(wStream * s,LICENSE_PRODUCT_INFO * productInfo)782 BOOL license_read_product_info(wStream* s, LICENSE_PRODUCT_INFO* productInfo)
783 {
784 	if (Stream_GetRemainingLength(s) < 8)
785 		return FALSE;
786 
787 	Stream_Read_UINT32(s, productInfo->dwVersion);     /* dwVersion (4 bytes) */
788 	Stream_Read_UINT32(s, productInfo->cbCompanyName); /* cbCompanyName (4 bytes) */
789 
790 	/* Name must be >0, but there is no upper limit defined, use UINT32_MAX */
791 	if ((productInfo->cbCompanyName < 2) || (productInfo->cbCompanyName % 2 != 0))
792 		return FALSE;
793 
794 	if (Stream_GetRemainingLength(s) < productInfo->cbCompanyName)
795 		return FALSE;
796 
797 	productInfo->pbProductId = NULL;
798 	productInfo->pbCompanyName = (BYTE*)malloc(productInfo->cbCompanyName);
799 	if (!productInfo->pbCompanyName)
800 		return FALSE;
801 	Stream_Read(s, productInfo->pbCompanyName, productInfo->cbCompanyName);
802 
803 	if (Stream_GetRemainingLength(s) < 4)
804 		goto out_fail;
805 
806 	Stream_Read_UINT32(s, productInfo->cbProductId); /* cbProductId (4 bytes) */
807 
808 	if ((productInfo->cbProductId < 2) || (productInfo->cbProductId % 2 != 0))
809 		goto out_fail;
810 
811 	if (Stream_GetRemainingLength(s) < productInfo->cbProductId)
812 		goto out_fail;
813 
814 	productInfo->pbProductId = (BYTE*)malloc(productInfo->cbProductId);
815 	if (!productInfo->pbProductId)
816 		goto out_fail;
817 	Stream_Read(s, productInfo->pbProductId, productInfo->cbProductId);
818 	return TRUE;
819 
820 out_fail:
821 	free(productInfo->pbCompanyName);
822 	free(productInfo->pbProductId);
823 	productInfo->pbCompanyName = NULL;
824 	productInfo->pbProductId = NULL;
825 	return FALSE;
826 }
827 
828 /**
829  * Allocate New Product Information (LICENSE_PRODUCT_INFO).\n
830  * @msdn{cc241915}
831  * @return new product information
832  */
833 
license_new_product_info()834 LICENSE_PRODUCT_INFO* license_new_product_info()
835 {
836 	LICENSE_PRODUCT_INFO* productInfo;
837 	productInfo = (LICENSE_PRODUCT_INFO*)malloc(sizeof(LICENSE_PRODUCT_INFO));
838 	if (!productInfo)
839 		return NULL;
840 	productInfo->dwVersion = 0;
841 	productInfo->cbCompanyName = 0;
842 	productInfo->pbCompanyName = NULL;
843 	productInfo->cbProductId = 0;
844 	productInfo->pbProductId = NULL;
845 	return productInfo;
846 }
847 
848 /**
849  * Free Product Information (LICENSE_PRODUCT_INFO).\n
850  * @msdn{cc241915}
851  * @param productInfo product information
852  */
853 
license_free_product_info(LICENSE_PRODUCT_INFO * productInfo)854 void license_free_product_info(LICENSE_PRODUCT_INFO* productInfo)
855 {
856 	if (productInfo)
857 	{
858 		free(productInfo->pbCompanyName);
859 		free(productInfo->pbProductId);
860 		free(productInfo);
861 	}
862 }
863 
864 /**
865  * Read License Binary Blob (LICENSE_BINARY_BLOB).\n
866  * @msdn{cc240481}
867  * @param s stream
868  * @param blob license binary blob
869  */
870 
license_read_binary_blob(wStream * s,LICENSE_BLOB * blob)871 BOOL license_read_binary_blob(wStream* s, LICENSE_BLOB* blob)
872 {
873 	UINT16 wBlobType;
874 
875 	if (Stream_GetRemainingLength(s) < 4)
876 		return FALSE;
877 
878 	Stream_Read_UINT16(s, wBlobType);    /* wBlobType (2 bytes) */
879 	Stream_Read_UINT16(s, blob->length); /* wBlobLen (2 bytes) */
880 
881 	if (Stream_GetRemainingLength(s) < blob->length)
882 		return FALSE;
883 
884 	/*
885 	 * Server can choose to not send data by setting length to 0.
886 	 * If so, it may not bother to set the type, so shortcut the warning
887 	 */
888 	if ((blob->type != BB_ANY_BLOB) && (blob->length == 0))
889 		return TRUE;
890 
891 	if ((blob->type != wBlobType) && (blob->type != BB_ANY_BLOB))
892 	{
893 		WLog_ERR(TAG,
894 		         "license binary blob type (0x%" PRIx16 ") does not match expected type (0x%" PRIx16
895 		         ").",
896 		         wBlobType, blob->type);
897 	}
898 
899 	blob->type = wBlobType;
900 	blob->data = (BYTE*)malloc(blob->length);
901 	if (!blob->data)
902 		return FALSE;
903 	Stream_Read(s, blob->data, blob->length); /* blobData */
904 	return TRUE;
905 }
906 
907 /**
908  * Write License Binary Blob (LICENSE_BINARY_BLOB).\n
909  * @msdn{cc240481}
910  * @param s stream
911  * @param blob license binary blob
912  */
913 
license_write_binary_blob(wStream * s,const LICENSE_BLOB * blob)914 BOOL license_write_binary_blob(wStream* s, const LICENSE_BLOB* blob)
915 {
916 	if (!Stream_EnsureRemainingCapacity(s, blob->length + 4))
917 		return FALSE;
918 
919 	Stream_Write_UINT16(s, blob->type);   /* wBlobType (2 bytes) */
920 	Stream_Write_UINT16(s, blob->length); /* wBlobLen (2 bytes) */
921 
922 	if (blob->length > 0)
923 		Stream_Write(s, blob->data, blob->length); /* blobData */
924 	return TRUE;
925 }
926 
license_write_encrypted_premaster_secret_blob(wStream * s,const LICENSE_BLOB * blob,UINT32 ModulusLength)927 static BOOL license_write_encrypted_premaster_secret_blob(wStream* s, const LICENSE_BLOB* blob,
928                                                           UINT32 ModulusLength)
929 {
930 	UINT32 length;
931 	length = ModulusLength + 8;
932 
933 	if (blob->length > ModulusLength)
934 	{
935 		WLog_ERR(TAG, "license_write_encrypted_premaster_secret_blob: invalid blob");
936 		return FALSE;
937 	}
938 
939 	if (!Stream_EnsureRemainingCapacity(s, length + 4))
940 		return FALSE;
941 	Stream_Write_UINT16(s, blob->type); /* wBlobType (2 bytes) */
942 	Stream_Write_UINT16(s, length);     /* wBlobLen (2 bytes) */
943 
944 	if (blob->length > 0)
945 		Stream_Write(s, blob->data, blob->length); /* blobData */
946 
947 	Stream_Zero(s, length - blob->length);
948 	return TRUE;
949 }
950 
951 /**
952  * Allocate New License Binary Blob (LICENSE_BINARY_BLOB).\n
953  * @msdn{cc240481}
954  * @return new license binary blob
955  */
956 
license_new_binary_blob(UINT16 type)957 LICENSE_BLOB* license_new_binary_blob(UINT16 type)
958 {
959 	LICENSE_BLOB* blob;
960 	blob = (LICENSE_BLOB*)calloc(1, sizeof(LICENSE_BLOB));
961 	if (blob)
962 		blob->type = type;
963 	return blob;
964 }
965 
966 /**
967  * Free License Binary Blob (LICENSE_BINARY_BLOB).\n
968  * @msdn{cc240481}
969  * @param blob license binary blob
970  */
971 
license_free_binary_blob(LICENSE_BLOB * blob)972 void license_free_binary_blob(LICENSE_BLOB* blob)
973 {
974 	if (blob)
975 	{
976 		free(blob->data);
977 		free(blob);
978 	}
979 }
980 
981 /**
982  * Read License Scope List (SCOPE_LIST).\n
983  * @msdn{cc241916}
984  * @param s stream
985  * @param scopeList scope list
986  */
987 
license_read_scope_list(wStream * s,SCOPE_LIST * scopeList)988 BOOL license_read_scope_list(wStream* s, SCOPE_LIST* scopeList)
989 {
990 	UINT32 i;
991 	UINT32 scopeCount;
992 
993 	if (Stream_GetRemainingLength(s) < 4)
994 		return FALSE;
995 
996 	Stream_Read_UINT32(s, scopeCount); /* ScopeCount (4 bytes) */
997 
998 	if (scopeCount > Stream_GetRemainingLength(s) / 4) /* every blob is at least 4 bytes */
999 		return FALSE;
1000 
1001 	scopeList->count = scopeCount;
1002 	scopeList->array = (LICENSE_BLOB*)calloc(scopeCount, sizeof(LICENSE_BLOB));
1003 	if (!scopeList->array)
1004 		return FALSE;
1005 
1006 	/* ScopeArray */
1007 	for (i = 0; i < scopeCount; i++)
1008 	{
1009 		scopeList->array[i].type = BB_SCOPE_BLOB;
1010 
1011 		if (!license_read_binary_blob(s, &scopeList->array[i]))
1012 			return FALSE;
1013 	}
1014 
1015 	return TRUE;
1016 }
1017 
1018 /**
1019  * Allocate New License Scope List (SCOPE_LIST).\n
1020  * @msdn{cc241916}
1021  * @return new scope list
1022  */
1023 
license_new_scope_list()1024 SCOPE_LIST* license_new_scope_list()
1025 {
1026 	return (SCOPE_LIST*)calloc(1, sizeof(SCOPE_LIST));
1027 }
1028 
1029 /**
1030  * Free License Scope List (SCOPE_LIST).\n
1031  * @msdn{cc241916}
1032  * @param scopeList scope list
1033  */
1034 
license_free_scope_list(SCOPE_LIST * scopeList)1035 void license_free_scope_list(SCOPE_LIST* scopeList)
1036 {
1037 	UINT32 i;
1038 
1039 	if (!scopeList)
1040 		return;
1041 
1042 	/*
1043 	 * We must NOT call license_free_binary_blob() on each scopelist->array[i] element,
1044 	 * because scopelist->array was allocated at once, by a single call to malloc. The elements
1045 	 * it contains cannot be deallocated separately then.
1046 	 * To make things clean, we must deallocate each scopelist->array[].data,
1047 	 * and finish by deallocating scopelist->array with a single call to free().
1048 	 */
1049 	for (i = 0; i < scopeList->count; i++)
1050 	{
1051 		free(scopeList->array[i].data);
1052 	}
1053 
1054 	free(scopeList->array);
1055 	free(scopeList);
1056 }
1057 
license_send_client_info(rdpLicense * license,const LICENSE_BLOB * calBlob,BYTE * signature)1058 BOOL license_send_client_info(rdpLicense* license, const LICENSE_BLOB* calBlob, BYTE* signature)
1059 {
1060 	wStream* s;
1061 
1062 	/* Client License Information: */
1063 	UINT32 PlatformId = PLATFORMID;
1064 	UINT32 PreferredKeyExchangeAlg = KEY_EXCHANGE_ALG_RSA;
1065 
1066 	s = license_send_stream_init(license);
1067 	if (!s)
1068 		return FALSE;
1069 
1070 	Stream_Write_UINT32(s, PreferredKeyExchangeAlg); /* PreferredKeyExchangeAlg (4 bytes) */
1071 	Stream_Write_UINT32(s, PlatformId);              /* PlatformId (4 bytes) */
1072 
1073 	/* ClientRandom (32 bytes) */
1074 	Stream_Write(s, license->ClientRandom, CLIENT_RANDOM_LENGTH);
1075 
1076 	/* Licensing Binary Blob with EncryptedPreMasterSecret: */
1077 	if (!license_write_encrypted_premaster_secret_blob(s, license->EncryptedPremasterSecret,
1078 	                                                   license->ModulusLength))
1079 		goto error;
1080 
1081 	/* Licensing Binary Blob with LicenseInfo: */
1082 	if (!license_write_binary_blob(s, calBlob))
1083 		goto error;
1084 
1085 	/* Licensing Binary Blob with EncryptedHWID */
1086 	if (!license_write_binary_blob(s, license->EncryptedHardwareId))
1087 		goto error;
1088 
1089 	/* MACData */
1090 	Stream_Write(s, signature, LICENSING_ENCRYPTION_KEY_LENGTH);
1091 
1092 	return license_send(license, s, LICENSE_INFO);
1093 
1094 error:
1095 	Stream_Release(s);
1096 	return FALSE;
1097 }
1098 
1099 /**
1100  * Read a LICENSE_REQUEST packet.\n
1101  * @msdn{cc241914}
1102  * @param license license module
1103  * @param s stream
1104  */
1105 
license_read_license_request_packet(rdpLicense * license,wStream * s)1106 BOOL license_read_license_request_packet(rdpLicense* license, wStream* s)
1107 {
1108 	/* ServerRandom (32 bytes) */
1109 	if (Stream_GetRemainingLength(s) < 32)
1110 		return FALSE;
1111 
1112 	Stream_Read(s, license->ServerRandom, 32);
1113 
1114 	/* ProductInfo */
1115 	if (!license_read_product_info(s, license->ProductInfo))
1116 		return FALSE;
1117 
1118 	/* KeyExchangeList */
1119 	if (!license_read_binary_blob(s, license->KeyExchangeList))
1120 		return FALSE;
1121 
1122 	/* ServerCertificate */
1123 	if (!license_read_binary_blob(s, license->ServerCertificate))
1124 		return FALSE;
1125 
1126 	/* ScopeList */
1127 	if (!license_read_scope_list(s, license->ScopeList))
1128 		return FALSE;
1129 
1130 	/* Parse Server Certificate */
1131 	if (!certificate_read_server_certificate(license->certificate, license->ServerCertificate->data,
1132 	                                         license->ServerCertificate->length))
1133 		return FALSE;
1134 
1135 	if (!license_generate_keys(license) || !license_generate_hwid(license) ||
1136 	    !license_encrypt_premaster_secret(license))
1137 		return FALSE;
1138 
1139 #ifdef WITH_DEBUG_LICENSE
1140 	WLog_DBG(TAG, "ServerRandom:");
1141 	winpr_HexDump(TAG, WLOG_DEBUG, license->ServerRandom, 32);
1142 	license_print_product_info(license->ProductInfo);
1143 	license_print_scope_list(license->ScopeList);
1144 #endif
1145 	return TRUE;
1146 }
1147 
1148 /*
1149  * Read a PLATFORM_CHALLENGE packet.\n
1150  * @msdn{cc241921}
1151  * @param license license module
1152  * @param s stream
1153  */
1154 
license_read_platform_challenge_packet(rdpLicense * license,wStream * s)1155 BOOL license_read_platform_challenge_packet(rdpLicense* license, wStream* s)
1156 {
1157 	BYTE macData[16];
1158 	UINT32 ConnectFlags = 0;
1159 
1160 	DEBUG_LICENSE("Receiving Platform Challenge Packet");
1161 
1162 	if (Stream_GetRemainingLength(s) < 4)
1163 		return FALSE;
1164 
1165 	Stream_Read_UINT32(s, ConnectFlags); /* ConnectFlags, Reserved (4 bytes) */
1166 
1167 	/* EncryptedPlatformChallenge */
1168 	license->EncryptedPlatformChallenge->type = BB_ANY_BLOB;
1169 	if (!license_read_binary_blob(s, license->EncryptedPlatformChallenge))
1170 		return FALSE;
1171 	license->EncryptedPlatformChallenge->type = BB_ENCRYPTED_DATA_BLOB;
1172 
1173 	/* MACData (16 bytes) */
1174 	if (Stream_GetRemainingLength(s) < 16)
1175 		return FALSE;
1176 
1177 	Stream_Read(s, macData, 16);
1178 	if (!license_decrypt_and_check_MAC(license, license->EncryptedPlatformChallenge->data,
1179 	                                   license->EncryptedPlatformChallenge->length,
1180 	                                   license->PlatformChallenge, macData))
1181 		return FALSE;
1182 
1183 #ifdef WITH_DEBUG_LICENSE
1184 	WLog_DBG(TAG, "ConnectFlags: 0x%08" PRIX32 "", ConnectFlags);
1185 	WLog_DBG(TAG, "EncryptedPlatformChallenge:");
1186 	winpr_HexDump(TAG, WLOG_DEBUG, license->EncryptedPlatformChallenge->data,
1187 	              license->EncryptedPlatformChallenge->length);
1188 	WLog_DBG(TAG, "PlatformChallenge:");
1189 	winpr_HexDump(TAG, WLOG_DEBUG, license->PlatformChallenge->data,
1190 	              license->PlatformChallenge->length);
1191 	WLog_DBG(TAG, "MacData:");
1192 	winpr_HexDump(TAG, WLOG_DEBUG, macData, 16);
1193 #endif
1194 	return TRUE;
1195 }
1196 
license_read_encrypted_blob(const rdpLicense * license,wStream * s,LICENSE_BLOB * target)1197 static BOOL license_read_encrypted_blob(const rdpLicense* license, wStream* s, LICENSE_BLOB* target)
1198 {
1199 	UINT16 wBlobType, wBlobLen;
1200 	BYTE* encryptedData;
1201 
1202 	if (Stream_GetRemainingLength(s) < 4)
1203 		return FALSE;
1204 
1205 	Stream_Read_UINT16(s, wBlobType);
1206 	if (wBlobType != BB_ENCRYPTED_DATA_BLOB)
1207 	{
1208 		WLog_DBG(
1209 		    TAG,
1210 		    "expecting BB_ENCRYPTED_DATA_BLOB blob, probably a windows 2003 server, continuing...");
1211 	}
1212 
1213 	Stream_Read_UINT16(s, wBlobLen);
1214 
1215 	if (Stream_GetRemainingLength(s) < wBlobLen)
1216 		return FALSE;
1217 
1218 	encryptedData = Stream_Pointer(s);
1219 	Stream_Seek(s, wBlobLen);
1220 	return license_rc4_with_licenseKey(license, encryptedData, wBlobLen, target);
1221 }
1222 
1223 /**
1224  * Read a NEW_LICENSE packet.\n
1225  * @msdn{cc241926}
1226  * @param license license module
1227  * @param s stream
1228  */
1229 
license_read_new_or_upgrade_license_packet(rdpLicense * license,wStream * s)1230 BOOL license_read_new_or_upgrade_license_packet(rdpLicense* license, wStream* s)
1231 {
1232 	UINT32 os_major;
1233 	UINT32 os_minor;
1234 	UINT32 cbScope, cbCompanyName, cbProductId, cbLicenseInfo;
1235 	wStream* licenseStream = NULL;
1236 	BOOL ret = FALSE;
1237 	BYTE computedMac[16];
1238 	LICENSE_BLOB* calBlob;
1239 
1240 	DEBUG_LICENSE("Receiving Server New/Upgrade License Packet");
1241 
1242 	calBlob = license_new_binary_blob(BB_DATA_BLOB);
1243 	if (!calBlob)
1244 		return FALSE;
1245 
1246 	/* EncryptedLicenseInfo */
1247 	if (!license_read_encrypted_blob(license, s, calBlob))
1248 		goto out_free_blob;
1249 
1250 	/* compute MAC and check it */
1251 	if (Stream_GetRemainingLength(s) < 16)
1252 		goto out_free_blob;
1253 
1254 	if (!security_mac_data(license->MacSaltKey, calBlob->data, calBlob->length, computedMac))
1255 		goto out_free_blob;
1256 
1257 	if (memcmp(computedMac, Stream_Pointer(s), sizeof(computedMac)) != 0)
1258 	{
1259 		WLog_ERR(TAG, "new or upgrade license MAC mismatch");
1260 		goto out_free_blob;
1261 	}
1262 
1263 	if (!Stream_SafeSeek(s, 16))
1264 		goto out_free_blob;
1265 
1266 	licenseStream = Stream_New(calBlob->data, calBlob->length);
1267 	if (!licenseStream)
1268 		goto out_free_blob;
1269 
1270 	if (Stream_GetRemainingLength(licenseStream) < 8)
1271 		goto out_free_stream;
1272 
1273 	Stream_Read_UINT16(licenseStream, os_minor);
1274 	Stream_Read_UINT16(licenseStream, os_major);
1275 
1276 	/* Scope */
1277 	Stream_Read_UINT32(licenseStream, cbScope);
1278 	if (Stream_GetRemainingLength(licenseStream) < cbScope)
1279 		goto out_free_stream;
1280 #ifdef WITH_DEBUG_LICENSE
1281 	WLog_DBG(TAG, "Scope:");
1282 	winpr_HexDump(TAG, WLOG_DEBUG, Stream_Pointer(licenseStream), cbScope);
1283 #endif
1284 	Stream_Seek(licenseStream, cbScope);
1285 
1286 	/* CompanyName */
1287 	if (Stream_GetRemainingLength(licenseStream) < 4)
1288 		goto out_free_stream;
1289 	Stream_Read_UINT32(licenseStream, cbCompanyName);
1290 	if (Stream_GetRemainingLength(licenseStream) < cbCompanyName)
1291 		goto out_free_stream;
1292 #ifdef WITH_DEBUG_LICENSE
1293 	WLog_DBG(TAG, "Company name:");
1294 	winpr_HexDump(TAG, WLOG_DEBUG, Stream_Pointer(licenseStream), cbCompanyName);
1295 #endif
1296 	Stream_Seek(licenseStream, cbCompanyName);
1297 
1298 	/* productId */
1299 	if (Stream_GetRemainingLength(licenseStream) < 4)
1300 		goto out_free_stream;
1301 	Stream_Read_UINT32(licenseStream, cbProductId);
1302 	if (Stream_GetRemainingLength(licenseStream) < cbProductId)
1303 		goto out_free_stream;
1304 #ifdef WITH_DEBUG_LICENSE
1305 	WLog_DBG(TAG, "Product id:");
1306 	winpr_HexDump(TAG, WLOG_DEBUG, Stream_Pointer(licenseStream), cbProductId);
1307 #endif
1308 	Stream_Seek(licenseStream, cbProductId);
1309 
1310 	/* licenseInfo */
1311 	if (Stream_GetRemainingLength(licenseStream) < 4)
1312 		goto out_free_stream;
1313 	Stream_Read_UINT32(licenseStream, cbLicenseInfo);
1314 	if (Stream_GetRemainingLength(licenseStream) < cbLicenseInfo)
1315 		goto out_free_stream;
1316 
1317 	license->state = LICENSE_STATE_COMPLETED;
1318 
1319 	ret = TRUE;
1320 	if (!license->rdp->settings->OldLicenseBehaviour)
1321 		ret = saveCal(license->rdp->settings, Stream_Pointer(licenseStream), cbLicenseInfo,
1322 		              license->rdp->settings->ClientHostname);
1323 
1324 out_free_stream:
1325 	Stream_Free(licenseStream, FALSE);
1326 out_free_blob:
1327 	license_free_binary_blob(calBlob);
1328 	return ret;
1329 }
1330 
1331 /**
1332  * Read an ERROR_ALERT packet.\n
1333  * @msdn{cc240482}
1334  * @param license license module
1335  * @param s stream
1336  */
1337 
license_read_error_alert_packet(rdpLicense * license,wStream * s)1338 BOOL license_read_error_alert_packet(rdpLicense* license, wStream* s)
1339 {
1340 	UINT32 dwErrorCode;
1341 	UINT32 dwStateTransition;
1342 
1343 	if (Stream_GetRemainingLength(s) < 8)
1344 		return FALSE;
1345 
1346 	Stream_Read_UINT32(s, dwErrorCode);       /* dwErrorCode (4 bytes) */
1347 	Stream_Read_UINT32(s, dwStateTransition); /* dwStateTransition (4 bytes) */
1348 
1349 	if (!license_read_binary_blob(s, license->ErrorInfo)) /* bbErrorInfo */
1350 		return FALSE;
1351 
1352 #ifdef WITH_DEBUG_LICENSE
1353 	WLog_DBG(TAG, "dwErrorCode: %s, dwStateTransition: %s", error_codes[dwErrorCode],
1354 	         state_transitions[dwStateTransition]);
1355 #endif
1356 
1357 	if (dwErrorCode == STATUS_VALID_CLIENT)
1358 	{
1359 		license->state = LICENSE_STATE_COMPLETED;
1360 		return TRUE;
1361 	}
1362 
1363 	switch (dwStateTransition)
1364 	{
1365 		case ST_TOTAL_ABORT:
1366 			license->state = LICENSE_STATE_ABORTED;
1367 			break;
1368 		case ST_NO_TRANSITION:
1369 			license->state = LICENSE_STATE_COMPLETED;
1370 			break;
1371 		case ST_RESET_PHASE_TO_START:
1372 			license->state = LICENSE_STATE_AWAIT;
1373 			break;
1374 		case ST_RESEND_LAST_MESSAGE:
1375 			break;
1376 		default:
1377 			break;
1378 	}
1379 
1380 	return TRUE;
1381 }
1382 
1383 /**
1384  * Write a NEW_LICENSE_REQUEST packet.\n
1385  * @msdn{cc241918}
1386  * @param license license module
1387  * @param s stream
1388  */
1389 
license_write_new_license_request_packet(rdpLicense * license,wStream * s)1390 BOOL license_write_new_license_request_packet(rdpLicense* license, wStream* s)
1391 {
1392 	UINT32 PlatformId = PLATFORMID;
1393 	UINT32 PreferredKeyExchangeAlg = KEY_EXCHANGE_ALG_RSA;
1394 
1395 	Stream_Write_UINT32(s, PreferredKeyExchangeAlg); /* PreferredKeyExchangeAlg (4 bytes) */
1396 	Stream_Write_UINT32(s, PlatformId);              /* PlatformId (4 bytes) */
1397 	Stream_Write(s, license->ClientRandom, 32);      /* ClientRandom (32 bytes) */
1398 
1399 	if (/* EncryptedPremasterSecret */
1400 	    !license_write_encrypted_premaster_secret_blob(s, license->EncryptedPremasterSecret,
1401 	                                                   license->ModulusLength) ||
1402 	    /* ClientUserName */
1403 	    !license_write_binary_blob(s, license->ClientUserName) ||
1404 	    /* ClientMachineName */
1405 	    !license_write_binary_blob(s, license->ClientMachineName))
1406 	{
1407 		return FALSE;
1408 	}
1409 
1410 #ifdef WITH_DEBUG_LICENSE
1411 	WLog_DBG(TAG, "PreferredKeyExchangeAlg: 0x%08" PRIX32 "", PreferredKeyExchangeAlg);
1412 	WLog_DBG(TAG, "ClientRandom:");
1413 	winpr_HexDump(TAG, WLOG_DEBUG, license->ClientRandom, 32);
1414 	WLog_DBG(TAG, "EncryptedPremasterSecret");
1415 	winpr_HexDump(TAG, WLOG_DEBUG, license->EncryptedPremasterSecret->data,
1416 	              license->EncryptedPremasterSecret->length);
1417 	WLog_DBG(TAG, "ClientUserName (%" PRIu16 "): %s", license->ClientUserName->length,
1418 	         (char*)license->ClientUserName->data);
1419 	WLog_DBG(TAG, "ClientMachineName (%" PRIu16 "): %s", license->ClientMachineName->length,
1420 	         (char*)license->ClientMachineName->data);
1421 #endif
1422 	return TRUE;
1423 }
1424 
1425 /**
1426  * Send a NEW_LICENSE_REQUEST packet.\n
1427  * @msdn{cc241918}
1428  * @param license license module
1429  */
1430 
license_answer_license_request(rdpLicense * license)1431 BOOL license_answer_license_request(rdpLicense* license)
1432 {
1433 	wStream* s;
1434 	BYTE* license_data = NULL;
1435 	size_t license_size = 0;
1436 	BOOL status;
1437 	char* username;
1438 
1439 	if (!license->rdp->settings->OldLicenseBehaviour)
1440 		license_data = loadCalFile(license->rdp->settings, license->rdp->settings->ClientHostname,
1441 		                           &license_size);
1442 
1443 	if (license_data)
1444 	{
1445 		LICENSE_BLOB* calBlob = NULL;
1446 		BYTE signature[LICENSING_ENCRYPTION_KEY_LENGTH];
1447 
1448 		DEBUG_LICENSE("Sending Saved License Packet");
1449 
1450 		license->EncryptedHardwareId->type = BB_ENCRYPTED_DATA_BLOB;
1451 		if (!license_encrypt_and_MAC(license, license->HardwareId, HWID_LENGTH,
1452 		                             license->EncryptedHardwareId, signature))
1453 		{
1454 			free(license_data);
1455 			return FALSE;
1456 		}
1457 
1458 		calBlob = license_new_binary_blob(BB_DATA_BLOB);
1459 		if (!calBlob)
1460 		{
1461 			free(license_data);
1462 			return FALSE;
1463 		}
1464 		calBlob->data = license_data;
1465 		calBlob->length = license_size;
1466 
1467 		status = license_send_client_info(license, calBlob, signature);
1468 		license_free_binary_blob(calBlob);
1469 
1470 		return status;
1471 	}
1472 
1473 	DEBUG_LICENSE("Sending New License Packet");
1474 
1475 	s = license_send_stream_init(license);
1476 	if (!s)
1477 		return FALSE;
1478 	if (license->rdp->settings->Username != NULL)
1479 		username = license->rdp->settings->Username;
1480 	else
1481 		username = "username";
1482 
1483 	license->ClientUserName->data = (BYTE*)username;
1484 	license->ClientUserName->length = strlen(username) + 1;
1485 	license->ClientMachineName->data = (BYTE*)license->rdp->settings->ClientHostname;
1486 	license->ClientMachineName->length = strlen(license->rdp->settings->ClientHostname) + 1;
1487 
1488 	status = license_write_new_license_request_packet(license, s);
1489 
1490 	license->ClientUserName->data = NULL;
1491 	license->ClientUserName->length = 0;
1492 	license->ClientMachineName->data = NULL;
1493 	license->ClientMachineName->length = 0;
1494 
1495 	if (!status)
1496 	{
1497 		Stream_Release(s);
1498 		return FALSE;
1499 	}
1500 
1501 	return license_send(license, s, NEW_LICENSE_REQUEST);
1502 }
1503 
1504 /**
1505  * Write Client Challenge Response Packet.\n
1506  * @msdn{cc241922}
1507  * @param license license module
1508  * @param s stream
1509  * @param mac_data signature
1510  */
1511 
license_write_platform_challenge_response_packet(rdpLicense * license,wStream * s,const BYTE * macData)1512 BOOL license_write_platform_challenge_response_packet(rdpLicense* license, wStream* s,
1513                                                       const BYTE* macData)
1514 {
1515 	if (!license_write_binary_blob(
1516 	        s,
1517 	        license->EncryptedPlatformChallengeResponse) || /* EncryptedPlatformChallengeResponse */
1518 	    !license_write_binary_blob(s, license->EncryptedHardwareId) || /* EncryptedHWID */
1519 	    !Stream_EnsureRemainingCapacity(s, 16))
1520 	{
1521 		return FALSE;
1522 	}
1523 
1524 	Stream_Write(s, macData, 16); /* MACData */
1525 	return TRUE;
1526 }
1527 
1528 /**
1529  * Send Client Challenge Response Packet.\n
1530  * @msdn{cc241922}
1531  * @param license license module
1532  */
1533 
license_send_platform_challenge_response_packet(rdpLicense * license)1534 BOOL license_send_platform_challenge_response_packet(rdpLicense* license)
1535 {
1536 	wStream* s;
1537 	wStream* challengeRespData;
1538 	int length;
1539 	BYTE* buffer;
1540 	BYTE mac_data[16];
1541 	BOOL status;
1542 
1543 	DEBUG_LICENSE("Sending Platform Challenge Response Packet");
1544 	s = license_send_stream_init(license);
1545 	license->EncryptedPlatformChallenge->type = BB_DATA_BLOB;
1546 
1547 	/* prepare the PLATFORM_CHALLENGE_RESPONSE_DATA */
1548 	challengeRespData = Stream_New(NULL, 8 + license->PlatformChallenge->length);
1549 	if (!challengeRespData)
1550 		return FALSE;
1551 	Stream_Write_UINT16(challengeRespData, 0x0100);                        /* wVersion */
1552 	Stream_Write_UINT16(challengeRespData, OTHER_PLATFORM_CHALLENGE_TYPE); /* wClientType */
1553 	Stream_Write_UINT16(challengeRespData, LICENSE_DETAIL_DETAIL);         /* wLicenseDetailLevel */
1554 	Stream_Write_UINT16(challengeRespData, license->PlatformChallenge->length); /* cbChallenge */
1555 	Stream_Write(challengeRespData, license->PlatformChallenge->data,
1556 	             license->PlatformChallenge->length); /* pbChallenge */
1557 	Stream_SealLength(challengeRespData);
1558 
1559 	/* compute MAC of PLATFORM_CHALLENGE_RESPONSE_DATA + HWID */
1560 	length = Stream_Length(challengeRespData) + HWID_LENGTH;
1561 	buffer = (BYTE*)malloc(length);
1562 	if (!buffer)
1563 	{
1564 		Stream_Free(challengeRespData, TRUE);
1565 		return FALSE;
1566 	}
1567 
1568 	CopyMemory(buffer, Stream_Buffer(challengeRespData), Stream_Length(challengeRespData));
1569 	CopyMemory(&buffer[Stream_Length(challengeRespData)], license->HardwareId, HWID_LENGTH);
1570 	status = security_mac_data(license->MacSaltKey, buffer, length, mac_data);
1571 	free(buffer);
1572 
1573 	if (!status)
1574 	{
1575 		Stream_Free(challengeRespData, TRUE);
1576 		return FALSE;
1577 	}
1578 
1579 	license->EncryptedHardwareId->type = BB_ENCRYPTED_DATA_BLOB;
1580 	if (!license_rc4_with_licenseKey(license, license->HardwareId, HWID_LENGTH,
1581 	                                 license->EncryptedHardwareId))
1582 	{
1583 		Stream_Free(challengeRespData, TRUE);
1584 		return FALSE;
1585 	}
1586 
1587 	status = license_rc4_with_licenseKey(license, Stream_Buffer(challengeRespData),
1588 	                                     Stream_Length(challengeRespData),
1589 	                                     license->EncryptedPlatformChallengeResponse);
1590 	Stream_Free(challengeRespData, TRUE);
1591 	if (!status)
1592 		return FALSE;
1593 
1594 #ifdef WITH_DEBUG_LICENSE
1595 	WLog_DBG(TAG, "LicensingEncryptionKey:");
1596 	winpr_HexDump(TAG, WLOG_DEBUG, license->LicensingEncryptionKey, 16);
1597 	WLog_DBG(TAG, "HardwareId:");
1598 	winpr_HexDump(TAG, WLOG_DEBUG, license->HardwareId, HWID_LENGTH);
1599 	WLog_DBG(TAG, "EncryptedHardwareId:");
1600 	winpr_HexDump(TAG, WLOG_DEBUG, license->EncryptedHardwareId->data, HWID_LENGTH);
1601 #endif
1602 	if (license_write_platform_challenge_response_packet(license, s, mac_data))
1603 		return license_send(license, s, PLATFORM_CHALLENGE_RESPONSE);
1604 
1605 	Stream_Release(s);
1606 	return FALSE;
1607 }
1608 
1609 /**
1610  * Send Server License Error - Valid Client Packet.\n
1611  * @msdn{cc241922}
1612  * @param license license module
1613  */
1614 
license_send_valid_client_error_packet(rdpRdp * rdp)1615 BOOL license_send_valid_client_error_packet(rdpRdp* rdp)
1616 {
1617 	rdpLicense* license = rdp->license;
1618 	wStream* s = license_send_stream_init(license);
1619 	if (!s)
1620 		return FALSE;
1621 
1622 	DEBUG_LICENSE("Sending Error Alert Packet");
1623 	Stream_Write_UINT32(s, STATUS_VALID_CLIENT); /* dwErrorCode */
1624 	Stream_Write_UINT32(s, ST_NO_TRANSITION);    /* dwStateTransition */
1625 
1626 	if (license_write_binary_blob(s, license->ErrorInfo))
1627 		return license_send(license, s, ERROR_ALERT);
1628 
1629 	Stream_Release(s);
1630 	return FALSE;
1631 }
1632 
1633 /**
1634  * Instantiate new license module.
1635  * @param rdp RDP module
1636  * @return new license module
1637  */
1638 
license_new(rdpRdp * rdp)1639 rdpLicense* license_new(rdpRdp* rdp)
1640 {
1641 	rdpLicense* license;
1642 	license = (rdpLicense*)calloc(1, sizeof(rdpLicense));
1643 	if (!license)
1644 		return NULL;
1645 
1646 	license->rdp = rdp;
1647 	license->state = LICENSE_STATE_AWAIT;
1648 	if (!(license->certificate = certificate_new()))
1649 		goto out_error;
1650 	if (!(license->ProductInfo = license_new_product_info()))
1651 		goto out_error;
1652 	if (!(license->ErrorInfo = license_new_binary_blob(BB_ERROR_BLOB)))
1653 		goto out_error;
1654 	if (!(license->KeyExchangeList = license_new_binary_blob(BB_KEY_EXCHG_ALG_BLOB)))
1655 		goto out_error;
1656 	if (!(license->ServerCertificate = license_new_binary_blob(BB_CERTIFICATE_BLOB)))
1657 		goto out_error;
1658 	if (!(license->ClientUserName = license_new_binary_blob(BB_CLIENT_USER_NAME_BLOB)))
1659 		goto out_error;
1660 	if (!(license->ClientMachineName = license_new_binary_blob(BB_CLIENT_MACHINE_NAME_BLOB)))
1661 		goto out_error;
1662 	if (!(license->PlatformChallenge = license_new_binary_blob(BB_ANY_BLOB)))
1663 		goto out_error;
1664 	if (!(license->EncryptedPlatformChallenge = license_new_binary_blob(BB_ANY_BLOB)))
1665 		goto out_error;
1666 	if (!(license->EncryptedPlatformChallengeResponse =
1667 	          license_new_binary_blob(BB_ENCRYPTED_DATA_BLOB)))
1668 		goto out_error;
1669 	if (!(license->EncryptedPremasterSecret = license_new_binary_blob(BB_ANY_BLOB)))
1670 		goto out_error;
1671 	if (!(license->EncryptedHardwareId = license_new_binary_blob(BB_ENCRYPTED_DATA_BLOB)))
1672 		goto out_error;
1673 	if (!(license->ScopeList = license_new_scope_list()))
1674 		goto out_error;
1675 
1676 	license_generate_randoms(license);
1677 
1678 	return license;
1679 
1680 out_error:
1681 	license_free(license);
1682 	return NULL;
1683 }
1684 
1685 /**
1686  * Free license module.
1687  * @param license license module to be freed
1688  */
1689 
license_free(rdpLicense * license)1690 void license_free(rdpLicense* license)
1691 {
1692 	if (license)
1693 	{
1694 		free(license->Modulus);
1695 		certificate_free(license->certificate);
1696 		license_free_product_info(license->ProductInfo);
1697 		license_free_binary_blob(license->ErrorInfo);
1698 		license_free_binary_blob(license->KeyExchangeList);
1699 		license_free_binary_blob(license->ServerCertificate);
1700 		license_free_binary_blob(license->ClientUserName);
1701 		license_free_binary_blob(license->ClientMachineName);
1702 		license_free_binary_blob(license->PlatformChallenge);
1703 		license_free_binary_blob(license->EncryptedPlatformChallenge);
1704 		license_free_binary_blob(license->EncryptedPlatformChallengeResponse);
1705 		license_free_binary_blob(license->EncryptedPremasterSecret);
1706 		license_free_binary_blob(license->EncryptedHardwareId);
1707 		license_free_scope_list(license->ScopeList);
1708 		free(license);
1709 	}
1710 }
1711