Coverage Report

Created: 2024-05-20 06:11

/src/FreeRDP/libfreerdp/core/license.c
Line
Count
Source (jump to first uncovered line)
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
 * Copyright 2022,2023 Armin Novak <armin.novak@thincast.com>
9
 * Copyright 2022,2023 Thincast Technologies GmbH
10
 *
11
 * Licensed under the Apache License, Version 2.0 (the "License");
12
 * you may not use this file except in compliance with the License.
13
 * You may obtain a copy of the License at
14
 *
15
 *     http://www.apache.org/licenses/LICENSE-2.0
16
 *
17
 * Unless required by applicable law or agreed to in writing, software
18
 * distributed under the License is distributed on an "AS IS" BASIS,
19
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
 * See the License for the specific language governing permissions and
21
 * limitations under the License.
22
 */
23
24
#include <freerdp/config.h>
25
26
#include "settings.h"
27
28
#include <freerdp/license.h>
29
30
#include <winpr/crt.h>
31
#include <winpr/assert.h>
32
#include <winpr/crypto.h>
33
#include <winpr/shell.h>
34
#include <winpr/path.h>
35
#include <winpr/file.h>
36
37
#include <freerdp/log.h>
38
39
#include <freerdp/crypto/certificate.h>
40
41
#include "license.h"
42
43
#include "../crypto/crypto.h"
44
#include "../crypto/certificate.h"
45
46
0
#define TAG FREERDP_TAG("core.license")
47
48
#if 0
49
#define LICENSE_NULL_CLIENT_RANDOM 1
50
#define LICENSE_NULL_PREMASTER_SECRET 1
51
#endif
52
53
0
#define PLATFORM_CHALLENGE_RESPONSE_VERSION 0x0100
54
55
/** @brief Licensing Packet Types */
56
enum LicenseRequestType
57
{
58
  LICENSE_REQUEST = 0x01,
59
  PLATFORM_CHALLENGE = 0x02,
60
  NEW_LICENSE = 0x03,
61
  UPGRADE_LICENSE = 0x04,
62
  LICENSE_INFO = 0x12,
63
  NEW_LICENSE_REQUEST = 0x13,
64
  PLATFORM_CHALLENGE_RESPONSE = 0x15,
65
  ERROR_ALERT = 0xFF
66
};
67
68
#define LICENSE_PKT_CS_MASK \
69
  (LICENSE_INFO | NEW_LICENSE_REQUEST | PLATFORM_CHALLENGE_RESPONSE | ERROR_ALERT)
70
#define LICENSE_PKT_SC_MASK \
71
  (LICENSE_REQUEST | PLATFORM_CHALLENGE | NEW_LICENSE | UPGRADE_LICENSE | ERROR_ALERT)
72
#define LICENSE_PKT_MASK (LICENSE_PKT_CS_MASK | LICENSE_PKT_SC_MASK)
73
74
#define LICENSE_PREAMBLE_LENGTH 4
75
76
/* Cryptographic Lengths */
77
78
#define SERVER_RANDOM_LENGTH 32
79
#define MASTER_SECRET_LENGTH 48
80
#define PREMASTER_SECRET_LENGTH 48
81
#define SESSION_KEY_BLOB_LENGTH 48
82
#define MAC_SALT_KEY_LENGTH 16
83
#define LICENSING_ENCRYPTION_KEY_LENGTH 16
84
0
#define HWID_PLATFORM_ID_LENGTH 4
85
#define HWID_UNIQUE_DATA_LENGTH 16
86
#define HWID_LENGTH 20
87
#define LICENSING_PADDING_SIZE 8
88
89
/* Preamble Flags */
90
91
#define PREAMBLE_VERSION_2_0 0x02
92
0
#define PREAMBLE_VERSION_3_0 0x03
93
#define LicenseProtocolVersionMask 0x0F
94
0
#define EXTENDED_ERROR_MSG_SUPPORTED 0x80
95
96
/** @brief binary Blob Types */
97
enum
98
{
99
  BB_ANY_BLOB = 0x0000,
100
  BB_DATA_BLOB = 0x0001,
101
  BB_RANDOM_BLOB = 0x0002,
102
  BB_CERTIFICATE_BLOB = 0x0003,
103
  BB_ERROR_BLOB = 0x0004,
104
  BB_ENCRYPTED_DATA_BLOB = 0x0009,
105
  BB_KEY_EXCHG_ALG_BLOB = 0x000D,
106
  BB_SCOPE_BLOB = 0x000E,
107
  BB_CLIENT_USER_NAME_BLOB = 0x000F,
108
  BB_CLIENT_MACHINE_NAME_BLOB = 0x0010
109
};
110
111
/* License Key Exchange Algorithms */
112
113
14.9k
#define KEY_EXCHANGE_ALG_RSA 0x00000001
114
115
/** @brief license Error Codes
116
 */
117
enum
118
{
119
  ERR_INVALID_SERVER_CERTIFICATE = 0x00000001,
120
  ERR_NO_LICENSE = 0x00000002,
121
  ERR_INVALID_MAC = 0x00000003,
122
  ERR_INVALID_SCOPE = 0x00000004,
123
  ERR_NO_LICENSE_SERVER = 0x00000006,
124
  STATUS_VALID_CLIENT = 0x00000007,
125
  ERR_INVALID_CLIENT = 0x00000008,
126
  ERR_INVALID_PRODUCT_ID = 0x0000000B,
127
  ERR_INVALID_MESSAGE_LENGTH = 0x0000000C
128
};
129
130
/** @brief state Transition Codes
131
 */
132
enum
133
{
134
  ST_TOTAL_ABORT = 0x00000001,
135
  ST_NO_TRANSITION = 0x00000002,
136
  ST_RESET_PHASE_TO_START = 0x00000003,
137
  ST_RESEND_LAST_MESSAGE = 0x00000004
138
};
139
140
/** @brief Platform Challenge Types
141
 */
142
enum
143
{
144
  WIN32_PLATFORM_CHALLENGE_TYPE = 0x0100,
145
  WIN16_PLATFORM_CHALLENGE_TYPE = 0x0200,
146
  WINCE_PLATFORM_CHALLENGE_TYPE = 0x0300,
147
  OTHER_PLATFORM_CHALLENGE_TYPE = 0xFF00
148
};
149
150
/** @brief License Detail Levels
151
 */
152
enum
153
{
154
  LICENSE_DETAIL_SIMPLE = 0x0001,
155
  LICENSE_DETAIL_MODERATE = 0x0002,
156
  LICENSE_DETAIL_DETAIL = 0x0003
157
};
158
159
/*
160
 * PlatformId:
161
 *
162
 * The most significant byte of the PlatformId field contains the operating system version of the
163
 * client. The second most significant byte of the PlatformId field identifies the ISV that provided
164
 * the client image. The remaining two bytes in the PlatformId field are used by the ISV to identify
165
 * the build number of the operating system.
166
 *
167
 * 0x04010000:
168
 *
169
 * CLIENT_OS_ID_WINNT_POST_52 (0x04000000)
170
 * CLIENT_IMAGE_ID_MICROSOFT  (0x00010000)
171
 */
172
enum
173
{
174
  CLIENT_OS_ID_WINNT_351 = 0x01000000,
175
  CLIENT_OS_ID_WINNT_40 = 0x02000000,
176
  CLIENT_OS_ID_WINNT_50 = 0x03000000,
177
  CLIENT_OS_ID_WINNT_POST_52 = 0x04000000,
178
179
  CLIENT_IMAGE_ID_MICROSOFT = 0x00010000,
180
  CLIENT_IMAGE_ID_CITRIX = 0x00020000,
181
};
182
183
struct rdp_license
184
{
185
  LICENSE_STATE state;
186
  LICENSE_TYPE type;
187
  rdpRdp* rdp;
188
  rdpCertificate* certificate;
189
  BYTE HardwareId[HWID_LENGTH];
190
  BYTE ClientRandom[CLIENT_RANDOM_LENGTH];
191
  BYTE ServerRandom[SERVER_RANDOM_LENGTH];
192
  BYTE MasterSecret[MASTER_SECRET_LENGTH];
193
  BYTE PremasterSecret[PREMASTER_SECRET_LENGTH];
194
  BYTE SessionKeyBlob[SESSION_KEY_BLOB_LENGTH];
195
  BYTE MacSaltKey[MAC_SALT_KEY_LENGTH];
196
  BYTE LicensingEncryptionKey[LICENSING_ENCRYPTION_KEY_LENGTH];
197
  LICENSE_PRODUCT_INFO* ProductInfo;
198
  LICENSE_BLOB* ErrorInfo;
199
  LICENSE_BLOB* LicenseInfo; /* Client -> Server */
200
  LICENSE_BLOB* KeyExchangeList;
201
  LICENSE_BLOB* ServerCertificate;
202
  LICENSE_BLOB* ClientUserName;
203
  LICENSE_BLOB* ClientMachineName;
204
  LICENSE_BLOB* PlatformChallenge;
205
  LICENSE_BLOB* EncryptedPremasterSecret;
206
  LICENSE_BLOB* EncryptedPlatformChallenge;
207
  LICENSE_BLOB* EncryptedPlatformChallengeResponse;
208
  LICENSE_BLOB* EncryptedHardwareId;
209
  LICENSE_BLOB* EncryptedLicenseInfo;
210
  BYTE MACData[LICENSING_ENCRYPTION_KEY_LENGTH];
211
  SCOPE_LIST* ScopeList;
212
  UINT32 PacketHeaderLength;
213
  UINT32 PreferredKeyExchangeAlg;
214
  UINT32 PlatformId;
215
  UINT16 ClientType;
216
  UINT16 LicenseDetailLevel;
217
  BOOL update;
218
};
219
220
static BOOL license_send_error_alert(rdpLicense* license, UINT32 dwErrorCode,
221
                                     UINT32 dwStateTransition, const LICENSE_BLOB* info);
222
static BOOL license_set_state(rdpLicense* license, LICENSE_STATE state);
223
static const char* license_get_state_string(LICENSE_STATE state);
224
225
static const char* license_preferred_key_exchange_alg_string(UINT32 alg, char* buffer, size_t size)
226
0
{
227
0
  const char* name = NULL;
228
229
0
  switch (alg)
230
0
  {
231
0
    case KEY_EXCHANGE_ALG_RSA:
232
0
      name = "KEY_EXCHANGE_ALG_RSA";
233
0
      break;
234
0
    default:
235
0
      name = "KEY_EXCHANGE_ALG_UNKNOWN";
236
0
      break;
237
0
  }
238
239
0
  _snprintf(buffer, size, "%s [0x%08" PRIx32 "]", name, alg);
240
0
  return buffer;
241
0
}
242
243
static const char* license_request_type_string(UINT32 type)
244
0
{
245
0
  switch (type)
246
0
  {
247
0
    case LICENSE_REQUEST:
248
0
      return "LICENSE_REQUEST";
249
0
    case PLATFORM_CHALLENGE:
250
0
      return "PLATFORM_CHALLENGE";
251
0
    case NEW_LICENSE:
252
0
      return "NEW_LICENSE";
253
0
    case UPGRADE_LICENSE:
254
0
      return "UPGRADE_LICENSE";
255
0
    case LICENSE_INFO:
256
0
      return "LICENSE_INFO";
257
0
    case NEW_LICENSE_REQUEST:
258
0
      return "NEW_LICENSE_REQUEST";
259
0
    case PLATFORM_CHALLENGE_RESPONSE:
260
0
      return "PLATFORM_CHALLENGE_RESPONSE";
261
0
    case ERROR_ALERT:
262
0
      return "ERROR_ALERT";
263
0
    default:
264
0
      return "LICENSE_REQUEST_TYPE_UNKNOWN";
265
0
  }
266
0
}
267
268
static const char* licencse_blob_type_string(UINT16 type)
269
0
{
270
0
  switch (type)
271
0
  {
272
0
    case BB_ANY_BLOB:
273
0
      return "BB_ANY_BLOB";
274
0
    case BB_DATA_BLOB:
275
0
      return "BB_DATA_BLOB";
276
0
    case BB_RANDOM_BLOB:
277
0
      return "BB_RANDOM_BLOB";
278
0
    case BB_CERTIFICATE_BLOB:
279
0
      return "BB_CERTIFICATE_BLOB";
280
0
    case BB_ERROR_BLOB:
281
0
      return "BB_ERROR_BLOB";
282
0
    case BB_ENCRYPTED_DATA_BLOB:
283
0
      return "BB_ENCRYPTED_DATA_BLOB";
284
0
    case BB_KEY_EXCHG_ALG_BLOB:
285
0
      return "BB_KEY_EXCHG_ALG_BLOB";
286
0
    case BB_SCOPE_BLOB:
287
0
      return "BB_SCOPE_BLOB";
288
0
    case BB_CLIENT_USER_NAME_BLOB:
289
0
      return "BB_CLIENT_USER_NAME_BLOB";
290
0
    case BB_CLIENT_MACHINE_NAME_BLOB:
291
0
      return "BB_CLIENT_MACHINE_NAME_BLOB";
292
0
    default:
293
0
      return "BB_UNKNOWN";
294
0
  }
295
0
}
296
static wStream* license_send_stream_init(rdpLicense* license);
297
298
static void license_generate_randoms(rdpLicense* license);
299
static BOOL license_generate_keys(rdpLicense* license);
300
static BOOL license_generate_hwid(rdpLicense* license);
301
static BOOL license_encrypt_premaster_secret(rdpLicense* license);
302
303
static LICENSE_PRODUCT_INFO* license_new_product_info(void);
304
static void license_free_product_info(LICENSE_PRODUCT_INFO* productInfo);
305
static BOOL license_read_product_info(wStream* s, LICENSE_PRODUCT_INFO* productInfo);
306
307
static LICENSE_BLOB* license_new_binary_blob(UINT16 type);
308
static void license_free_binary_blob(LICENSE_BLOB* blob);
309
static BOOL license_read_binary_blob_data(LICENSE_BLOB* blob, UINT16 type, const void* data,
310
                                          size_t length);
311
static BOOL license_read_binary_blob(wStream* s, LICENSE_BLOB* blob);
312
static BOOL license_write_binary_blob(wStream* s, const LICENSE_BLOB* blob);
313
314
static SCOPE_LIST* license_new_scope_list(void);
315
static BOOL license_scope_list_resize(SCOPE_LIST* scopeList, UINT32 count);
316
static void license_free_scope_list(SCOPE_LIST* scopeList);
317
static BOOL license_read_scope_list(wStream* s, SCOPE_LIST* scopeList);
318
static BOOL license_write_scope_list(wStream* s, const SCOPE_LIST* scopeList);
319
320
static BOOL license_read_license_request_packet(rdpLicense* license, wStream* s);
321
static BOOL license_write_license_request_packet(const rdpLicense* license, wStream* s);
322
323
static BOOL license_read_platform_challenge_packet(rdpLicense* license, wStream* s);
324
static BOOL license_send_platform_challenge_packet(rdpLicense* license);
325
static BOOL license_read_new_or_upgrade_license_packet(rdpLicense* license, wStream* s);
326
static BOOL license_read_error_alert_packet(rdpLicense* license, wStream* s);
327
328
static BOOL license_write_new_license_request_packet(const rdpLicense* license, wStream* s);
329
static BOOL license_read_new_license_request_packet(rdpLicense* license, wStream* s);
330
static BOOL license_answer_license_request(rdpLicense* license);
331
332
static BOOL license_send_platform_challenge_response(rdpLicense* license);
333
static BOOL license_read_platform_challenge_response(rdpLicense* license, wStream* s);
334
335
static BOOL license_read_client_platform_challenge_response(rdpLicense* license, wStream* s);
336
static BOOL license_write_client_platform_challenge_response(rdpLicense* license, wStream* s);
337
338
static BOOL license_read_server_upgrade_license(rdpLicense* license, wStream* s);
339
static BOOL license_write_server_upgrade_license(const rdpLicense* license, wStream* s);
340
341
static BOOL license_send_license_info(rdpLicense* license, const LICENSE_BLOB* calBlob,
342
                                      const BYTE* signature, size_t signature_length);
343
static BOOL license_read_license_info(rdpLicense* license, wStream* s);
344
static state_run_t license_client_recv(rdpLicense* license, wStream* s);
345
static state_run_t license_server_recv(rdpLicense* license, wStream* s);
346
347
14.9k
#define PLATFORMID (CLIENT_OS_ID_WINNT_POST_52 | CLIENT_IMAGE_ID_MICROSOFT)
348
349
#ifdef WITH_DEBUG_LICENSE
350
351
static const char* const error_codes[] = { "ERR_UNKNOWN",
352
                                         "ERR_INVALID_SERVER_CERTIFICATE",
353
                                         "ERR_NO_LICENSE",
354
                                         "ERR_INVALID_MAC",
355
                                         "ERR_INVALID_SCOPE",
356
                                         "ERR_UNKNOWN",
357
                                         "ERR_NO_LICENSE_SERVER",
358
                                         "STATUS_VALID_CLIENT",
359
                                         "ERR_INVALID_CLIENT",
360
                                         "ERR_UNKNOWN",
361
                                         "ERR_UNKNOWN",
362
                                         "ERR_INVALID_PRODUCT_ID",
363
                                         "ERR_INVALID_MESSAGE_LENGTH" };
364
365
static const char* const state_transitions[] = { "ST_UNKNOWN", "ST_TOTAL_ABORT", "ST_NO_TRANSITION",
366
                                               "ST_RESET_PHASE_TO_START",
367
                                               "ST_RESEND_LAST_MESSAGE" };
368
369
static void license_print_product_info(const LICENSE_PRODUCT_INFO* productInfo)
370
{
371
  char* CompanyName = NULL;
372
  char* ProductId = NULL;
373
374
  WINPR_ASSERT(productInfo);
375
  WINPR_ASSERT(productInfo->pbCompanyName);
376
  WINPR_ASSERT(productInfo->pbProductId);
377
378
  CompanyName = ConvertWCharNToUtf8Alloc((const WCHAR*)productInfo->pbCompanyName,
379
                                         productInfo->cbCompanyName / sizeof(WCHAR), NULL);
380
  ProductId = ConvertWCharNToUtf8Alloc((const WCHAR*)productInfo->pbProductId,
381
                                       productInfo->cbProductId / sizeof(WCHAR), NULL);
382
  WLog_INFO(TAG, "ProductInfo:");
383
  WLog_INFO(TAG, "\tdwVersion: 0x%08" PRIX32 "", productInfo->dwVersion);
384
  WLog_INFO(TAG, "\tCompanyName: %s", CompanyName);
385
  WLog_INFO(TAG, "\tProductId: %s", ProductId);
386
  free(CompanyName);
387
  free(ProductId);
388
}
389
390
static void license_print_scope_list(const SCOPE_LIST* scopeList)
391
{
392
  WINPR_ASSERT(scopeList);
393
394
  WLog_INFO(TAG, "ScopeList (%" PRIu32 "):", scopeList->count);
395
396
  for (UINT32 index = 0; index < scopeList->count; index++)
397
  {
398
    const LICENSE_BLOB* scope = NULL;
399
400
    WINPR_ASSERT(scopeList->array);
401
    scope = scopeList->array[index];
402
    WINPR_ASSERT(scope);
403
404
    WLog_INFO(TAG, "\t%s", (const char*)scope->data);
405
  }
406
}
407
#endif
408
409
static const char licenseStore[] = "licenses";
410
411
static BOOL license_ensure_state(rdpLicense* license, LICENSE_STATE state, UINT32 msg)
412
0
{
413
0
  const LICENSE_STATE cstate = license_get_state(license);
414
415
0
  WINPR_ASSERT(license);
416
417
0
  if (cstate != state)
418
0
  {
419
0
    const char* scstate = license_get_state_string(cstate);
420
0
    const char* sstate = license_get_state_string(state);
421
0
    const char* where = license_request_type_string(msg);
422
423
0
    WLog_WARN(TAG, "Received [%s], but found invalid licensing state %s, expected %s", where,
424
0
              scstate, sstate);
425
0
    return FALSE;
426
0
  }
427
0
  return TRUE;
428
0
}
429
430
state_run_t license_recv(rdpLicense* license, wStream* s)
431
0
{
432
0
  WINPR_ASSERT(license);
433
0
  WINPR_ASSERT(license->rdp);
434
0
  WINPR_ASSERT(license->rdp->settings);
435
436
0
  if (freerdp_settings_get_bool(license->rdp->settings, FreeRDP_ServerMode))
437
0
    return license_server_recv(license, s);
438
0
  else
439
0
    return license_client_recv(license, s);
440
0
}
441
442
static BOOL license_check_stream_length(wStream* s, SSIZE_T expect, const char* where)
443
0
{
444
0
  const size_t remain = Stream_GetRemainingLength(s);
445
446
0
  WINPR_ASSERT(where);
447
448
0
  if (expect < 0)
449
0
  {
450
0
    WLog_WARN(TAG, "invalid %s, expected value %" PRIdz " invalid", where, expect);
451
0
    return FALSE;
452
0
  }
453
0
  if (remain < (size_t)expect)
454
0
  {
455
0
    WLog_WARN(TAG, "short %s, expected %" PRIdz " bytes, got %" PRIuz, where, expect, remain);
456
0
    return FALSE;
457
0
  }
458
0
  return TRUE;
459
0
}
460
461
static BOOL license_check_stream_capacity(wStream* s, size_t expect, const char* where)
462
0
{
463
0
  WINPR_ASSERT(where);
464
465
0
  if (!Stream_CheckAndLogRequiredCapacityEx(TAG, WLOG_WARN, s, expect, 1, "%s(%s:%" PRIuz ") %s",
466
0
                                            __func__, __FILE__, (size_t)__LINE__, where))
467
0
    return FALSE;
468
469
0
  return TRUE;
470
0
}
471
472
static BOOL computeCalHash(const char* hostname, char* hashStr, size_t len)
473
0
{
474
0
  WINPR_DIGEST_CTX* sha1 = NULL;
475
0
  BOOL ret = FALSE;
476
0
  BYTE hash[20] = { 0 };
477
478
0
  WINPR_ASSERT(hostname);
479
0
  WINPR_ASSERT(hashStr);
480
481
0
  if (len < 2 * sizeof(hash) + 1)
482
0
    return FALSE;
483
484
0
  if (!(sha1 = winpr_Digest_New()))
485
0
    goto out;
486
0
  if (!winpr_Digest_Init(sha1, WINPR_MD_SHA1))
487
0
    goto out;
488
0
  if (!winpr_Digest_Update(sha1, (const BYTE*)hostname, strlen(hostname)))
489
0
    goto out;
490
0
  if (!winpr_Digest_Final(sha1, hash, sizeof(hash)))
491
0
    goto out;
492
493
0
  for (size_t i = 0; i < sizeof(hash); i++, hashStr += 2)
494
0
    sprintf_s(hashStr, 3, "%.2x", hash[i]);
495
496
0
  ret = TRUE;
497
0
out:
498
0
  if (!ret)
499
0
    WLog_ERR(TAG, "failed to generate SHA1 of hostname '%s'", hostname);
500
0
  winpr_Digest_Free(sha1);
501
0
  return ret;
502
0
}
503
504
static BOOL saveCal(const rdpSettings* settings, const BYTE* data, size_t length,
505
                    const char* hostname)
506
0
{
507
0
  char hash[41] = { 0 };
508
0
  FILE* fp = NULL;
509
0
  char* licenseStorePath = NULL;
510
0
  char filename[MAX_PATH] = { 0 };
511
0
  char filenameNew[MAX_PATH] = { 0 };
512
0
  char* filepath = NULL;
513
0
  char* filepathNew = NULL;
514
515
0
  size_t written = 0;
516
0
  BOOL ret = FALSE;
517
0
  const char* path = freerdp_settings_get_string(settings, FreeRDP_ConfigPath);
518
519
0
  WINPR_ASSERT(path);
520
0
  WINPR_ASSERT(data || (length == 0));
521
0
  WINPR_ASSERT(hostname);
522
523
0
  if (!winpr_PathFileExists(path))
524
0
  {
525
0
    if (!winpr_PathMakePath(path, 0))
526
0
    {
527
0
      WLog_ERR(TAG, "error creating directory '%s'", path);
528
0
      goto out;
529
0
    }
530
0
    WLog_INFO(TAG, "creating directory %s", path);
531
0
  }
532
533
0
  if (!(licenseStorePath = GetCombinedPath(path, licenseStore)))
534
0
  {
535
0
    WLog_ERR(TAG, "Failed to get license store path from '%s' + '%s'", path, licenseStore);
536
0
    goto out;
537
0
  }
538
539
0
  if (!winpr_PathFileExists(licenseStorePath))
540
0
  {
541
0
    if (!winpr_PathMakePath(licenseStorePath, 0))
542
0
    {
543
0
      WLog_ERR(TAG, "error creating directory '%s'", licenseStorePath);
544
0
      goto out;
545
0
    }
546
0
    WLog_INFO(TAG, "creating directory %s", licenseStorePath);
547
0
  }
548
549
0
  if (!computeCalHash(hostname, hash, sizeof(hash)))
550
0
    goto out;
551
0
  sprintf_s(filename, sizeof(filename) - 1, "%s.cal", hash);
552
0
  sprintf_s(filenameNew, sizeof(filenameNew) - 1, "%s.cal.new", hash);
553
554
0
  if (!(filepath = GetCombinedPath(licenseStorePath, filename)))
555
0
  {
556
0
    WLog_ERR(TAG, "Failed to get license file path from '%s' + '%s'", path, filename);
557
0
    goto out;
558
0
  }
559
560
0
  if (!(filepathNew = GetCombinedPath(licenseStorePath, filenameNew)))
561
0
  {
562
0
    WLog_ERR(TAG, "Failed to get license new file path from '%s' + '%s'", path, filenameNew);
563
0
    goto out;
564
0
  }
565
566
0
  fp = winpr_fopen(filepathNew, "wb");
567
0
  if (!fp)
568
0
  {
569
0
    WLog_ERR(TAG, "Failed to open license file '%s'", filepathNew);
570
0
    goto out;
571
0
  }
572
573
0
  written = fwrite(data, length, 1, fp);
574
0
  fclose(fp);
575
576
0
  if (written != 1)
577
0
  {
578
0
    WLog_ERR(TAG, "Failed to write to license file '%s'", filepathNew);
579
0
    winpr_DeleteFile(filepathNew);
580
0
    goto out;
581
0
  }
582
583
0
  ret = winpr_MoveFileEx(filepathNew, filepath, MOVEFILE_REPLACE_EXISTING);
584
0
  if (!ret)
585
0
    WLog_ERR(TAG, "Failed to move license file '%s' to '%s'", filepathNew, filepath);
586
587
0
out:
588
0
  free(filepathNew);
589
0
  free(filepath);
590
0
  free(licenseStorePath);
591
0
  return ret;
592
0
}
593
594
static BYTE* loadCalFile(const rdpSettings* settings, const char* hostname, size_t* dataLen)
595
0
{
596
0
  char* licenseStorePath = NULL;
597
0
  char* calPath = NULL;
598
0
  char calFilename[MAX_PATH] = { 0 };
599
0
  char hash[41] = { 0 };
600
0
  INT64 length = 0;
601
0
  size_t status = 0;
602
0
  FILE* fp = NULL;
603
0
  BYTE* ret = NULL;
604
605
0
  WINPR_ASSERT(settings);
606
0
  WINPR_ASSERT(hostname);
607
0
  WINPR_ASSERT(dataLen);
608
609
0
  if (!computeCalHash(hostname, hash, sizeof(hash)))
610
0
  {
611
0
    WLog_ERR(TAG, "loadCalFile: unable to compute hostname hash");
612
0
    return NULL;
613
0
  }
614
615
0
  sprintf_s(calFilename, sizeof(calFilename) - 1, "%s.cal", hash);
616
617
0
  if (!(licenseStorePath = GetCombinedPath(
618
0
            freerdp_settings_get_string(settings, FreeRDP_ConfigPath), licenseStore)))
619
0
    return NULL;
620
621
0
  if (!(calPath = GetCombinedPath(licenseStorePath, calFilename)))
622
0
    goto error_path;
623
624
0
  fp = winpr_fopen(calPath, "rb");
625
0
  if (!fp)
626
0
    goto error_open;
627
628
0
  _fseeki64(fp, 0, SEEK_END);
629
0
  length = _ftelli64(fp);
630
0
  _fseeki64(fp, 0, SEEK_SET);
631
0
  if (length < 0)
632
0
    goto error_malloc;
633
634
0
  ret = (BYTE*)malloc((size_t)length);
635
0
  if (!ret)
636
0
    goto error_malloc;
637
638
0
  status = fread(ret, (size_t)length, 1, fp);
639
0
  if (status == 0)
640
0
    goto error_read;
641
642
0
  *dataLen = (size_t)length;
643
644
0
  fclose(fp);
645
0
  free(calPath);
646
0
  free(licenseStorePath);
647
0
  return ret;
648
649
0
error_read:
650
0
  free(ret);
651
0
error_malloc:
652
0
  fclose(fp);
653
0
error_open:
654
0
  free(calPath);
655
0
error_path:
656
0
  free(licenseStorePath);
657
0
  return NULL;
658
0
}
659
660
/**
661
 * Read a licensing preamble.
662
 * msdn{cc240480}
663
 * @param s stream
664
 * @param bMsgType license message type
665
 * @param flags message flags
666
 * @param wMsgSize message size
667
 * @return if the operation completed successfully
668
 */
669
670
static BOOL license_read_preamble(wStream* s, BYTE* bMsgType, BYTE* flags, UINT16* wMsgSize)
671
0
{
672
0
  WINPR_ASSERT(bMsgType);
673
0
  WINPR_ASSERT(flags);
674
0
  WINPR_ASSERT(wMsgSize);
675
676
  /* preamble (4 bytes) */
677
0
  if (!license_check_stream_length(s, 4, "license preamble"))
678
0
    return FALSE;
679
680
0
  Stream_Read_UINT8(s, *bMsgType);  /* bMsgType (1 byte) */
681
0
  Stream_Read_UINT8(s, *flags);     /* flags (1 byte) */
682
0
  Stream_Read_UINT16(s, *wMsgSize); /* wMsgSize (2 bytes) */
683
0
  return license_check_stream_length(s, *wMsgSize - 4ll, "license preamble::wMsgSize");
684
0
}
685
686
/**
687
 * Write a licensing preamble.
688
 * msdn{cc240480}
689
 * @param s stream
690
 * @param bMsgType license message type
691
 * @param flags message flags
692
 * @param wMsgSize message size
693
 * @return if the operation completed successfully
694
 */
695
696
static BOOL license_write_preamble(wStream* s, BYTE bMsgType, BYTE flags, UINT16 wMsgSize)
697
0
{
698
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
699
0
    return FALSE;
700
701
  /* preamble (4 bytes) */
702
0
  Stream_Write_UINT8(s, bMsgType);  /* bMsgType (1 byte) */
703
0
  Stream_Write_UINT8(s, flags);     /* flags (1 byte) */
704
0
  Stream_Write_UINT16(s, wMsgSize); /* wMsgSize (2 bytes) */
705
0
  return TRUE;
706
0
}
707
708
/**
709
 * @brief Initialize a license packet stream.
710
 *
711
 * @param license license module
712
 *
713
 * @return stream or NULL
714
 */
715
716
wStream* license_send_stream_init(rdpLicense* license)
717
0
{
718
0
  WINPR_ASSERT(license);
719
0
  WINPR_ASSERT(license->rdp);
720
721
0
  const BOOL do_crypt = license->rdp->do_crypt;
722
723
0
  license->rdp->sec_flags = SEC_LICENSE_PKT;
724
725
  /*
726
   * Encryption of licensing packets is optional even if the rdp security
727
   * layer is used. If the peer has not indicated that it is capable of
728
   * processing encrypted licensing packets (rdp->do_crypt_license) we turn
729
   * off encryption (via rdp->do_crypt) before initializing the rdp stream
730
   * and reenable it afterwards.
731
   */
732
733
0
  if (do_crypt)
734
0
  {
735
0
    license->rdp->sec_flags |= SEC_LICENSE_ENCRYPT_CS;
736
0
    license->rdp->do_crypt = license->rdp->do_crypt_license;
737
0
  }
738
739
0
  wStream* s = rdp_send_stream_init(license->rdp);
740
0
  if (!s)
741
0
    return NULL;
742
743
0
  license->rdp->do_crypt = do_crypt;
744
0
  license->PacketHeaderLength = (UINT16)Stream_GetPosition(s);
745
0
  if (!Stream_SafeSeek(s, LICENSE_PREAMBLE_LENGTH))
746
0
    goto fail;
747
0
  return s;
748
749
0
fail:
750
0
  Stream_Release(s);
751
0
  return NULL;
752
0
}
753
754
/**
755
 * Send an RDP licensing packet.
756
 * msdn{cc240479}
757
 * @param license license module
758
 * @param s stream
759
 */
760
761
static BOOL license_send(rdpLicense* license, wStream* s, BYTE type)
762
0
{
763
0
  WINPR_ASSERT(license);
764
0
  WINPR_ASSERT(license->rdp);
765
766
0
  rdpRdp* rdp = license->rdp;
767
0
  WINPR_ASSERT(rdp->settings);
768
769
0
  DEBUG_LICENSE("Sending %s Packet", license_request_type_string(type));
770
0
  const size_t length = Stream_GetPosition(s);
771
0
  WINPR_ASSERT(length >= license->PacketHeaderLength);
772
0
  WINPR_ASSERT(length <= UINT16_MAX + license->PacketHeaderLength);
773
774
0
  const UINT16 wMsgSize = (UINT16)(length - license->PacketHeaderLength);
775
0
  Stream_SetPosition(s, license->PacketHeaderLength);
776
0
  BYTE flags = PREAMBLE_VERSION_3_0;
777
778
  /**
779
   * Using EXTENDED_ERROR_MSG_SUPPORTED here would cause mstsc to crash when
780
   * running in server mode! This flag seems to be incorrectly documented.
781
   */
782
783
0
  if (!rdp->settings->ServerMode)
784
0
    flags |= EXTENDED_ERROR_MSG_SUPPORTED;
785
786
0
  if (!license_write_preamble(s, type, flags, wMsgSize))
787
0
    return FALSE;
788
789
#ifdef WITH_DEBUG_LICENSE
790
  WLog_DBG(TAG, "Sending %s Packet, length %" PRIu16 "", license_request_type_string(type),
791
           wMsgSize);
792
  winpr_HexDump(TAG, WLOG_DEBUG, Stream_PointerAs(s, char) - LICENSE_PREAMBLE_LENGTH, wMsgSize);
793
#endif
794
0
  Stream_SetPosition(s, length);
795
0
  const BOOL ret = rdp_send(rdp, s, MCS_GLOBAL_CHANNEL_ID);
796
0
  rdp->sec_flags = 0;
797
0
  return ret;
798
0
}
799
800
BOOL license_read_server_upgrade_license(rdpLicense* license, wStream* s)
801
0
{
802
0
  WINPR_ASSERT(license);
803
0
804
0
  if (!license_read_binary_blob(s, license->EncryptedLicenseInfo))
805
0
    return FALSE;
806
0
  if (!license_check_stream_length(s, sizeof(license->MACData),
807
0
                                   "SERVER_UPGRADE_LICENSE::MACData"))
808
0
    return FALSE;
809
0
  Stream_Read(s, license->MACData, sizeof(license->MACData));
810
0
  return TRUE;
811
0
}
812
813
BOOL license_write_server_upgrade_license(const rdpLicense* license, wStream* s)
814
0
{
815
0
  WINPR_ASSERT(license);
816
817
0
  if (!license_write_binary_blob(s, license->EncryptedLicenseInfo))
818
0
    return FALSE;
819
0
  if (!license_check_stream_capacity(s, sizeof(license->MACData),
820
0
                                     "SERVER_UPGRADE_LICENSE::MACData"))
821
0
    return FALSE;
822
0
  Stream_Write(s, license->MACData, sizeof(license->MACData));
823
0
  return TRUE;
824
0
}
825
826
static BOOL license_server_send_new_or_upgrade_license(rdpLicense* license, BOOL upgrade)
827
0
{
828
0
  wStream* s = license_send_stream_init(license);
829
0
  const BYTE type = upgrade ? UPGRADE_LICENSE : NEW_LICENSE;
830
831
0
  if (!s)
832
0
    return FALSE;
833
834
0
  if (!license_write_server_upgrade_license(license, s))
835
0
    goto fail;
836
837
0
  return license_send(license, s, type);
838
839
0
fail:
840
0
  Stream_Release(s);
841
0
  return FALSE;
842
0
}
843
844
/**
845
 * Receive an RDP licensing packet.
846
 * msdn{cc240479}
847
 * @param license license module
848
 * @param s stream
849
 * @return if the operation completed successfully
850
 */
851
852
state_run_t license_client_recv(rdpLicense* license, wStream* s)
853
0
{
854
0
  BYTE flags = 0;
855
0
  BYTE bMsgType = 0;
856
0
  UINT16 wMsgSize = 0;
857
0
  const size_t length = Stream_GetRemainingLength(s);
858
859
0
  WINPR_ASSERT(license);
860
861
0
  if (!license_read_preamble(s, &bMsgType, &flags, &wMsgSize)) /* preamble (4 bytes) */
862
0
    return STATE_RUN_FAILED;
863
864
0
  DEBUG_LICENSE("Receiving %s Packet", license_request_type_string(bMsgType));
865
866
0
  switch (bMsgType)
867
0
  {
868
0
    case LICENSE_REQUEST:
869
      /* Client does not require configuration, so skip this state */
870
0
      if (license_get_state(license) == LICENSE_STATE_INITIAL)
871
0
        license_set_state(license, LICENSE_STATE_CONFIGURED);
872
873
0
      if (!license_ensure_state(license, LICENSE_STATE_CONFIGURED, bMsgType))
874
0
        return STATE_RUN_FAILED;
875
876
0
      if (!license_read_license_request_packet(license, s))
877
0
        return STATE_RUN_FAILED;
878
879
0
      if (!license_answer_license_request(license))
880
0
        return STATE_RUN_FAILED;
881
882
0
      license_set_state(license, LICENSE_STATE_NEW_REQUEST);
883
0
      break;
884
885
0
    case PLATFORM_CHALLENGE:
886
0
      if (!license_ensure_state(license, LICENSE_STATE_NEW_REQUEST, bMsgType))
887
0
        return STATE_RUN_FAILED;
888
889
0
      if (!license_read_platform_challenge_packet(license, s))
890
0
        return STATE_RUN_FAILED;
891
892
0
      if (!license_send_platform_challenge_response(license))
893
0
        return STATE_RUN_FAILED;
894
0
      license_set_state(license, LICENSE_STATE_PLATFORM_CHALLENGE_RESPONSE);
895
0
      break;
896
897
0
    case NEW_LICENSE:
898
0
    case UPGRADE_LICENSE:
899
0
      if (!license_ensure_state(license, LICENSE_STATE_PLATFORM_CHALLENGE_RESPONSE, bMsgType))
900
0
        return STATE_RUN_FAILED;
901
0
      if (!license_read_new_or_upgrade_license_packet(license, s))
902
0
        return STATE_RUN_FAILED;
903
0
      break;
904
905
0
    case ERROR_ALERT:
906
0
      if (!license_read_error_alert_packet(license, s))
907
0
        return STATE_RUN_FAILED;
908
0
      break;
909
910
0
    default:
911
0
      WLog_ERR(TAG, "invalid bMsgType:%" PRIu8 "", bMsgType);
912
0
      return STATE_RUN_FAILED;
913
0
  }
914
915
0
  if (!tpkt_ensure_stream_consumed(s, length))
916
0
    return STATE_RUN_FAILED;
917
0
  return STATE_RUN_SUCCESS;
918
0
}
919
920
state_run_t license_server_recv(rdpLicense* license, wStream* s)
921
0
{
922
0
  state_run_t rc = STATE_RUN_FAILED;
923
0
  BYTE flags = 0;
924
0
  BYTE bMsgType = 0;
925
0
  UINT16 wMsgSize = 0;
926
0
  const size_t length = Stream_GetRemainingLength(s);
927
928
0
  WINPR_ASSERT(license);
929
930
0
  if (!license_read_preamble(s, &bMsgType, &flags, &wMsgSize)) /* preamble (4 bytes) */
931
0
    goto fail;
932
933
0
  DEBUG_LICENSE("Receiving %s Packet", license_request_type_string(bMsgType));
934
935
0
  switch (bMsgType)
936
0
  {
937
0
    case NEW_LICENSE_REQUEST:
938
0
      if (!license_ensure_state(license, LICENSE_STATE_REQUEST, bMsgType))
939
0
        goto fail;
940
0
      if (!license_read_new_license_request_packet(license, s))
941
0
        goto fail;
942
      // TODO: Validate if client is allowed
943
0
      if (!license_send_error_alert(license, ERR_INVALID_MAC, ST_TOTAL_ABORT,
944
0
                                    license->ErrorInfo))
945
0
        goto fail;
946
0
      if (!license_send_platform_challenge_packet(license))
947
0
        goto fail;
948
0
      license->update = FALSE;
949
0
      if (!license_set_state(license, LICENSE_STATE_PLATFORM_CHALLENGE))
950
0
        goto fail;
951
0
      break;
952
0
    case LICENSE_INFO:
953
0
      if (!license_ensure_state(license, LICENSE_STATE_REQUEST, bMsgType))
954
0
        goto fail;
955
0
      if (!license_read_license_info(license, s))
956
0
        goto fail;
957
      // TODO: Validate license info
958
0
      if (!license_send_platform_challenge_packet(license))
959
0
        goto fail;
960
0
      if (!license_set_state(license, LICENSE_STATE_PLATFORM_CHALLENGE))
961
0
        goto fail;
962
0
      license->update = TRUE;
963
0
      break;
964
965
0
    case PLATFORM_CHALLENGE_RESPONSE:
966
0
      if (!license_ensure_state(license, LICENSE_STATE_PLATFORM_CHALLENGE, bMsgType))
967
0
        goto fail;
968
0
      if (!license_read_client_platform_challenge_response(license, s))
969
0
        goto fail;
970
971
      // TODO: validate challenge response
972
0
      if (FALSE)
973
0
      {
974
0
        if (license_send_error_alert(license, ERR_INVALID_CLIENT, ST_TOTAL_ABORT,
975
0
                                     license->ErrorInfo))
976
0
          goto fail;
977
0
      }
978
0
      else
979
0
      {
980
0
        if (!license_server_send_new_or_upgrade_license(license, license->update))
981
0
          goto fail;
982
983
0
        license->type = LICENSE_TYPE_ISSUED;
984
0
        license_set_state(license, LICENSE_STATE_COMPLETED);
985
986
0
        rc = STATE_RUN_CONTINUE; /* License issued, switch state */
987
0
      }
988
0
      break;
989
990
0
    case ERROR_ALERT:
991
0
      if (!license_read_error_alert_packet(license, s))
992
0
        goto fail;
993
0
      break;
994
995
0
    default:
996
0
      WLog_ERR(TAG, "invalid bMsgType:%" PRIu8 "", bMsgType);
997
0
      goto fail;
998
0
  }
999
1000
0
  if (!tpkt_ensure_stream_consumed(s, length))
1001
0
    goto fail;
1002
1003
0
  if (!state_run_success(rc))
1004
0
    rc = STATE_RUN_SUCCESS;
1005
1006
0
fail:
1007
0
  if (state_run_failed(rc))
1008
0
  {
1009
0
    if (flags & EXTENDED_ERROR_MSG_SUPPORTED)
1010
0
      license_send_error_alert(license, ERR_INVALID_CLIENT, ST_TOTAL_ABORT, NULL);
1011
0
    license_set_state(license, LICENSE_STATE_ABORTED);
1012
0
  }
1013
1014
0
  return rc;
1015
0
}
1016
1017
void license_generate_randoms(rdpLicense* license)
1018
14.9k
{
1019
14.9k
  WINPR_ASSERT(license);
1020
1021
#ifdef LICENSE_NULL_CLIENT_RANDOM
1022
  ZeroMemory(license->ClientRandom, sizeof(license->ClientRandom)); /* ClientRandom */
1023
#else
1024
14.9k
  winpr_RAND(license->ClientRandom, sizeof(license->ClientRandom));       /* ClientRandom */
1025
14.9k
#endif
1026
1027
14.9k
  winpr_RAND(license->ServerRandom, sizeof(license->ServerRandom)); /* ServerRandom */
1028
1029
#ifdef LICENSE_NULL_PREMASTER_SECRET
1030
  ZeroMemory(license->PremasterSecret, sizeof(license->PremasterSecret)); /* PremasterSecret */
1031
#else
1032
14.9k
  winpr_RAND(license->PremasterSecret, sizeof(license->PremasterSecret)); /* PremasterSecret */
1033
14.9k
#endif
1034
14.9k
}
1035
1036
/**
1037
 * Generate License Cryptographic Keys.
1038
 * @param license license module
1039
 */
1040
1041
static BOOL license_generate_keys(rdpLicense* license)
1042
0
{
1043
0
  WINPR_ASSERT(license);
1044
1045
0
  if (
1046
      /* MasterSecret */
1047
0
      !security_master_secret(license->PremasterSecret, sizeof(license->PremasterSecret),
1048
0
                              license->ClientRandom, sizeof(license->ClientRandom),
1049
0
                              license->ServerRandom, sizeof(license->ServerRandom),
1050
0
                              license->MasterSecret, sizeof(license->MasterSecret)) ||
1051
      /* SessionKeyBlob */
1052
0
      !security_session_key_blob(license->MasterSecret, sizeof(license->MasterSecret),
1053
0
                                 license->ClientRandom, sizeof(license->ClientRandom),
1054
0
                                 license->ServerRandom, sizeof(license->ServerRandom),
1055
0
                                 license->SessionKeyBlob, sizeof(license->SessionKeyBlob)))
1056
0
  {
1057
0
    return FALSE;
1058
0
  }
1059
0
  security_mac_salt_key(license->SessionKeyBlob, sizeof(license->SessionKeyBlob),
1060
0
                        license->ClientRandom, sizeof(license->ClientRandom),
1061
0
                        license->ServerRandom, sizeof(license->ServerRandom), license->MacSaltKey,
1062
0
                        sizeof(license->MacSaltKey)); /* MacSaltKey */
1063
0
  const BOOL ret = security_licensing_encryption_key(
1064
0
      license->SessionKeyBlob, sizeof(license->SessionKeyBlob), license->ClientRandom,
1065
0
      sizeof(license->ClientRandom), license->ServerRandom, sizeof(license->ServerRandom),
1066
0
      license->LicensingEncryptionKey,
1067
0
      sizeof(license->LicensingEncryptionKey)); /* LicensingEncryptionKey */
1068
1069
#ifdef WITH_DEBUG_LICENSE
1070
  WLog_DBG(TAG, "ClientRandom:");
1071
  winpr_HexDump(TAG, WLOG_DEBUG, license->ClientRandom, sizeof(license->ClientRandom));
1072
  WLog_DBG(TAG, "ServerRandom:");
1073
  winpr_HexDump(TAG, WLOG_DEBUG, license->ServerRandom, sizeof(license->ServerRandom));
1074
  WLog_DBG(TAG, "PremasterSecret:");
1075
  winpr_HexDump(TAG, WLOG_DEBUG, license->PremasterSecret, sizeof(license->PremasterSecret));
1076
  WLog_DBG(TAG, "MasterSecret:");
1077
  winpr_HexDump(TAG, WLOG_DEBUG, license->MasterSecret, sizeof(license->MasterSecret));
1078
  WLog_DBG(TAG, "SessionKeyBlob:");
1079
  winpr_HexDump(TAG, WLOG_DEBUG, license->SessionKeyBlob, sizeof(license->SessionKeyBlob));
1080
  WLog_DBG(TAG, "MacSaltKey:");
1081
  winpr_HexDump(TAG, WLOG_DEBUG, license->MacSaltKey, sizeof(license->MacSaltKey));
1082
  WLog_DBG(TAG, "LicensingEncryptionKey:");
1083
  winpr_HexDump(TAG, WLOG_DEBUG, license->LicensingEncryptionKey,
1084
                sizeof(license->LicensingEncryptionKey));
1085
#endif
1086
0
  return ret;
1087
0
}
1088
1089
/**
1090
 * Generate Unique Hardware Identifier (CLIENT_HARDWARE_ID).
1091
 * @param license license module
1092
 */
1093
1094
BOOL license_generate_hwid(rdpLicense* license)
1095
0
{
1096
0
  const BYTE* hashTarget = NULL;
1097
0
  size_t targetLen = 0;
1098
0
  BYTE macAddress[6] = { 0 };
1099
1100
0
  WINPR_ASSERT(license);
1101
0
  WINPR_ASSERT(license->rdp);
1102
0
  WINPR_ASSERT(license->rdp->settings);
1103
1104
0
  ZeroMemory(license->HardwareId, sizeof(license->HardwareId));
1105
1106
0
  if (license->rdp->settings->OldLicenseBehaviour)
1107
0
  {
1108
0
    hashTarget = macAddress;
1109
0
    targetLen = sizeof(macAddress);
1110
0
  }
1111
0
  else
1112
0
  {
1113
0
    wStream buffer = { 0 };
1114
0
    const char* hostname = license->rdp->settings->ClientHostname;
1115
0
    wStream* s = Stream_StaticInit(&buffer, license->HardwareId, 4);
1116
0
    Stream_Write_UINT32(s, license->PlatformId);
1117
1118
0
    hashTarget = (const BYTE*)hostname;
1119
0
    targetLen = hostname ? strlen(hostname) : 0;
1120
0
  }
1121
1122
  /* Allow FIPS override for use of MD5 here, really this does not have to be MD5 as we are just
1123
   * taking a MD5 hash of the 6 bytes of 0's(macAddress) */
1124
  /* and filling in the Data1-Data4 fields of the CLIENT_HARDWARE_ID structure(from MS-RDPELE
1125
   * section 2.2.2.3.1). This is for RDP licensing packets */
1126
  /* which will already be encrypted under FIPS, so the use of MD5 here is not for sensitive data
1127
   * protection. */
1128
0
  return winpr_Digest_Allow_FIPS(WINPR_MD_MD5, hashTarget, targetLen,
1129
0
                                 &license->HardwareId[HWID_PLATFORM_ID_LENGTH],
1130
0
                                 WINPR_MD5_DIGEST_LENGTH);
1131
0
}
1132
1133
static BOOL license_get_server_rsa_public_key(rdpLicense* license)
1134
0
{
1135
0
  rdpSettings* settings = NULL;
1136
1137
0
  WINPR_ASSERT(license);
1138
0
  WINPR_ASSERT(license->certificate);
1139
0
  WINPR_ASSERT(license->rdp);
1140
1141
0
  settings = license->rdp->settings;
1142
0
  WINPR_ASSERT(settings);
1143
1144
0
  if (license->ServerCertificate->length < 1)
1145
0
  {
1146
0
    if (!freerdp_certificate_read_server_cert(license->certificate, settings->ServerCertificate,
1147
0
                                              settings->ServerCertificateLength))
1148
0
      return FALSE;
1149
0
  }
1150
1151
0
  return TRUE;
1152
0
}
1153
1154
BOOL license_encrypt_premaster_secret(rdpLicense* license)
1155
0
{
1156
0
  WINPR_ASSERT(license);
1157
0
  WINPR_ASSERT(license->certificate);
1158
1159
0
  if (!license_get_server_rsa_public_key(license))
1160
0
    return FALSE;
1161
1162
0
  WINPR_ASSERT(license->EncryptedPremasterSecret);
1163
1164
0
  const rdpCertInfo* info = freerdp_certificate_get_info(license->certificate);
1165
0
  if (!info)
1166
0
  {
1167
0
    WLog_ERR(TAG, "info=%p, license->certificate=%p", info, license->certificate);
1168
0
    return FALSE;
1169
0
  }
1170
1171
#ifdef WITH_DEBUG_LICENSE
1172
  WLog_DBG(TAG, "Modulus (%" PRIu32 " bits):", info->ModulusLength * 8);
1173
  winpr_HexDump(TAG, WLOG_DEBUG, info->Modulus, info->ModulusLength);
1174
  WLog_DBG(TAG, "Exponent:");
1175
  winpr_HexDump(TAG, WLOG_DEBUG, info->exponent, sizeof(info->exponent));
1176
#endif
1177
1178
0
  BYTE* EncryptedPremasterSecret = (BYTE*)calloc(1, info->ModulusLength);
1179
0
  if (!EncryptedPremasterSecret)
1180
0
  {
1181
0
    WLog_ERR(TAG, "EncryptedPremasterSecret=%p, info->ModulusLength=%" PRIu32,
1182
0
             EncryptedPremasterSecret, info->ModulusLength);
1183
0
    return FALSE;
1184
0
  }
1185
1186
0
  license->EncryptedPremasterSecret->type = BB_RANDOM_BLOB;
1187
0
  license->EncryptedPremasterSecret->length = sizeof(license->PremasterSecret);
1188
0
#ifndef LICENSE_NULL_PREMASTER_SECRET
1189
0
  {
1190
0
    const SSIZE_T length =
1191
0
        crypto_rsa_public_encrypt(license->PremasterSecret, sizeof(license->PremasterSecret),
1192
0
                                  info, EncryptedPremasterSecret, info->ModulusLength);
1193
0
    if ((length < 0) || (length > UINT16_MAX))
1194
0
    {
1195
0
      WLog_ERR(TAG, "RSA public encrypt length=%" PRIdz " < 0 || > %" PRIu16, length,
1196
0
               UINT16_MAX);
1197
0
      return FALSE;
1198
0
    }
1199
0
    license->EncryptedPremasterSecret->length = (UINT16)length;
1200
0
  }
1201
0
#endif
1202
0
  license->EncryptedPremasterSecret->data = EncryptedPremasterSecret;
1203
0
  return TRUE;
1204
0
}
1205
1206
static BOOL license_rc4_with_licenseKey(const rdpLicense* license, const BYTE* input, size_t len,
1207
                                        LICENSE_BLOB* target)
1208
0
{
1209
0
  WINPR_ASSERT(license);
1210
0
  WINPR_ASSERT(input || (len == 0));
1211
0
  WINPR_ASSERT(target);
1212
0
  WINPR_ASSERT(len <= UINT16_MAX);
1213
1214
0
  WINPR_RC4_CTX* rc4 = winpr_RC4_New_Allow_FIPS(license->LicensingEncryptionKey,
1215
0
                                                sizeof(license->LicensingEncryptionKey));
1216
0
  if (!rc4)
1217
0
  {
1218
0
    WLog_ERR(TAG, "Failed to allocate RC4");
1219
0
    return FALSE;
1220
0
  }
1221
1222
0
  BYTE* buffer = (BYTE*)realloc(target->data, len);
1223
0
  if (!buffer)
1224
0
    goto error_buffer;
1225
1226
0
  target->data = buffer;
1227
0
  target->length = (UINT16)len;
1228
1229
0
  if (!winpr_RC4_Update(rc4, len, input, buffer))
1230
0
    goto error_buffer;
1231
1232
0
  winpr_RC4_Free(rc4);
1233
0
  return TRUE;
1234
1235
0
error_buffer:
1236
0
  WLog_ERR(TAG, "Failed to create/update RC4: len=%" PRIuz ", buffer=%p", len, buffer);
1237
0
  winpr_RC4_Free(rc4);
1238
0
  return FALSE;
1239
0
}
1240
1241
/**
1242
 * Encrypt the input using the license key and MAC the input for a signature
1243
 *
1244
 * @param license rdpLicense to get keys and salt from
1245
 * @param input the input data to encrypt and MAC
1246
 * @param len size of input
1247
 * @param target a target LICENSE_BLOB where the encrypted input will be stored
1248
 * @param mac the signature buffer (16 bytes)
1249
 * @return if the operation completed successfully
1250
 */
1251
static BOOL license_encrypt_and_MAC(rdpLicense* license, const BYTE* input, size_t len,
1252
                                    LICENSE_BLOB* target, BYTE* mac, size_t mac_length)
1253
0
{
1254
0
  WINPR_ASSERT(license);
1255
0
  return license_rc4_with_licenseKey(license, input, len, target) &&
1256
0
         security_mac_data(license->MacSaltKey, sizeof(license->MacSaltKey), input, len, mac,
1257
0
                           mac_length);
1258
0
}
1259
1260
/**
1261
 * Decrypt the input using the license key and check the MAC
1262
 *
1263
 * @param license rdpLicense to get keys and salt from
1264
 * @param input the input data to decrypt and MAC
1265
 * @param len size of input
1266
 * @param target a target LICENSE_BLOB where the decrypted input will be stored
1267
 * @param packetMac the signature buffer (16 bytes)
1268
 *
1269
 * @return if the operation completed successfully
1270
 */
1271
static BOOL license_decrypt_and_check_MAC(rdpLicense* license, const BYTE* input, size_t len,
1272
                                          LICENSE_BLOB* target, const BYTE* packetMac)
1273
0
{
1274
0
  BYTE macData[sizeof(license->MACData)] = { 0 };
1275
1276
0
  WINPR_ASSERT(license);
1277
0
  WINPR_ASSERT(target);
1278
1279
0
  if (freerdp_settings_get_bool(license->rdp->settings, FreeRDP_TransportDumpReplay))
1280
0
  {
1281
0
    WLog_DBG(TAG, "TransportDumpReplay active, skipping...");
1282
0
    return TRUE;
1283
0
  }
1284
1285
0
  if (!license_rc4_with_licenseKey(license, input, len, target))
1286
0
    return FALSE;
1287
1288
0
  if (!security_mac_data(license->MacSaltKey, sizeof(license->MacSaltKey), target->data, len,
1289
0
                         macData, sizeof(macData)))
1290
0
    return FALSE;
1291
1292
0
  if (memcmp(packetMac, macData, sizeof(macData)) != 0)
1293
0
  {
1294
0
    WLog_ERR(TAG, "packetMac != expectedMac");
1295
0
    return FALSE;
1296
0
  }
1297
0
  return TRUE;
1298
0
}
1299
1300
/**
1301
 * Read Product Information (PRODUCT_INFO).
1302
 * msdn{cc241915}
1303
 * @param s stream
1304
 * @param productInfo product information
1305
 */
1306
1307
BOOL license_read_product_info(wStream* s, LICENSE_PRODUCT_INFO* productInfo)
1308
0
{
1309
0
  WINPR_ASSERT(productInfo);
1310
1311
0
  if (!license_check_stream_length(s, 8, "license product info::cbCompanyName"))
1312
0
    return FALSE;
1313
1314
0
  Stream_Read_UINT32(s, productInfo->dwVersion);     /* dwVersion (4 bytes) */
1315
0
  Stream_Read_UINT32(s, productInfo->cbCompanyName); /* cbCompanyName (4 bytes) */
1316
1317
  /* Name must be >0, but there is no upper limit defined, use UINT32_MAX */
1318
0
  if ((productInfo->cbCompanyName < 2) || (productInfo->cbCompanyName % 2 != 0))
1319
0
  {
1320
0
    WLog_WARN(TAG, "license product info invalid cbCompanyName %" PRIu32,
1321
0
              productInfo->cbCompanyName);
1322
0
    return FALSE;
1323
0
  }
1324
1325
0
  if (!license_check_stream_length(s, productInfo->cbCompanyName,
1326
0
                                   "license product info::CompanyName"))
1327
0
    return FALSE;
1328
1329
0
  productInfo->pbProductId = NULL;
1330
0
  productInfo->pbCompanyName = (BYTE*)malloc(productInfo->cbCompanyName);
1331
0
  if (!productInfo->pbCompanyName)
1332
0
    goto out_fail;
1333
0
  Stream_Read(s, productInfo->pbCompanyName, productInfo->cbCompanyName);
1334
1335
0
  if (!license_check_stream_length(s, 4, "license product info::cbProductId"))
1336
0
    goto out_fail;
1337
1338
0
  Stream_Read_UINT32(s, productInfo->cbProductId); /* cbProductId (4 bytes) */
1339
1340
0
  if ((productInfo->cbProductId < 2) || (productInfo->cbProductId % 2 != 0))
1341
0
  {
1342
0
    WLog_WARN(TAG, "license product info invalid cbProductId %" PRIu32,
1343
0
              productInfo->cbProductId);
1344
0
    goto out_fail;
1345
0
  }
1346
1347
0
  if (!license_check_stream_length(s, productInfo->cbProductId,
1348
0
                                   "license product info::ProductId"))
1349
0
    goto out_fail;
1350
1351
0
  productInfo->pbProductId = (BYTE*)malloc(productInfo->cbProductId);
1352
0
  if (!productInfo->pbProductId)
1353
0
    goto out_fail;
1354
0
  Stream_Read(s, productInfo->pbProductId, productInfo->cbProductId);
1355
0
  return TRUE;
1356
1357
0
out_fail:
1358
0
  free(productInfo->pbCompanyName);
1359
0
  free(productInfo->pbProductId);
1360
0
  productInfo->pbCompanyName = NULL;
1361
0
  productInfo->pbProductId = NULL;
1362
0
  return FALSE;
1363
0
}
1364
1365
static BOOL license_write_product_info(wStream* s, const LICENSE_PRODUCT_INFO* productInfo)
1366
0
{
1367
0
  WINPR_ASSERT(productInfo);
1368
1369
0
  if (!license_check_stream_capacity(s, 8, "license product info::cbCompanyName"))
1370
0
    return FALSE;
1371
1372
0
  Stream_Write_UINT32(s, productInfo->dwVersion);     /* dwVersion (4 bytes) */
1373
0
  Stream_Write_UINT32(s, productInfo->cbCompanyName); /* cbCompanyName (4 bytes) */
1374
1375
  /* Name must be >0, but there is no upper limit defined, use UINT32_MAX */
1376
0
  if ((productInfo->cbCompanyName < 2) || (productInfo->cbCompanyName % 2 != 0) ||
1377
0
      !productInfo->pbCompanyName)
1378
0
  {
1379
0
    WLog_WARN(TAG, "license product info invalid cbCompanyName %" PRIu32,
1380
0
              productInfo->cbCompanyName);
1381
0
    return FALSE;
1382
0
  }
1383
1384
0
  if (!license_check_stream_capacity(s, productInfo->cbCompanyName,
1385
0
                                     "license product info::CompanyName"))
1386
0
    return FALSE;
1387
1388
0
  Stream_Write(s, productInfo->pbCompanyName, productInfo->cbCompanyName);
1389
1390
0
  if (!license_check_stream_capacity(s, 4, "license product info::cbProductId"))
1391
0
    return FALSE;
1392
1393
0
  Stream_Write_UINT32(s, productInfo->cbProductId); /* cbProductId (4 bytes) */
1394
1395
0
  if ((productInfo->cbProductId < 2) || (productInfo->cbProductId % 2 != 0) ||
1396
0
      !productInfo->pbProductId)
1397
0
  {
1398
0
    WLog_WARN(TAG, "license product info invalid cbProductId %" PRIu32,
1399
0
              productInfo->cbProductId);
1400
0
    return FALSE;
1401
0
  }
1402
1403
0
  if (!license_check_stream_capacity(s, productInfo->cbProductId,
1404
0
                                     "license product info::ProductId"))
1405
0
    return FALSE;
1406
1407
0
  Stream_Write(s, productInfo->pbProductId, productInfo->cbProductId);
1408
0
  return TRUE;
1409
0
}
1410
1411
/**
1412
 * Allocate New Product Information (LICENSE_PRODUCT_INFO).
1413
 * msdn{cc241915}
1414
 * @return new product information
1415
 */
1416
1417
LICENSE_PRODUCT_INFO* license_new_product_info(void)
1418
14.9k
{
1419
14.9k
  LICENSE_PRODUCT_INFO* productInfo =
1420
14.9k
      (LICENSE_PRODUCT_INFO*)calloc(1, sizeof(LICENSE_PRODUCT_INFO));
1421
14.9k
  if (!productInfo)
1422
0
    return NULL;
1423
14.9k
  return productInfo;
1424
14.9k
}
1425
1426
/**
1427
 * Free Product Information (LICENSE_PRODUCT_INFO).
1428
 * msdn{cc241915}
1429
 * @param productInfo product information
1430
 */
1431
1432
void license_free_product_info(LICENSE_PRODUCT_INFO* productInfo)
1433
14.9k
{
1434
14.9k
  if (productInfo)
1435
14.9k
  {
1436
14.9k
    free(productInfo->pbCompanyName);
1437
14.9k
    free(productInfo->pbProductId);
1438
14.9k
    free(productInfo);
1439
14.9k
  }
1440
14.9k
}
1441
1442
BOOL license_read_binary_blob_data(LICENSE_BLOB* blob, UINT16 wBlobType, const void* data,
1443
                                   size_t length)
1444
0
{
1445
0
  WINPR_ASSERT(blob);
1446
0
  WINPR_ASSERT(length <= UINT16_MAX);
1447
0
  WINPR_ASSERT(data || (length == 0));
1448
1449
0
  blob->length = (UINT16)length;
1450
0
  free(blob->data);
1451
0
  blob->data = NULL;
1452
1453
0
  if ((blob->type != wBlobType) && (blob->type != BB_ANY_BLOB))
1454
0
  {
1455
0
    WLog_ERR(TAG, "license binary blob::type expected %s, got %s",
1456
0
             licencse_blob_type_string(wBlobType), licencse_blob_type_string(blob->type));
1457
0
  }
1458
1459
  /*
1460
   * Server can choose to not send data by setting length to 0.
1461
   * If so, it may not bother to set the type, so shortcut the warning
1462
   */
1463
0
  if ((blob->type != BB_ANY_BLOB) && (blob->length == 0))
1464
0
  {
1465
0
    WLog_WARN(TAG, "license binary blob::type %s, length=0, skipping.",
1466
0
              licencse_blob_type_string(blob->type));
1467
0
    return TRUE;
1468
0
  }
1469
1470
0
  blob->type = wBlobType;
1471
0
  blob->data = (BYTE*)malloc(blob->length);
1472
0
  if (!blob->data)
1473
0
  {
1474
0
    WLog_ERR(TAG, "license binary blob::length=%" PRIu16 ", blob::data=%p", blob->length,
1475
0
             blob->data);
1476
0
    return FALSE;
1477
0
  }
1478
0
  memcpy(blob->data, data, blob->length); /* blobData */
1479
0
  return TRUE;
1480
0
}
1481
1482
/**
1483
 * Read License Binary Blob (LICENSE_BINARY_BLOB).
1484
 * msdn{cc240481}
1485
 * @param s stream
1486
 * @param blob license binary blob
1487
 */
1488
1489
BOOL license_read_binary_blob(wStream* s, LICENSE_BLOB* blob)
1490
0
{
1491
0
  UINT16 wBlobType = 0;
1492
0
  UINT16 length = 0;
1493
1494
0
  WINPR_ASSERT(blob);
1495
1496
0
  if (!license_check_stream_length(s, 4, "license binary blob::type"))
1497
0
    return FALSE;
1498
1499
0
  Stream_Read_UINT16(s, wBlobType); /* wBlobType (2 bytes) */
1500
0
  Stream_Read_UINT16(s, length);    /* wBlobLen (2 bytes) */
1501
1502
0
  if (!license_check_stream_length(s, length, "license binary blob::length"))
1503
0
    return FALSE;
1504
1505
0
  if (!license_read_binary_blob_data(blob, wBlobType, Stream_Pointer(s), length))
1506
0
    return FALSE;
1507
1508
0
  return Stream_SafeSeek(s, length);
1509
0
}
1510
1511
/**
1512
 * Write License Binary Blob (LICENSE_BINARY_BLOB).
1513
 * msdn{cc240481}
1514
 * @param s stream
1515
 * @param blob license binary blob
1516
 */
1517
1518
BOOL license_write_binary_blob(wStream* s, const LICENSE_BLOB* blob)
1519
0
{
1520
0
  WINPR_ASSERT(blob);
1521
1522
0
  if (!Stream_EnsureRemainingCapacity(s, blob->length + 4))
1523
0
    return FALSE;
1524
1525
0
  Stream_Write_UINT16(s, blob->type);   /* wBlobType (2 bytes) */
1526
0
  Stream_Write_UINT16(s, blob->length); /* wBlobLen (2 bytes) */
1527
1528
0
  if (blob->length > 0)
1529
0
    Stream_Write(s, blob->data, blob->length); /* blobData */
1530
0
  return TRUE;
1531
0
}
1532
1533
static BOOL license_write_encrypted_premaster_secret_blob(wStream* s, const LICENSE_BLOB* blob,
1534
                                                          UINT32 ModulusLength)
1535
0
{
1536
0
  const UINT32 length = ModulusLength + 8;
1537
1538
0
  WINPR_ASSERT(blob);
1539
0
  WINPR_ASSERT(length <= UINT16_MAX);
1540
1541
0
  if (blob->length > ModulusLength)
1542
0
  {
1543
0
    WLog_ERR(TAG, "invalid blob");
1544
0
    return FALSE;
1545
0
  }
1546
1547
0
  if (!Stream_EnsureRemainingCapacity(s, length + 4))
1548
0
    return FALSE;
1549
0
  Stream_Write_UINT16(s, blob->type); /* wBlobType (2 bytes) */
1550
0
  Stream_Write_UINT16(s, (UINT16)length); /* wBlobLen (2 bytes) */
1551
1552
0
  if (blob->length > 0)
1553
0
    Stream_Write(s, blob->data, blob->length); /* blobData */
1554
1555
0
  Stream_Zero(s, length - blob->length);
1556
0
  return TRUE;
1557
0
}
1558
1559
static BOOL license_read_encrypted_premaster_secret_blob(wStream* s, LICENSE_BLOB* blob,
1560
                                                         UINT32* ModulusLength)
1561
0
{
1562
0
  if (!license_read_binary_blob(s, blob))
1563
0
    return FALSE;
1564
0
  WINPR_ASSERT(ModulusLength);
1565
0
  *ModulusLength = blob->length;
1566
0
  return TRUE;
1567
0
}
1568
1569
/**
1570
 * Allocate New License Binary Blob (LICENSE_BINARY_BLOB).
1571
 * msdn{cc240481}
1572
 * @return new license binary blob
1573
 */
1574
1575
LICENSE_BLOB* license_new_binary_blob(UINT16 type)
1576
179k
{
1577
179k
  LICENSE_BLOB* blob = (LICENSE_BLOB*)calloc(1, sizeof(LICENSE_BLOB));
1578
179k
  if (blob)
1579
179k
    blob->type = type;
1580
179k
  return blob;
1581
179k
}
1582
1583
/**
1584
 * Free License Binary Blob (LICENSE_BINARY_BLOB).
1585
 * msdn{cc240481}
1586
 * @param blob license binary blob
1587
 */
1588
1589
void license_free_binary_blob(LICENSE_BLOB* blob)
1590
179k
{
1591
179k
  if (blob)
1592
179k
  {
1593
179k
    free(blob->data);
1594
179k
    free(blob);
1595
179k
  }
1596
179k
}
1597
1598
/**
1599
 * Read License Scope List (SCOPE_LIST).
1600
 * msdn{cc241916}
1601
 * @param s stream
1602
 * @param scopeList scope list
1603
 */
1604
1605
BOOL license_read_scope_list(wStream* s, SCOPE_LIST* scopeList)
1606
0
{
1607
0
  UINT32 scopeCount = 0;
1608
1609
0
  WINPR_ASSERT(scopeList);
1610
1611
0
  if (!license_check_stream_length(s, 4, "license scope list"))
1612
0
    return FALSE;
1613
1614
0
  Stream_Read_UINT32(s, scopeCount); /* ScopeCount (4 bytes) */
1615
1616
0
  if (!license_check_stream_length(s, scopeCount * 4ull, "license scope list::count"))
1617
0
    return FALSE;
1618
1619
0
  if (!license_scope_list_resize(scopeList, scopeCount))
1620
0
    return FALSE;
1621
  /* ScopeArray */
1622
0
  for (UINT32 i = 0; i < scopeCount; i++)
1623
0
  {
1624
0
    if (!license_read_binary_blob(s, scopeList->array[i]))
1625
0
      return FALSE;
1626
0
  }
1627
1628
0
  return TRUE;
1629
0
}
1630
1631
BOOL license_write_scope_list(wStream* s, const SCOPE_LIST* scopeList)
1632
0
{
1633
0
  WINPR_ASSERT(scopeList);
1634
1635
0
  if (!license_check_stream_capacity(s, 4, "license scope list"))
1636
0
    return FALSE;
1637
1638
0
  Stream_Write_UINT32(s, scopeList->count); /* ScopeCount (4 bytes) */
1639
1640
0
  if (!license_check_stream_capacity(s, scopeList->count * 4ull, "license scope list::count"))
1641
0
    return FALSE;
1642
1643
  /* ScopeArray */
1644
0
  WINPR_ASSERT(scopeList->array || (scopeList->count == 0));
1645
0
  for (UINT32 i = 0; i < scopeList->count; i++)
1646
0
  {
1647
0
    const LICENSE_BLOB* element = scopeList->array[i];
1648
1649
0
    if (!license_write_binary_blob(s, element))
1650
0
      return FALSE;
1651
0
  }
1652
1653
0
  return TRUE;
1654
0
}
1655
1656
/**
1657
 * Allocate New License Scope List (SCOPE_LIST).
1658
 * msdn{cc241916}
1659
 * @return new scope list
1660
 */
1661
1662
SCOPE_LIST* license_new_scope_list(void)
1663
14.9k
{
1664
14.9k
  SCOPE_LIST* list = calloc(1, sizeof(SCOPE_LIST));
1665
14.9k
  return list;
1666
14.9k
}
1667
1668
BOOL license_scope_list_resize(SCOPE_LIST* scopeList, UINT32 count)
1669
14.9k
{
1670
14.9k
  WINPR_ASSERT(scopeList);
1671
14.9k
  WINPR_ASSERT(scopeList->array || (scopeList->count == 0));
1672
1673
14.9k
  for (UINT32 x = count; x < scopeList->count; x++)
1674
0
  {
1675
0
    license_free_binary_blob(scopeList->array[x]);
1676
0
    scopeList->array[x] = NULL;
1677
0
  }
1678
1679
14.9k
  if (count > 0)
1680
0
  {
1681
0
    LICENSE_BLOB** tmp = realloc(scopeList->array, count * sizeof(LICENSE_BLOB*));
1682
0
    if (!tmp)
1683
0
      return FALSE;
1684
0
    scopeList->array = tmp;
1685
0
  }
1686
14.9k
  else
1687
14.9k
  {
1688
14.9k
    free(scopeList->array);
1689
14.9k
    scopeList->array = NULL;
1690
14.9k
  }
1691
1692
14.9k
  for (UINT32 x = scopeList->count; x < count; x++)
1693
0
  {
1694
0
    LICENSE_BLOB* blob = license_new_binary_blob(BB_SCOPE_BLOB);
1695
0
    if (!blob)
1696
0
    {
1697
0
      scopeList->count = x;
1698
0
      return FALSE;
1699
0
    }
1700
0
    scopeList->array[x] = blob;
1701
0
  }
1702
1703
14.9k
  scopeList->count = count;
1704
14.9k
  return TRUE;
1705
14.9k
}
1706
1707
/**
1708
 * Free License Scope List (SCOPE_LIST).
1709
 * msdn{cc241916}
1710
 * @param scopeList scope list
1711
 */
1712
1713
void license_free_scope_list(SCOPE_LIST* scopeList)
1714
14.9k
{
1715
14.9k
  if (!scopeList)
1716
0
    return;
1717
1718
14.9k
  license_scope_list_resize(scopeList, 0);
1719
14.9k
  free(scopeList);
1720
14.9k
}
1721
1722
BOOL license_send_license_info(rdpLicense* license, const LICENSE_BLOB* calBlob,
1723
                               const BYTE* signature, size_t signature_length)
1724
0
{
1725
0
  WINPR_ASSERT(calBlob);
1726
0
  WINPR_ASSERT(signature);
1727
0
  WINPR_ASSERT(license->certificate);
1728
1729
0
  const rdpCertInfo* info = freerdp_certificate_get_info(license->certificate);
1730
0
  if (!info)
1731
0
    return FALSE;
1732
1733
0
  wStream* s = license_send_stream_init(license);
1734
0
  if (!s)
1735
0
    return FALSE;
1736
1737
0
  if (!license_check_stream_capacity(s, 8 + sizeof(license->ClientRandom),
1738
0
                                     "license info::ClientRandom"))
1739
0
    return FALSE;
1740
1741
0
  Stream_Write_UINT32(s,
1742
0
                      license->PreferredKeyExchangeAlg); /* PreferredKeyExchangeAlg (4 bytes) */
1743
0
  Stream_Write_UINT32(s, license->PlatformId);           /* PlatformId (4 bytes) */
1744
1745
  /* ClientRandom (32 bytes) */
1746
0
  Stream_Write(s, license->ClientRandom, sizeof(license->ClientRandom));
1747
1748
  /* Licensing Binary Blob with EncryptedPreMasterSecret: */
1749
0
  if (!license_write_encrypted_premaster_secret_blob(s, license->EncryptedPremasterSecret,
1750
0
                                                     info->ModulusLength))
1751
0
    goto error;
1752
1753
  /* Licensing Binary Blob with LicenseInfo: */
1754
0
  if (!license_write_binary_blob(s, calBlob))
1755
0
    goto error;
1756
1757
  /* Licensing Binary Blob with EncryptedHWID */
1758
0
  if (!license_write_binary_blob(s, license->EncryptedHardwareId))
1759
0
    goto error;
1760
1761
  /* MACData */
1762
0
  if (!license_check_stream_capacity(s, signature_length, "license info::MACData"))
1763
0
    goto error;
1764
0
  Stream_Write(s, signature, signature_length);
1765
1766
0
  return license_send(license, s, LICENSE_INFO);
1767
1768
0
error:
1769
0
  Stream_Release(s);
1770
0
  return FALSE;
1771
0
}
1772
1773
static BOOL license_check_preferred_alg(rdpLicense* license, UINT32 PreferredKeyExchangeAlg,
1774
                                        const char* where)
1775
0
{
1776
0
  WINPR_ASSERT(license);
1777
0
  WINPR_ASSERT(where);
1778
1779
0
  if (license->PreferredKeyExchangeAlg != PreferredKeyExchangeAlg)
1780
0
  {
1781
0
    char buffer1[64] = { 0 };
1782
0
    char buffer2[64] = { 0 };
1783
0
    WLog_WARN(TAG, "%s::PreferredKeyExchangeAlg, expected %s, got %s", where,
1784
0
              license_preferred_key_exchange_alg_string(license->PreferredKeyExchangeAlg,
1785
0
                                                        buffer1, sizeof(buffer1)),
1786
0
              license_preferred_key_exchange_alg_string(PreferredKeyExchangeAlg, buffer2,
1787
0
                                                        sizeof(buffer2)));
1788
0
    return FALSE;
1789
0
  }
1790
0
  return TRUE;
1791
0
}
1792
1793
BOOL license_read_license_info(rdpLicense* license, wStream* s)
1794
0
{
1795
0
  BOOL rc = FALSE;
1796
0
  UINT32 PreferredKeyExchangeAlg = 0;
1797
1798
0
  WINPR_ASSERT(license);
1799
0
  WINPR_ASSERT(license->certificate);
1800
1801
0
  const rdpCertInfo* info = freerdp_certificate_get_info(license->certificate);
1802
0
  if (!info)
1803
0
    goto error;
1804
1805
  /* ClientRandom (32 bytes) */
1806
0
  if (!license_check_stream_length(s, 8 + sizeof(license->ClientRandom), "license info"))
1807
0
    goto error;
1808
1809
0
  Stream_Read_UINT32(s, PreferredKeyExchangeAlg); /* PreferredKeyExchangeAlg (4 bytes) */
1810
0
  if (!license_check_preferred_alg(license, PreferredKeyExchangeAlg, "license info"))
1811
0
    goto error;
1812
0
  Stream_Read_UINT32(s, license->PlatformId); /* PlatformId (4 bytes) */
1813
1814
  /* ClientRandom (32 bytes) */
1815
0
  Stream_Read(s, license->ClientRandom, sizeof(license->ClientRandom));
1816
1817
  /* Licensing Binary Blob with EncryptedPreMasterSecret: */
1818
0
  UINT32 ModulusLength = 0;
1819
0
  if (!license_read_encrypted_premaster_secret_blob(s, license->EncryptedPremasterSecret,
1820
0
                                                    &ModulusLength))
1821
0
    goto error;
1822
1823
0
  if (ModulusLength != info->ModulusLength)
1824
0
  {
1825
0
    WLog_WARN(TAG,
1826
0
              "EncryptedPremasterSecret,::ModulusLength[%" PRIu32
1827
0
              "] != rdpCertInfo::ModulusLength[%" PRIu32 "]",
1828
0
              ModulusLength, info->ModulusLength);
1829
0
    goto error;
1830
0
  }
1831
  /* Licensing Binary Blob with LicenseInfo: */
1832
0
  if (!license_read_binary_blob(s, license->LicenseInfo))
1833
0
    goto error;
1834
1835
  /* Licensing Binary Blob with EncryptedHWID */
1836
0
  if (!license_read_binary_blob(s, license->EncryptedHardwareId))
1837
0
    goto error;
1838
1839
  /* MACData */
1840
0
  if (!license_check_stream_length(s, sizeof(license->MACData), "license info::MACData"))
1841
0
    goto error;
1842
0
  Stream_Read(s, license->MACData, sizeof(license->MACData));
1843
1844
0
  rc = TRUE;
1845
1846
0
error:
1847
0
  return rc;
1848
0
}
1849
1850
/**
1851
 * Read a LICENSE_REQUEST packet.
1852
 * msdn{cc241914}
1853
 * @param license license module
1854
 * @param s stream
1855
 */
1856
1857
BOOL license_read_license_request_packet(rdpLicense* license, wStream* s)
1858
0
{
1859
0
  WINPR_ASSERT(license);
1860
1861
  /* ServerRandom (32 bytes) */
1862
0
  if (!license_check_stream_length(s, sizeof(license->ServerRandom), "license request"))
1863
0
    return FALSE;
1864
1865
0
  Stream_Read(s, license->ServerRandom, sizeof(license->ServerRandom));
1866
1867
  /* ProductInfo */
1868
0
  if (!license_read_product_info(s, license->ProductInfo))
1869
0
    return FALSE;
1870
1871
  /* KeyExchangeList */
1872
0
  if (!license_read_binary_blob(s, license->KeyExchangeList))
1873
0
    return FALSE;
1874
1875
  /* ServerCertificate */
1876
0
  if (!license_read_binary_blob(s, license->ServerCertificate))
1877
0
    return FALSE;
1878
1879
  /* ScopeList */
1880
0
  if (!license_read_scope_list(s, license->ScopeList))
1881
0
    return FALSE;
1882
1883
  /* Parse Server Certificate */
1884
0
  if (!freerdp_certificate_read_server_cert(license->certificate,
1885
0
                                            license->ServerCertificate->data,
1886
0
                                            license->ServerCertificate->length))
1887
0
    return FALSE;
1888
1889
0
  if (!license_generate_keys(license) || !license_generate_hwid(license) ||
1890
0
      !license_encrypt_premaster_secret(license))
1891
0
    return FALSE;
1892
1893
#ifdef WITH_DEBUG_LICENSE
1894
  WLog_DBG(TAG, "ServerRandom:");
1895
  winpr_HexDump(TAG, WLOG_DEBUG, license->ServerRandom, sizeof(license->ServerRandom));
1896
  license_print_product_info(license->ProductInfo);
1897
  license_print_scope_list(license->ScopeList);
1898
#endif
1899
0
  return TRUE;
1900
0
}
1901
1902
BOOL license_write_license_request_packet(const rdpLicense* license, wStream* s)
1903
0
{
1904
0
  WINPR_ASSERT(license);
1905
1906
  /* ServerRandom (32 bytes) */
1907
0
  if (!license_check_stream_capacity(s, sizeof(license->ServerRandom), "license request"))
1908
0
    return FALSE;
1909
0
  Stream_Write(s, license->ServerRandom, sizeof(license->ServerRandom));
1910
1911
  /* ProductInfo */
1912
0
  if (!license_write_product_info(s, license->ProductInfo))
1913
0
    return FALSE;
1914
1915
  /* KeyExchangeList */
1916
0
  if (!license_write_binary_blob(s, license->KeyExchangeList))
1917
0
    return FALSE;
1918
1919
  /* ServerCertificate */
1920
0
  if (!license_write_binary_blob(s, license->ServerCertificate))
1921
0
    return FALSE;
1922
1923
  /* ScopeList */
1924
0
  if (!license_write_scope_list(s, license->ScopeList))
1925
0
    return FALSE;
1926
1927
0
  return TRUE;
1928
0
}
1929
1930
static BOOL license_send_license_request_packet(rdpLicense* license)
1931
0
{
1932
0
  wStream* s = license_send_stream_init(license);
1933
0
  if (!s)
1934
0
    return FALSE;
1935
1936
0
  if (!license_write_license_request_packet(license, s))
1937
0
    goto fail;
1938
1939
0
  return license_send(license, s, LICENSE_REQUEST);
1940
1941
0
fail:
1942
0
  Stream_Release(s);
1943
0
  return FALSE;
1944
0
}
1945
1946
/*
1947
 * Read a PLATFORM_CHALLENGE packet.
1948
 * msdn{cc241921}
1949
 * @param license license module
1950
 * @param s stream
1951
 */
1952
1953
BOOL license_read_platform_challenge_packet(rdpLicense* license, wStream* s)
1954
0
{
1955
0
  BYTE macData[LICENSING_ENCRYPTION_KEY_LENGTH] = { 0 };
1956
0
  UINT32 ConnectFlags = 0;
1957
1958
0
  WINPR_ASSERT(license);
1959
1960
0
  DEBUG_LICENSE("Receiving Platform Challenge Packet");
1961
1962
0
  if (!license_check_stream_length(s, 4, "license platform challenge"))
1963
0
    return FALSE;
1964
1965
0
  Stream_Read_UINT32(s, ConnectFlags); /* ConnectFlags, Reserved (4 bytes) */
1966
1967
  /* EncryptedPlatformChallenge */
1968
0
  license->EncryptedPlatformChallenge->type = BB_ANY_BLOB;
1969
0
  if (!license_read_binary_blob(s, license->EncryptedPlatformChallenge))
1970
0
    return FALSE;
1971
0
  license->EncryptedPlatformChallenge->type = BB_ENCRYPTED_DATA_BLOB;
1972
1973
  /* MACData (16 bytes) */
1974
0
  if (!license_check_stream_length(s, sizeof(macData), "license platform challenge::MAC"))
1975
0
    return FALSE;
1976
1977
0
  Stream_Read(s, macData, sizeof(macData));
1978
0
  if (!license_decrypt_and_check_MAC(license, license->EncryptedPlatformChallenge->data,
1979
0
                                     license->EncryptedPlatformChallenge->length,
1980
0
                                     license->PlatformChallenge, macData))
1981
0
    return FALSE;
1982
1983
#ifdef WITH_DEBUG_LICENSE
1984
  WLog_DBG(TAG, "ConnectFlags: 0x%08" PRIX32 "", ConnectFlags);
1985
  WLog_DBG(TAG, "EncryptedPlatformChallenge:");
1986
  winpr_HexDump(TAG, WLOG_DEBUG, license->EncryptedPlatformChallenge->data,
1987
                license->EncryptedPlatformChallenge->length);
1988
  WLog_DBG(TAG, "PlatformChallenge:");
1989
  winpr_HexDump(TAG, WLOG_DEBUG, license->PlatformChallenge->data,
1990
                license->PlatformChallenge->length);
1991
  WLog_DBG(TAG, "MacData:");
1992
  winpr_HexDump(TAG, WLOG_DEBUG, macData, sizeof(macData));
1993
#endif
1994
0
  return TRUE;
1995
0
}
1996
1997
BOOL license_send_error_alert(rdpLicense* license, UINT32 dwErrorCode, UINT32 dwStateTransition,
1998
                              const LICENSE_BLOB* info)
1999
0
{
2000
0
  wStream* s = license_send_stream_init(license);
2001
2002
0
  if (!s)
2003
0
    goto fail;
2004
2005
0
  if (!license_check_stream_capacity(s, 8, "license error alert"))
2006
0
    goto fail;
2007
0
  Stream_Write_UINT32(s, dwErrorCode);
2008
0
  Stream_Write_UINT32(s, dwStateTransition);
2009
2010
0
  if (info)
2011
0
  {
2012
0
    if (!license_write_binary_blob(s, info))
2013
0
      goto fail;
2014
0
  }
2015
2016
0
  return license_send(license, s, ERROR_ALERT);
2017
0
fail:
2018
0
  Stream_Release(s);
2019
0
  return FALSE;
2020
0
}
2021
2022
BOOL license_send_platform_challenge_packet(rdpLicense* license)
2023
0
{
2024
0
  wStream* s = license_send_stream_init(license);
2025
2026
0
  if (!s)
2027
0
    goto fail;
2028
2029
0
  DEBUG_LICENSE("Receiving Platform Challenge Packet");
2030
2031
0
  if (!license_check_stream_capacity(s, 4, "license platform challenge"))
2032
0
    goto fail;
2033
2034
0
  Stream_Zero(s, 4); /* ConnectFlags, Reserved (4 bytes) */
2035
2036
  /* EncryptedPlatformChallenge */
2037
0
  if (!license_write_binary_blob(s, license->EncryptedPlatformChallenge))
2038
0
    goto fail;
2039
2040
  /* MACData (16 bytes) */
2041
0
  if (!license_check_stream_length(s, sizeof(license->MACData),
2042
0
                                   "license platform challenge::MAC"))
2043
0
    goto fail;
2044
2045
0
  Stream_Write(s, license->MACData, sizeof(license->MACData));
2046
2047
0
  return license_send(license, s, PLATFORM_CHALLENGE);
2048
0
fail:
2049
0
  Stream_Release(s);
2050
0
  return FALSE;
2051
0
}
2052
2053
static BOOL license_read_encrypted_blob(const rdpLicense* license, wStream* s, LICENSE_BLOB* target)
2054
0
{
2055
0
  UINT16 wBlobType = 0;
2056
0
  UINT16 wBlobLen = 0;
2057
2058
0
  WINPR_ASSERT(license);
2059
0
  WINPR_ASSERT(target);
2060
2061
0
  if (!license_check_stream_length(s, 4, "license encrypted blob"))
2062
0
    return FALSE;
2063
2064
0
  Stream_Read_UINT16(s, wBlobType);
2065
0
  if (wBlobType != BB_ENCRYPTED_DATA_BLOB)
2066
0
  {
2067
0
    WLog_WARN(
2068
0
        TAG,
2069
0
        "expecting BB_ENCRYPTED_DATA_BLOB blob, probably a windows 2003 server, continuing...");
2070
0
  }
2071
2072
0
  Stream_Read_UINT16(s, wBlobLen);
2073
2074
0
  BYTE* encryptedData = Stream_Pointer(s);
2075
0
  if (!Stream_SafeSeek(s, wBlobLen))
2076
0
  {
2077
0
    WLog_WARN(TAG,
2078
0
              "short license encrypted blob::length, expected %" PRIu16 " bytes, got %" PRIuz,
2079
0
              wBlobLen, Stream_GetRemainingLength(s));
2080
0
    return FALSE;
2081
0
  }
2082
2083
0
  return license_rc4_with_licenseKey(license, encryptedData, wBlobLen, target);
2084
0
}
2085
2086
/**
2087
 * Read a NEW_LICENSE packet.
2088
 * msdn{cc241926}
2089
 * @param license license module
2090
 * @param s stream
2091
 */
2092
2093
BOOL license_read_new_or_upgrade_license_packet(rdpLicense* license, wStream* s)
2094
0
{
2095
0
  UINT32 os_major = 0;
2096
0
  UINT32 os_minor = 0;
2097
0
  UINT32 cbScope = 0;
2098
0
  UINT32 cbCompanyName = 0;
2099
0
  UINT32 cbProductId = 0;
2100
0
  UINT32 cbLicenseInfo = 0;
2101
0
  wStream sbuffer = { 0 };
2102
0
  wStream* licenseStream = NULL;
2103
0
  BOOL ret = FALSE;
2104
0
  BYTE computedMac[16] = { 0 };
2105
0
  const BYTE* readMac = NULL;
2106
2107
0
  WINPR_ASSERT(license);
2108
2109
0
  DEBUG_LICENSE("Receiving Server New/Upgrade License Packet");
2110
2111
0
  LICENSE_BLOB* calBlob = license_new_binary_blob(BB_DATA_BLOB);
2112
0
  if (!calBlob)
2113
0
    return FALSE;
2114
2115
  /* EncryptedLicenseInfo */
2116
0
  if (!license_read_encrypted_blob(license, s, calBlob))
2117
0
    goto fail;
2118
2119
  /* compute MAC and check it */
2120
0
  readMac = Stream_Pointer(s);
2121
0
  if (!Stream_SafeSeek(s, sizeof(computedMac)))
2122
0
  {
2123
0
    WLog_WARN(TAG, "short license new/upgrade, expected 16 bytes, got %" PRIuz,
2124
0
              Stream_GetRemainingLength(s));
2125
0
    goto fail;
2126
0
  }
2127
2128
0
  if (!security_mac_data(license->MacSaltKey, sizeof(license->MacSaltKey), calBlob->data,
2129
0
                         calBlob->length, computedMac, sizeof(computedMac)))
2130
0
    goto fail;
2131
2132
0
  if (memcmp(computedMac, readMac, sizeof(computedMac)) != 0)
2133
0
  {
2134
0
    WLog_ERR(TAG, "new or upgrade license MAC mismatch");
2135
0
    goto fail;
2136
0
  }
2137
2138
0
  licenseStream = Stream_StaticConstInit(&sbuffer, calBlob->data, calBlob->length);
2139
0
  if (!licenseStream)
2140
0
  {
2141
0
    WLog_ERR(TAG, "license::blob::data=%p, license::blob::length=%" PRIu16, calBlob->data,
2142
0
             calBlob->length);
2143
0
    goto fail;
2144
0
  }
2145
2146
0
  if (!license_check_stream_length(licenseStream, 8, "license new/upgrade::blob::version"))
2147
0
    goto fail;
2148
2149
0
  Stream_Read_UINT16(licenseStream, os_minor);
2150
0
  Stream_Read_UINT16(licenseStream, os_major);
2151
2152
0
  WLog_DBG(TAG, "Version: %" PRIu16 ".%" PRIu16, os_major, os_minor);
2153
2154
  /* Scope */
2155
0
  Stream_Read_UINT32(licenseStream, cbScope);
2156
0
  if (!license_check_stream_length(licenseStream, cbScope, "license new/upgrade::blob::scope"))
2157
0
    goto fail;
2158
2159
#ifdef WITH_DEBUG_LICENSE
2160
  WLog_DBG(TAG, "Scope:");
2161
  winpr_HexDump(TAG, WLOG_DEBUG, Stream_Pointer(licenseStream), cbScope);
2162
#endif
2163
0
  Stream_Seek(licenseStream, cbScope);
2164
2165
  /* CompanyName */
2166
0
  if (!license_check_stream_length(licenseStream, 4, "license new/upgrade::blob::cbCompanyName"))
2167
0
    goto fail;
2168
2169
0
  Stream_Read_UINT32(licenseStream, cbCompanyName);
2170
0
  if (!license_check_stream_length(licenseStream, cbCompanyName,
2171
0
                                   "license new/upgrade::blob::CompanyName"))
2172
0
    goto fail;
2173
2174
#ifdef WITH_DEBUG_LICENSE
2175
  WLog_DBG(TAG, "Company name:");
2176
  winpr_HexDump(TAG, WLOG_DEBUG, Stream_Pointer(licenseStream), cbCompanyName);
2177
#endif
2178
0
  Stream_Seek(licenseStream, cbCompanyName);
2179
2180
  /* productId */
2181
0
  if (!license_check_stream_length(licenseStream, 4, "license new/upgrade::blob::cbProductId"))
2182
0
    goto fail;
2183
2184
0
  Stream_Read_UINT32(licenseStream, cbProductId);
2185
2186
0
  if (!license_check_stream_length(licenseStream, cbProductId,
2187
0
                                   "license new/upgrade::blob::ProductId"))
2188
0
    goto fail;
2189
2190
#ifdef WITH_DEBUG_LICENSE
2191
  WLog_DBG(TAG, "Product id:");
2192
  winpr_HexDump(TAG, WLOG_DEBUG, Stream_Pointer(licenseStream), cbProductId);
2193
#endif
2194
0
  Stream_Seek(licenseStream, cbProductId);
2195
2196
  /* licenseInfo */
2197
0
  if (!license_check_stream_length(licenseStream, 4, "license new/upgrade::blob::cbLicenseInfo"))
2198
0
    goto fail;
2199
2200
0
  Stream_Read_UINT32(licenseStream, cbLicenseInfo);
2201
0
  if (!license_check_stream_length(licenseStream, cbLicenseInfo,
2202
0
                                   "license new/upgrade::blob::LicenseInfo"))
2203
0
    goto fail;
2204
2205
0
  license->type = LICENSE_TYPE_ISSUED;
2206
0
  ret = license_set_state(license, LICENSE_STATE_COMPLETED);
2207
2208
0
  if (!license->rdp->settings->OldLicenseBehaviour)
2209
0
    ret = saveCal(license->rdp->settings, Stream_Pointer(licenseStream), cbLicenseInfo,
2210
0
                  license->rdp->settings->ClientHostname);
2211
2212
0
fail:
2213
0
  license_free_binary_blob(calBlob);
2214
0
  return ret;
2215
0
}
2216
2217
/**
2218
 * Read an ERROR_ALERT packet.
2219
 * msdn{cc240482}
2220
 * @param license license module
2221
 * @param s stream
2222
 */
2223
2224
BOOL license_read_error_alert_packet(rdpLicense* license, wStream* s)
2225
0
{
2226
0
  UINT32 dwErrorCode = 0;
2227
0
  UINT32 dwStateTransition = 0;
2228
2229
0
  WINPR_ASSERT(license);
2230
0
  WINPR_ASSERT(license->rdp);
2231
2232
0
  if (!license_check_stream_length(s, 8ul, "error alert"))
2233
0
    return FALSE;
2234
2235
0
  Stream_Read_UINT32(s, dwErrorCode);       /* dwErrorCode (4 bytes) */
2236
0
  Stream_Read_UINT32(s, dwStateTransition); /* dwStateTransition (4 bytes) */
2237
2238
0
  if (!license_read_binary_blob(s, license->ErrorInfo)) /* bbErrorInfo */
2239
0
    return FALSE;
2240
2241
#ifdef WITH_DEBUG_LICENSE
2242
  WLog_DBG(TAG, "dwErrorCode: %s, dwStateTransition: %s", error_codes[dwErrorCode],
2243
           state_transitions[dwStateTransition]);
2244
#endif
2245
2246
0
  if (dwErrorCode == STATUS_VALID_CLIENT)
2247
0
  {
2248
0
    license->type = LICENSE_TYPE_NONE;
2249
0
    return license_set_state(license, LICENSE_STATE_COMPLETED);
2250
0
  }
2251
2252
0
  switch (dwStateTransition)
2253
0
  {
2254
0
    case ST_TOTAL_ABORT:
2255
0
      license_set_state(license, LICENSE_STATE_ABORTED);
2256
0
      break;
2257
0
    case ST_NO_TRANSITION:
2258
0
      license_set_state(license, LICENSE_STATE_COMPLETED);
2259
0
      break;
2260
0
    case ST_RESET_PHASE_TO_START:
2261
0
      license_set_state(license, LICENSE_STATE_CONFIGURED);
2262
0
      break;
2263
0
    case ST_RESEND_LAST_MESSAGE:
2264
0
      break;
2265
0
    default:
2266
0
      break;
2267
0
  }
2268
2269
0
  return TRUE;
2270
0
}
2271
2272
/**
2273
 * Write a NEW_LICENSE_REQUEST packet.
2274
 * msdn{cc241918}
2275
 * @param license license module
2276
 * @param s stream
2277
 */
2278
2279
BOOL license_write_new_license_request_packet(const rdpLicense* license, wStream* s)
2280
0
{
2281
0
  WINPR_ASSERT(license);
2282
2283
0
  const rdpCertInfo* info = freerdp_certificate_get_info(license->certificate);
2284
0
  if (!info)
2285
0
    return FALSE;
2286
2287
0
  if (!license_check_stream_capacity(s, 8 + sizeof(license->ClientRandom), "License Request"))
2288
0
    return FALSE;
2289
2290
0
  Stream_Write_UINT32(s,
2291
0
                      license->PreferredKeyExchangeAlg); /* PreferredKeyExchangeAlg (4 bytes) */
2292
0
  Stream_Write_UINT32(s, license->PlatformId);           /* PlatformId (4 bytes) */
2293
0
  Stream_Write(s, license->ClientRandom,
2294
0
               sizeof(license->ClientRandom)); /* ClientRandom (32 bytes) */
2295
2296
0
  if (/* EncryptedPremasterSecret */
2297
0
      !license_write_encrypted_premaster_secret_blob(s, license->EncryptedPremasterSecret,
2298
0
                                                     info->ModulusLength) ||
2299
      /* ClientUserName */
2300
0
      !license_write_binary_blob(s, license->ClientUserName) ||
2301
      /* ClientMachineName */
2302
0
      !license_write_binary_blob(s, license->ClientMachineName))
2303
0
  {
2304
0
    return FALSE;
2305
0
  }
2306
2307
#ifdef WITH_DEBUG_LICENSE
2308
  WLog_DBG(TAG, "PreferredKeyExchangeAlg: 0x%08" PRIX32 "", license->PreferredKeyExchangeAlg);
2309
  WLog_DBG(TAG, "ClientRandom:");
2310
  winpr_HexDump(TAG, WLOG_DEBUG, license->ClientRandom, sizeof(license->ClientRandom));
2311
  WLog_DBG(TAG, "EncryptedPremasterSecret");
2312
  winpr_HexDump(TAG, WLOG_DEBUG, license->EncryptedPremasterSecret->data,
2313
                license->EncryptedPremasterSecret->length);
2314
  WLog_DBG(TAG, "ClientUserName (%" PRIu16 "): %s", license->ClientUserName->length,
2315
           (char*)license->ClientUserName->data);
2316
  WLog_DBG(TAG, "ClientMachineName (%" PRIu16 "): %s", license->ClientMachineName->length,
2317
           (char*)license->ClientMachineName->data);
2318
#endif
2319
0
  return TRUE;
2320
0
}
2321
2322
BOOL license_read_new_license_request_packet(rdpLicense* license, wStream* s)
2323
0
{
2324
0
  UINT32 PreferredKeyExchangeAlg = 0;
2325
2326
0
  WINPR_ASSERT(license);
2327
2328
0
  if (!license_check_stream_length(s, 8ull + sizeof(license->ClientRandom),
2329
0
                                   "new license request"))
2330
0
    return FALSE;
2331
2332
0
  Stream_Read_UINT32(s, PreferredKeyExchangeAlg); /* PreferredKeyExchangeAlg (4 bytes) */
2333
0
  if (!license_check_preferred_alg(license, PreferredKeyExchangeAlg, "new license request"))
2334
0
    return FALSE;
2335
2336
0
  Stream_Read_UINT32(s, license->PlatformId);                  /* PlatformId (4 bytes) */
2337
0
  Stream_Read(s, license->ClientRandom,
2338
0
              sizeof(license->ClientRandom)); /* ClientRandom (32 bytes) */
2339
2340
  /* EncryptedPremasterSecret */
2341
0
  UINT32 ModulusLength = 0;
2342
0
  if (!license_read_encrypted_premaster_secret_blob(s, license->EncryptedPremasterSecret,
2343
0
                                                    &ModulusLength))
2344
0
    return FALSE;
2345
2346
0
  const rdpCertInfo* info = freerdp_certificate_get_info(license->certificate);
2347
0
  if (!info)
2348
0
    WLog_WARN(TAG, "Missing license certificate, skipping ModulusLength checks");
2349
0
  else if (ModulusLength != info->ModulusLength)
2350
0
  {
2351
0
    WLog_WARN(TAG,
2352
0
              "EncryptedPremasterSecret expected to be %" PRIu32 " bytes, but read %" PRIu32
2353
0
              " bytes",
2354
0
              info->ModulusLength, ModulusLength);
2355
0
    return FALSE;
2356
0
  }
2357
2358
  /* ClientUserName */
2359
0
  if (!license_read_binary_blob(s, license->ClientUserName))
2360
0
    return FALSE;
2361
  /* ClientMachineName */
2362
0
  if (!license_read_binary_blob(s, license->ClientMachineName))
2363
0
    return FALSE;
2364
2365
0
  return TRUE;
2366
0
}
2367
2368
/**
2369
 * Send a NEW_LICENSE_REQUEST packet.
2370
 * msdn{cc241918}
2371
 * @param license license module
2372
 */
2373
2374
BOOL license_answer_license_request(rdpLicense* license)
2375
0
{
2376
0
  wStream* s = NULL;
2377
0
  BYTE* license_data = NULL;
2378
0
  size_t license_size = 0;
2379
0
  BOOL status = 0;
2380
0
  char* username = NULL;
2381
2382
0
  WINPR_ASSERT(license);
2383
0
  WINPR_ASSERT(license->rdp);
2384
0
  WINPR_ASSERT(license->rdp->settings);
2385
2386
0
  if (!license->rdp->settings->OldLicenseBehaviour)
2387
0
    license_data = loadCalFile(license->rdp->settings, license->rdp->settings->ClientHostname,
2388
0
                               &license_size);
2389
2390
0
  if (license_data)
2391
0
  {
2392
0
    LICENSE_BLOB* calBlob = NULL;
2393
0
    BYTE signature[LICENSING_ENCRYPTION_KEY_LENGTH] = { 0 };
2394
2395
0
    DEBUG_LICENSE("Sending Saved License Packet");
2396
2397
0
    WINPR_ASSERT(license->EncryptedHardwareId);
2398
0
    license->EncryptedHardwareId->type = BB_ENCRYPTED_DATA_BLOB;
2399
0
    if (!license_encrypt_and_MAC(license, license->HardwareId, sizeof(license->HardwareId),
2400
0
                                 license->EncryptedHardwareId, signature, sizeof(signature)))
2401
0
    {
2402
0
      free(license_data);
2403
0
      return FALSE;
2404
0
    }
2405
2406
0
    calBlob = license_new_binary_blob(BB_DATA_BLOB);
2407
0
    if (!calBlob)
2408
0
    {
2409
0
      free(license_data);
2410
0
      return FALSE;
2411
0
    }
2412
0
    calBlob->data = license_data;
2413
0
    WINPR_ASSERT(license_size <= UINT16_MAX);
2414
0
    calBlob->length = (UINT16)license_size;
2415
2416
0
    status = license_send_license_info(license, calBlob, signature, sizeof(signature));
2417
0
    license_free_binary_blob(calBlob);
2418
2419
0
    return status;
2420
0
  }
2421
2422
0
  DEBUG_LICENSE("Sending New License Packet");
2423
2424
0
  s = license_send_stream_init(license);
2425
0
  if (!s)
2426
0
    return FALSE;
2427
0
  if (license->rdp->settings->Username != NULL)
2428
0
    username = license->rdp->settings->Username;
2429
0
  else
2430
0
    username = "username";
2431
2432
0
  {
2433
0
    WINPR_ASSERT(license->ClientUserName);
2434
0
    const size_t len = strlen(username) + 1;
2435
0
    WINPR_ASSERT(len <= UINT16_MAX);
2436
2437
0
    license->ClientUserName->data = (BYTE*)username;
2438
0
    license->ClientUserName->length = (UINT16)len;
2439
0
  }
2440
2441
0
  {
2442
0
    WINPR_ASSERT(license->ClientMachineName);
2443
0
    const size_t len = strlen(license->rdp->settings->ClientHostname) + 1;
2444
0
    WINPR_ASSERT(len <= UINT16_MAX);
2445
2446
0
    license->ClientMachineName->data = (BYTE*)license->rdp->settings->ClientHostname;
2447
0
    license->ClientMachineName->length = (UINT16)len;
2448
0
  }
2449
0
  status = license_write_new_license_request_packet(license, s);
2450
2451
0
  WINPR_ASSERT(license->ClientUserName);
2452
0
  license->ClientUserName->data = NULL;
2453
0
  license->ClientUserName->length = 0;
2454
2455
0
  WINPR_ASSERT(license->ClientMachineName);
2456
0
  license->ClientMachineName->data = NULL;
2457
0
  license->ClientMachineName->length = 0;
2458
2459
0
  if (!status)
2460
0
  {
2461
0
    Stream_Release(s);
2462
0
    return FALSE;
2463
0
  }
2464
2465
0
  return license_send(license, s, NEW_LICENSE_REQUEST);
2466
0
}
2467
2468
/**
2469
 * Send Client Challenge Response Packet.
2470
 * msdn{cc241922}
2471
 * @param license license module
2472
 */
2473
2474
BOOL license_send_platform_challenge_response(rdpLicense* license)
2475
0
{
2476
0
  wStream* s = license_send_stream_init(license);
2477
0
  wStream* challengeRespData = NULL;
2478
0
  BYTE* buffer = NULL;
2479
0
  BOOL status = 0;
2480
2481
0
  WINPR_ASSERT(license);
2482
0
  WINPR_ASSERT(license->PlatformChallenge);
2483
0
  WINPR_ASSERT(license->MacSaltKey);
2484
0
  WINPR_ASSERT(license->EncryptedPlatformChallenge);
2485
0
  WINPR_ASSERT(license->EncryptedHardwareId);
2486
2487
0
  DEBUG_LICENSE("Sending Platform Challenge Response Packet");
2488
2489
0
  license->EncryptedPlatformChallenge->type = BB_DATA_BLOB;
2490
2491
  /* prepare the PLATFORM_CHALLENGE_RESPONSE_DATA */
2492
0
  challengeRespData = Stream_New(NULL, 8 + license->PlatformChallenge->length);
2493
0
  if (!challengeRespData)
2494
0
    return FALSE;
2495
0
  Stream_Write_UINT16(challengeRespData, PLATFORM_CHALLENGE_RESPONSE_VERSION); /* wVersion */
2496
0
  Stream_Write_UINT16(challengeRespData, license->ClientType);                 /* wClientType */
2497
0
  Stream_Write_UINT16(challengeRespData, license->LicenseDetailLevel); /* wLicenseDetailLevel */
2498
0
  Stream_Write_UINT16(challengeRespData, license->PlatformChallenge->length); /* cbChallenge */
2499
0
  Stream_Write(challengeRespData, license->PlatformChallenge->data,
2500
0
               license->PlatformChallenge->length); /* pbChallenge */
2501
0
  Stream_SealLength(challengeRespData);
2502
2503
  /* compute MAC of PLATFORM_CHALLENGE_RESPONSE_DATA + HWID */
2504
0
  const size_t length = Stream_Length(challengeRespData) + sizeof(license->HardwareId);
2505
0
  buffer = (BYTE*)malloc(length);
2506
0
  if (!buffer)
2507
0
  {
2508
0
    Stream_Free(challengeRespData, TRUE);
2509
0
    return FALSE;
2510
0
  }
2511
2512
0
  CopyMemory(buffer, Stream_Buffer(challengeRespData), Stream_Length(challengeRespData));
2513
0
  CopyMemory(&buffer[Stream_Length(challengeRespData)], license->HardwareId,
2514
0
             sizeof(license->HardwareId));
2515
0
  status = security_mac_data(license->MacSaltKey, sizeof(license->MacSaltKey), buffer, length,
2516
0
                             license->MACData, sizeof(license->MACData));
2517
0
  free(buffer);
2518
2519
0
  if (!status)
2520
0
  {
2521
0
    Stream_Free(challengeRespData, TRUE);
2522
0
    return FALSE;
2523
0
  }
2524
2525
0
  license->EncryptedHardwareId->type = BB_ENCRYPTED_DATA_BLOB;
2526
0
  if (!license_rc4_with_licenseKey(license, license->HardwareId, sizeof(license->HardwareId),
2527
0
                                   license->EncryptedHardwareId))
2528
0
  {
2529
0
    Stream_Free(challengeRespData, TRUE);
2530
0
    return FALSE;
2531
0
  }
2532
2533
0
  status = license_rc4_with_licenseKey(license, Stream_Buffer(challengeRespData),
2534
0
                                       Stream_Length(challengeRespData),
2535
0
                                       license->EncryptedPlatformChallengeResponse);
2536
0
  Stream_Free(challengeRespData, TRUE);
2537
0
  if (!status)
2538
0
    return FALSE;
2539
2540
#ifdef WITH_DEBUG_LICENSE
2541
  WLog_DBG(TAG, "LicensingEncryptionKey:");
2542
  winpr_HexDump(TAG, WLOG_DEBUG, license->LicensingEncryptionKey, 16);
2543
  WLog_DBG(TAG, "HardwareId:");
2544
  winpr_HexDump(TAG, WLOG_DEBUG, license->HardwareId, sizeof(license->HardwareId));
2545
  WLog_DBG(TAG, "EncryptedHardwareId:");
2546
  winpr_HexDump(TAG, WLOG_DEBUG, license->EncryptedHardwareId->data,
2547
                license->EncryptedHardwareId->length);
2548
#endif
2549
0
  if (license_write_client_platform_challenge_response(license, s))
2550
0
    return license_send(license, s, PLATFORM_CHALLENGE_RESPONSE);
2551
2552
0
  Stream_Release(s);
2553
0
  return FALSE;
2554
0
}
2555
2556
BOOL license_read_platform_challenge_response(rdpLicense* license, wStream* s)
2557
0
{
2558
0
  UINT16 wVersion = 0;
2559
0
  UINT16 cbChallenge = 0;
2560
0
  const BYTE* pbChallenge = NULL;
2561
0
2562
0
  WINPR_ASSERT(license);
2563
0
  WINPR_ASSERT(license->PlatformChallenge);
2564
0
  WINPR_ASSERT(license->MacSaltKey);
2565
0
  WINPR_ASSERT(license->EncryptedPlatformChallenge);
2566
0
  WINPR_ASSERT(license->EncryptedHardwareId);
2567
0
2568
0
  DEBUG_LICENSE("Receiving Platform Challenge Response Packet");
2569
0
2570
0
  if (!license_check_stream_length(s, 8, "PLATFORM_CHALLENGE_RESPONSE_DATA"))
2571
0
    return FALSE;
2572
0
2573
0
  Stream_Read_UINT16(s, wVersion);
2574
0
  if (wVersion != PLATFORM_CHALLENGE_RESPONSE_VERSION)
2575
0
  {
2576
0
    WLog_WARN(TAG,
2577
0
              "Invalid PLATFORM_CHALLENGE_RESPONSE_DATA::wVersion 0x%04" PRIx16
2578
0
              ", expected 0x04" PRIx16,
2579
0
              wVersion, PLATFORM_CHALLENGE_RESPONSE_VERSION);
2580
0
    return FALSE;
2581
0
  }
2582
0
  Stream_Read_UINT16(s, license->ClientType);
2583
0
  Stream_Read_UINT16(s, license->LicenseDetailLevel);
2584
0
  Stream_Read_UINT16(s, cbChallenge);
2585
0
2586
0
  if (!license_check_stream_length(s, cbChallenge,
2587
0
                                   "PLATFORM_CHALLENGE_RESPONSE_DATA::pbChallenge"))
2588
0
    return FALSE;
2589
0
2590
0
  pbChallenge = Stream_Pointer(s);
2591
0
  if (!license_read_binary_blob_data(license->EncryptedPlatformChallengeResponse, BB_DATA_BLOB,
2592
0
                                     pbChallenge, cbChallenge))
2593
0
    return FALSE;
2594
0
  return Stream_SafeSeek(s, cbChallenge);
2595
0
}
2596
2597
BOOL license_write_client_platform_challenge_response(rdpLicense* license, wStream* s)
2598
0
{
2599
0
  WINPR_ASSERT(license);
2600
2601
0
  if (!license_write_binary_blob(s, license->EncryptedPlatformChallengeResponse))
2602
0
    return FALSE;
2603
0
  if (!license_write_binary_blob(s, license->EncryptedHardwareId))
2604
0
    return FALSE;
2605
0
  if (!license_check_stream_capacity(s, sizeof(license->MACData),
2606
0
                                     "CLIENT_PLATFORM_CHALLENGE_RESPONSE::MACData"))
2607
0
    return FALSE;
2608
0
  Stream_Write(s, license->MACData, sizeof(license->MACData));
2609
0
  return TRUE;
2610
0
}
2611
2612
BOOL license_read_client_platform_challenge_response(rdpLicense* license, wStream* s)
2613
0
{
2614
0
  WINPR_ASSERT(license);
2615
2616
0
  if (!license_read_binary_blob(s, license->EncryptedPlatformChallengeResponse))
2617
0
    return FALSE;
2618
0
  if (!license_read_binary_blob(s, license->EncryptedHardwareId))
2619
0
    return FALSE;
2620
0
  if (!license_check_stream_length(s, sizeof(license->MACData),
2621
0
                                   "CLIENT_PLATFORM_CHALLENGE_RESPONSE::MACData"))
2622
0
    return FALSE;
2623
0
  Stream_Read(s, license->MACData, sizeof(license->MACData));
2624
0
  return TRUE;
2625
0
}
2626
2627
/**
2628
 * Send Server License Error - Valid Client Packet.
2629
 * msdn{cc241922}
2630
 *
2631
 * @param rdp A pointer to the context to use
2632
 *
2633
 * @return \b TRUE for success, \b FALSE otherwise
2634
 */
2635
2636
BOOL license_send_valid_client_error_packet(rdpRdp* rdp)
2637
0
{
2638
0
  WINPR_ASSERT(rdp);
2639
0
  rdpLicense* license = rdp->license;
2640
0
  WINPR_ASSERT(license);
2641
2642
0
  license->state = LICENSE_STATE_COMPLETED;
2643
0
  license->type = LICENSE_TYPE_NONE;
2644
0
  return license_send_error_alert(license, STATUS_VALID_CLIENT, ST_NO_TRANSITION,
2645
0
                                  license->ErrorInfo);
2646
0
}
2647
2648
/**
2649
 * Instantiate new license module.
2650
 * @param rdp RDP module
2651
 * @return new license module
2652
 */
2653
2654
rdpLicense* license_new(rdpRdp* rdp)
2655
14.9k
{
2656
14.9k
  rdpLicense* license = NULL;
2657
14.9k
  WINPR_ASSERT(rdp);
2658
2659
14.9k
  license = (rdpLicense*)calloc(1, sizeof(rdpLicense));
2660
14.9k
  if (!license)
2661
0
    return NULL;
2662
2663
14.9k
  license->PlatformId = PLATFORMID;
2664
14.9k
  license->ClientType = OTHER_PLATFORM_CHALLENGE_TYPE;
2665
14.9k
  license->LicenseDetailLevel = LICENSE_DETAIL_DETAIL;
2666
14.9k
  license->PreferredKeyExchangeAlg = KEY_EXCHANGE_ALG_RSA;
2667
14.9k
  license->rdp = rdp;
2668
2669
14.9k
  license_set_state(license, LICENSE_STATE_INITIAL);
2670
14.9k
  if (!(license->certificate = freerdp_certificate_new()))
2671
0
    goto out_error;
2672
14.9k
  if (!(license->ProductInfo = license_new_product_info()))
2673
0
    goto out_error;
2674
14.9k
  if (!(license->ErrorInfo = license_new_binary_blob(BB_ERROR_BLOB)))
2675
0
    goto out_error;
2676
14.9k
  if (!(license->LicenseInfo = license_new_binary_blob(BB_DATA_BLOB)))
2677
0
    goto out_error;
2678
14.9k
  if (!(license->KeyExchangeList = license_new_binary_blob(BB_KEY_EXCHG_ALG_BLOB)))
2679
0
    goto out_error;
2680
14.9k
  if (!(license->ServerCertificate = license_new_binary_blob(BB_CERTIFICATE_BLOB)))
2681
0
    goto out_error;
2682
14.9k
  if (!(license->ClientUserName = license_new_binary_blob(BB_CLIENT_USER_NAME_BLOB)))
2683
0
    goto out_error;
2684
14.9k
  if (!(license->ClientMachineName = license_new_binary_blob(BB_CLIENT_MACHINE_NAME_BLOB)))
2685
0
    goto out_error;
2686
14.9k
  if (!(license->PlatformChallenge = license_new_binary_blob(BB_ANY_BLOB)))
2687
0
    goto out_error;
2688
14.9k
  if (!(license->EncryptedPlatformChallenge = license_new_binary_blob(BB_ANY_BLOB)))
2689
0
    goto out_error;
2690
14.9k
  if (!(license->EncryptedPlatformChallengeResponse =
2691
14.9k
            license_new_binary_blob(BB_ENCRYPTED_DATA_BLOB)))
2692
0
    goto out_error;
2693
14.9k
  if (!(license->EncryptedPremasterSecret = license_new_binary_blob(BB_ANY_BLOB)))
2694
0
    goto out_error;
2695
14.9k
  if (!(license->EncryptedHardwareId = license_new_binary_blob(BB_ENCRYPTED_DATA_BLOB)))
2696
0
    goto out_error;
2697
14.9k
  if (!(license->EncryptedLicenseInfo = license_new_binary_blob(BB_ENCRYPTED_DATA_BLOB)))
2698
0
    goto out_error;
2699
14.9k
  if (!(license->ScopeList = license_new_scope_list()))
2700
0
    goto out_error;
2701
2702
14.9k
  license_generate_randoms(license);
2703
2704
14.9k
  return license;
2705
2706
0
out_error:
2707
0
  WINPR_PRAGMA_DIAG_PUSH
2708
0
  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
2709
0
  license_free(license);
2710
0
  WINPR_PRAGMA_DIAG_POP
2711
0
  return NULL;
2712
14.9k
}
2713
2714
/**
2715
 * Free license module.
2716
 * @param license license module to be freed
2717
 */
2718
2719
void license_free(rdpLicense* license)
2720
14.9k
{
2721
14.9k
  if (license)
2722
14.9k
  {
2723
14.9k
    freerdp_certificate_free(license->certificate);
2724
14.9k
    license_free_product_info(license->ProductInfo);
2725
14.9k
    license_free_binary_blob(license->ErrorInfo);
2726
14.9k
    license_free_binary_blob(license->LicenseInfo);
2727
14.9k
    license_free_binary_blob(license->KeyExchangeList);
2728
14.9k
    license_free_binary_blob(license->ServerCertificate);
2729
14.9k
    license_free_binary_blob(license->ClientUserName);
2730
14.9k
    license_free_binary_blob(license->ClientMachineName);
2731
14.9k
    license_free_binary_blob(license->PlatformChallenge);
2732
14.9k
    license_free_binary_blob(license->EncryptedPlatformChallenge);
2733
14.9k
    license_free_binary_blob(license->EncryptedPlatformChallengeResponse);
2734
14.9k
    license_free_binary_blob(license->EncryptedPremasterSecret);
2735
14.9k
    license_free_binary_blob(license->EncryptedHardwareId);
2736
14.9k
    license_free_binary_blob(license->EncryptedLicenseInfo);
2737
14.9k
    license_free_scope_list(license->ScopeList);
2738
14.9k
    free(license);
2739
14.9k
  }
2740
14.9k
}
2741
2742
LICENSE_STATE license_get_state(const rdpLicense* license)
2743
0
{
2744
0
  WINPR_ASSERT(license);
2745
0
  return license->state;
2746
0
}
2747
2748
LICENSE_TYPE license_get_type(const rdpLicense* license)
2749
0
{
2750
0
  WINPR_ASSERT(license);
2751
0
  return license->type;
2752
0
}
2753
2754
BOOL license_set_state(rdpLicense* license, LICENSE_STATE state)
2755
14.9k
{
2756
14.9k
  WINPR_ASSERT(license);
2757
14.9k
  license->state = state;
2758
14.9k
  switch (state)
2759
14.9k
  {
2760
0
    case LICENSE_STATE_COMPLETED:
2761
0
      break;
2762
0
    case LICENSE_STATE_ABORTED:
2763
14.9k
    default:
2764
14.9k
      license->type = LICENSE_TYPE_INVALID;
2765
14.9k
      break;
2766
14.9k
  }
2767
2768
14.9k
  return TRUE;
2769
14.9k
}
2770
2771
const char* license_get_state_string(LICENSE_STATE state)
2772
0
{
2773
0
  switch (state)
2774
0
  {
2775
0
    case LICENSE_STATE_INITIAL:
2776
0
      return "LICENSE_STATE_INITIAL";
2777
0
    case LICENSE_STATE_CONFIGURED:
2778
0
      return "LICENSE_STATE_CONFIGURED";
2779
0
    case LICENSE_STATE_REQUEST:
2780
0
      return "LICENSE_STATE_REQUEST";
2781
0
    case LICENSE_STATE_NEW_REQUEST:
2782
0
      return "LICENSE_STATE_NEW_REQUEST";
2783
0
    case LICENSE_STATE_PLATFORM_CHALLENGE:
2784
0
      return "LICENSE_STATE_PLATFORM_CHALLENGE";
2785
0
    case LICENSE_STATE_PLATFORM_CHALLENGE_RESPONSE:
2786
0
      return "LICENSE_STATE_PLATFORM_CHALLENGE_RESPONSE";
2787
0
    case LICENSE_STATE_COMPLETED:
2788
0
      return "LICENSE_STATE_COMPLETED";
2789
0
    case LICENSE_STATE_ABORTED:
2790
0
      return "LICENSE_STATE_ABORTED";
2791
0
    default:
2792
0
      return "LICENSE_STATE_UNKNOWN";
2793
0
  }
2794
0
}
2795
2796
BOOL license_server_send_request(rdpLicense* license)
2797
0
{
2798
0
  if (!license_ensure_state(license, LICENSE_STATE_CONFIGURED, LICENSE_REQUEST))
2799
0
    return FALSE;
2800
0
  if (!license_send_license_request_packet(license))
2801
0
    return FALSE;
2802
0
  return license_set_state(license, LICENSE_STATE_REQUEST);
2803
0
}
2804
2805
static BOOL license_set_string(const char* what, const char* value, BYTE** bdst, UINT32* dstLen)
2806
0
{
2807
0
  WINPR_ASSERT(what);
2808
0
  WINPR_ASSERT(value);
2809
0
  WINPR_ASSERT(bdst);
2810
0
  WINPR_ASSERT(dstLen);
2811
2812
0
  union
2813
0
  {
2814
0
    WCHAR** w;
2815
0
    BYTE** b;
2816
0
  } cnv;
2817
0
  cnv.b = bdst;
2818
2819
0
  size_t len = 0;
2820
0
  *cnv.w = ConvertUtf8ToWCharAlloc(value, &len);
2821
0
  if (!*cnv.w || (len > UINT32_MAX / sizeof(WCHAR)))
2822
0
  {
2823
0
    WLog_ERR(TAG, "license->ProductInfo: %s == %p || %" PRIu32 " > UINT32_MAX", what, *cnv.w,
2824
0
             len);
2825
0
    return FALSE;
2826
0
  }
2827
0
  *dstLen = (UINT32)(len * sizeof(WCHAR));
2828
0
  return TRUE;
2829
0
}
2830
2831
BOOL license_server_configure(rdpLicense* license)
2832
0
{
2833
0
  wStream* s = NULL;
2834
0
  UINT32 algs[] = { KEY_EXCHANGE_ALG_RSA };
2835
2836
0
  WINPR_ASSERT(license);
2837
0
  WINPR_ASSERT(license->rdp);
2838
2839
0
  const rdpSettings* settings = license->rdp->settings;
2840
2841
0
  const char* CompanyName =
2842
0
      freerdp_settings_get_string(settings, FreeRDP_ServerLicenseCompanyName);
2843
2844
0
  const char* ProductName =
2845
0
      freerdp_settings_get_string(settings, FreeRDP_ServerLicenseProductName);
2846
0
  const UINT32 ProductVersion =
2847
0
      freerdp_settings_get_uint32(settings, FreeRDP_ServerLicenseProductVersion);
2848
0
  const UINT32 issuerCount =
2849
0
      freerdp_settings_get_uint32(settings, FreeRDP_ServerLicenseProductIssuersCount);
2850
0
  const char* const* issuers = (const char* const*)freerdp_settings_get_pointer(
2851
0
      settings, FreeRDP_ServerLicenseProductIssuers);
2852
2853
0
  WINPR_ASSERT(CompanyName);
2854
0
  WINPR_ASSERT(ProductName);
2855
0
  WINPR_ASSERT(ProductVersion > 0);
2856
0
  WINPR_ASSERT(issuers || (issuerCount == 0));
2857
2858
0
  if (!license_ensure_state(license, LICENSE_STATE_INITIAL, LICENSE_REQUEST))
2859
0
    return FALSE;
2860
2861
0
  license->ProductInfo->dwVersion = ProductVersion;
2862
0
  if (!license_set_string("pbCompanyName", CompanyName, &license->ProductInfo->pbCompanyName,
2863
0
                          &license->ProductInfo->cbCompanyName))
2864
0
    return FALSE;
2865
2866
0
  if (!license_set_string("pbProductId", ProductName, &license->ProductInfo->pbProductId,
2867
0
                          &license->ProductInfo->cbProductId))
2868
0
    return FALSE;
2869
2870
0
  if (!license_read_binary_blob_data(license->KeyExchangeList, BB_KEY_EXCHG_ALG_BLOB, algs,
2871
0
                                     sizeof(algs)))
2872
0
    return FALSE;
2873
2874
0
  if (!freerdp_certificate_read_server_cert(license->certificate, settings->ServerCertificate,
2875
0
                                            settings->ServerCertificateLength))
2876
0
    return FALSE;
2877
2878
0
  s = Stream_New(NULL, 1024);
2879
0
  if (!s)
2880
0
    return FALSE;
2881
0
  else
2882
0
  {
2883
0
    BOOL r = FALSE;
2884
0
    SSIZE_T res =
2885
0
        freerdp_certificate_write_server_cert(license->certificate, CERT_CHAIN_VERSION_2, s);
2886
0
    if (res >= 0)
2887
0
      r = license_read_binary_blob_data(license->ServerCertificate, BB_CERTIFICATE_BLOB,
2888
0
                                        Stream_Buffer(s), Stream_GetPosition(s));
2889
2890
0
    Stream_Free(s, TRUE);
2891
0
    if (!r)
2892
0
      return FALSE;
2893
0
  }
2894
2895
0
  if (!license_scope_list_resize(license->ScopeList, issuerCount))
2896
0
    return FALSE;
2897
0
  for (size_t x = 0; x < issuerCount; x++)
2898
0
  {
2899
0
    LICENSE_BLOB* blob = license->ScopeList->array[x];
2900
0
    const char* name = issuers[x];
2901
0
    const size_t length = strnlen(name, UINT16_MAX) + 1;
2902
0
    if ((length == 0) || (length > UINT16_MAX))
2903
0
    {
2904
0
      WLog_WARN(TAG,
2905
0
                "%s: Invalid issuer at position %" PRIuz ": length 0 < %" PRIuz " <= %" PRIu16
2906
0
                " ['%s']",
2907
0
                x, length, UINT16_MAX, name);
2908
0
      return FALSE;
2909
0
    }
2910
0
    if (!license_read_binary_blob_data(blob, BB_SCOPE_BLOB, name, length))
2911
0
      return FALSE;
2912
0
  }
2913
2914
0
  return license_set_state(license, LICENSE_STATE_CONFIGURED);
2915
0
}
2916
2917
rdpLicense* license_get(rdpContext* context)
2918
0
{
2919
0
  WINPR_ASSERT(context);
2920
0
  WINPR_ASSERT(context->rdp);
2921
0
  return context->rdp->license;
2922
0
}