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