Coverage Report

Created: 2026-07-25 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/libcli/security/trust_forest_info.c
Line
Count
Source
1
/*
2
   Unix SMB/CIFS implementation.
3
   Authentication utility functions
4
   Copyright (C) Stefan Metzmacher 2018,2025
5
6
   This program is free software; you can redistribute it and/or modify
7
   it under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 3 of the License, or
9
   (at your option) any later version.
10
11
   This program is distributed in the hope that it will be useful,
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
   GNU General Public License for more details.
15
16
   You should have received a copy of the GNU General Public License
17
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
*/
19
20
#include "replace.h"
21
#include "libcli/security/security.h"
22
#include "librpc/gen_ndr/ndr_drsblobs.h"
23
#include "librpc/gen_ndr/ndr_lsa.h"
24
#include "lib/util/talloc_stack.h"
25
#include "lib/util/bytearray.h"
26
#include "lib/util/dns_cmp.h"
27
28
static NTSTATUS trust_forest_record_from_lsa(TALLOC_CTX *mem_ctx,
29
        const struct lsa_ForestTrustRecord2 *lftr,
30
        struct ForestTrustInfoRecord *ftr)
31
0
{
32
0
  struct ForestTrustString *str = NULL;
33
0
  const struct lsa_StringLarge *lstr = NULL;
34
0
  const struct lsa_ForestTrustDomainInfo *linfo = NULL;
35
0
  struct ForestTrustDataDomainInfo *info = NULL;
36
0
  DATA_BLOB blob = { .length = 0, };
37
38
0
  if (lftr == NULL) {
39
0
    return NT_STATUS_INVALID_PARAMETER;
40
0
  }
41
42
0
  ftr->flags = lftr->flags;
43
0
  ftr->timestamp = lftr->time;
44
45
0
  switch (lftr->type) {
46
0
  case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
47
0
    ftr->type = FOREST_TRUST_TOP_LEVEL_NAME;
48
49
0
    lstr = &lftr->forest_trust_data.top_level_name;
50
0
    str = &ftr->data.name;
51
52
0
    str->string = talloc_strdup(mem_ctx, lstr->string);
53
0
    if (str->string == NULL) {
54
0
      return NT_STATUS_NO_MEMORY;
55
0
    }
56
57
0
    return NT_STATUS_OK;
58
59
0
  case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
60
0
    ftr->type = FOREST_TRUST_TOP_LEVEL_NAME_EX;
61
62
0
    lstr = &lftr->forest_trust_data.top_level_name_ex;
63
0
    str = &ftr->data.name;
64
65
0
    str->string = talloc_strdup(mem_ctx, lstr->string);
66
0
    if (str->string == NULL) {
67
0
      return NT_STATUS_NO_MEMORY;
68
0
    }
69
70
0
    return NT_STATUS_OK;
71
72
0
  case LSA_FOREST_TRUST_DOMAIN_INFO:
73
0
    ftr->type = FOREST_TRUST_DOMAIN_INFO;
74
75
0
    linfo = &lftr->forest_trust_data.domain_info;
76
0
    info = &ftr->data.info;
77
78
0
    if (linfo->domain_sid == NULL) {
79
0
      return NT_STATUS_INVALID_PARAMETER;
80
0
    }
81
0
    info->sid = *linfo->domain_sid;
82
83
0
    lstr = &linfo->dns_domain_name;
84
0
    str = &info->dns_name;
85
0
    str->string = talloc_strdup(mem_ctx, lstr->string);
86
0
    if (str->string == NULL) {
87
0
      return NT_STATUS_NO_MEMORY;
88
0
    }
89
90
0
    lstr = &linfo->netbios_domain_name;
91
0
    str = &info->netbios_name;
92
0
    str->string = talloc_strdup(mem_ctx, lstr->string);
93
0
    if (str->string == NULL) {
94
0
      return NT_STATUS_NO_MEMORY;
95
0
    }
96
97
0
    return NT_STATUS_OK;
98
99
0
  case LSA_FOREST_TRUST_BINARY_DATA:
100
0
    ftr->type = FOREST_TRUST_BINARY_DATA;
101
102
0
    blob = data_blob_talloc_named(mem_ctx,
103
0
                lftr->forest_trust_data.data.data,
104
0
                lftr->forest_trust_data.data.length,
105
0
                "BINARY_DATA");
106
0
    if (blob.length != lftr->forest_trust_data.data.length) {
107
0
      return NT_STATUS_NO_MEMORY;
108
0
    }
109
0
    ftr->data.binary.data = blob.data;
110
0
    ftr->data.binary.size = blob.length;
111
112
0
    return NT_STATUS_OK;
113
114
0
  case LSA_FOREST_TRUST_SCANNER_INFO:
115
0
    ftr->type = FOREST_TRUST_SCANNER_INFO;
116
117
0
    linfo = &lftr->forest_trust_data.scanner_info;
118
0
    info = &ftr->data.scanner_info.info;
119
120
0
    ftr->data.scanner_info.sub_type = FOREST_TRUST_SCANNER_INFO;
121
122
0
    if (linfo->domain_sid != NULL) {
123
0
      info->sid = *linfo->domain_sid;
124
0
    } else {
125
0
      info->sid = (struct dom_sid) { .sid_rev_num = 0, };
126
0
    }
127
128
0
    lstr = &linfo->dns_domain_name;
129
0
    str = &info->dns_name;
130
0
    str->string = talloc_strdup(mem_ctx, lstr->string);
131
0
    if (str->string == NULL) {
132
0
      return NT_STATUS_NO_MEMORY;
133
0
    }
134
135
0
    lstr = &linfo->netbios_domain_name;
136
0
    str = &info->netbios_name;
137
0
    str->string = talloc_strdup(mem_ctx, lstr->string);
138
0
    if (str->string == NULL) {
139
0
      return NT_STATUS_NO_MEMORY;
140
0
    }
141
142
0
    return NT_STATUS_OK;
143
0
  }
144
145
0
  return NT_STATUS_NOT_SUPPORTED;
146
0
}
147
148
static NTSTATUS trust_forest_record_lsa_resolve_binary(TALLOC_CTX *mem_ctx,
149
        uint32_t flags,
150
        NTTIME time,
151
        const struct lsa_ForestTrustBinaryData *binary,
152
        struct lsa_ForestTrustRecord2 *lftr2)
153
0
{
154
0
  enum ForestTrustInfoRecordType sub_type = FOREST_TRUST_BINARY_DATA;
155
0
  DATA_BLOB blob = { .length = 0, };
156
157
0
  if (binary == NULL) {
158
0
    return NT_STATUS_INVALID_PARAMETER;
159
0
  }
160
161
  /*
162
   * Note 'binary' may points to
163
   * lftr2->forest_trust_data.data
164
   *
165
   * So we remember the relevant
166
   * information in blob and clear
167
   * the binary pointer in order
168
   * to avoid touching it again.
169
   *
170
   * Because we likely change
171
   * the lftr2->forest_trust_data union
172
   */
173
0
  blob.data = binary->data;
174
0
  blob.length = binary->length;
175
0
  binary = NULL;
176
177
  /*
178
   * We need at least size and subtype
179
   */
180
0
  if (blob.length < 5) {
181
0
    return NT_STATUS_INVALID_PARAMETER;
182
0
  }
183
184
0
  sub_type = PULL_LE_U8(blob.data, 4);
185
186
  /*
187
   * Only levels above LSA_FOREST_TRUST_DOMAIN_INFO
188
   * are handled as binary.
189
   */
190
0
  if (sub_type <= FOREST_TRUST_BINARY_DATA) {
191
0
    return NT_STATUS_INVALID_PARAMETER;
192
0
  }
193
194
0
  lftr2->flags = flags;
195
0
  lftr2->time = time;
196
197
  /*
198
   * Depending if the sub_type is wellknown the information is upgraded,
199
   * currently only for the LSA_FOREST_TRUST_SCANNER_INFO records.
200
   */
201
202
0
  if (sub_type == FOREST_TRUST_SCANNER_INFO) {
203
0
    struct lsa_ForestTrustDomainInfo *d_sdi = NULL;
204
0
    union ForestTrustData fta = { .unknown = { .size = 0, }, };
205
0
    const struct ForestTrustDataDomainInfo *s_sdi = NULL;
206
0
    enum ndr_err_code ndr_err;
207
208
0
    ndr_err = ndr_pull_union_blob(&blob,
209
0
                mem_ctx,
210
0
                &fta,
211
0
                FOREST_TRUST_SCANNER_INFO,
212
0
                (ndr_pull_flags_fn_t)ndr_pull_ForestTrustData);
213
0
    if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
214
0
      return ndr_map_error2ntstatus(ndr_err);
215
0
    }
216
217
0
    if (fta.scanner_info.sub_type != FOREST_TRUST_SCANNER_INFO) {
218
0
      return NT_STATUS_INVALID_PARAMETER;
219
0
    }
220
221
0
    s_sdi = &fta.scanner_info.info;
222
0
    d_sdi = &lftr2->forest_trust_data.scanner_info;
223
224
0
    d_sdi->dns_domain_name.string = s_sdi->dns_name.string;
225
0
    d_sdi->netbios_domain_name.string = s_sdi->netbios_name.string;
226
227
0
    if (s_sdi->sid_size != 0) {
228
0
      d_sdi->domain_sid = dom_sid_dup(mem_ctx,
229
0
              &s_sdi->sid);
230
0
      if (d_sdi->domain_sid == NULL) {
231
0
        return NT_STATUS_NO_MEMORY;
232
0
      }
233
0
    } else {
234
0
      d_sdi->domain_sid = NULL;
235
0
    }
236
237
0
    lftr2->type = LSA_FOREST_TRUST_SCANNER_INFO;
238
239
0
    return NT_STATUS_OK;
240
0
  }
241
242
  /*
243
   * In all other cases lftr->type is downgraded to
244
   * LSA_FOREST_TRUST_BINARY_DATA.
245
   */
246
247
0
  lftr2->type = LSA_FOREST_TRUST_BINARY_DATA;
248
0
  lftr2->forest_trust_data.data.data = blob.data;
249
0
  lftr2->forest_trust_data.data.length = blob.length;
250
251
0
  return NT_STATUS_OK;
252
0
}
253
254
static NTSTATUS trust_forest_record_lsa_1to2(TALLOC_CTX *mem_ctx,
255
        const struct lsa_ForestTrustRecord *lftr,
256
        struct lsa_ForestTrustRecord2 *lftr2)
257
0
{
258
0
  const struct lsa_ForestTrustBinaryData *binary = NULL;
259
260
0
  if (lftr == NULL) {
261
0
    return NT_STATUS_INVALID_PARAMETER;
262
0
  }
263
264
0
  lftr2->flags = lftr->flags;
265
0
  lftr2->time = lftr->time;
266
267
0
  switch (lftr->type) {
268
0
  case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
269
0
    lftr2->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
270
0
    lftr2->forest_trust_data.top_level_name =
271
0
      lftr->forest_trust_data.top_level_name;
272
273
0
    return NT_STATUS_OK;
274
275
0
  case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
276
0
    lftr2->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX;
277
0
    lftr2->forest_trust_data.top_level_name_ex =
278
0
      lftr->forest_trust_data.top_level_name_ex;
279
280
0
    return NT_STATUS_OK;
281
282
0
  case LSA_FOREST_TRUST_DOMAIN_INFO:
283
0
    lftr2->type = LSA_FOREST_TRUST_DOMAIN_INFO;
284
0
    lftr2->forest_trust_data.domain_info =
285
0
      lftr->forest_trust_data.domain_info;
286
287
0
    return NT_STATUS_OK;
288
289
0
  case LSA_FOREST_TRUST_BINARY_DATA:
290
0
  case LSA_FOREST_TRUST_SCANNER_INFO:
291
    /* just to avoid the missing enum switch warning */
292
0
    break;
293
0
  }
294
295
  /*
296
   * All levels above LSA_FOREST_TRUST_DOMAIN_INFO are handled as binary.
297
   *
298
   * Depending if the sub_type is wellknown the information is upgraded,
299
   * currently only for the LSA_FOREST_TRUST_SCANNER_INFO records.
300
   *
301
   * In all other cases lftr->type is downgraded to
302
   * LSA_FOREST_TRUST_BINARY_DATA.
303
   */
304
305
0
  binary = &lftr->forest_trust_data.data;
306
307
0
  return trust_forest_record_lsa_resolve_binary(mem_ctx,
308
0
                  lftr->flags,
309
0
                  lftr->time,
310
0
                  binary,
311
0
                  lftr2);
312
0
}
313
314
NTSTATUS trust_forest_info_from_lsa(TALLOC_CTX *mem_ctx,
315
        const struct lsa_ForestTrustInformation *lfti,
316
        struct ForestTrustInfo **_fti)
317
0
{
318
0
  struct ForestTrustInfo *fti;
319
0
  uint32_t i;
320
321
0
  *_fti = NULL;
322
323
0
  fti = talloc_zero(mem_ctx, struct ForestTrustInfo);
324
0
  if (fti == NULL) {
325
0
    return NT_STATUS_NO_MEMORY;
326
0
  }
327
328
0
  fti->version = 1;
329
0
  fti->count = lfti->count;
330
0
  fti->records = talloc_zero_array(fti,
331
0
           struct ForestTrustInfoRecordArmor,
332
0
           fti->count);
333
0
  if (fti->records == NULL) {
334
0
    TALLOC_FREE(fti);
335
0
    return NT_STATUS_NO_MEMORY;
336
0
  }
337
338
0
  for (i = 0; i < fti->count; i++) {
339
0
    const struct lsa_ForestTrustRecord *lftr = lfti->entries[i];
340
0
    struct lsa_ForestTrustRecord2 lftr2 = { .flags = 0, };
341
0
    struct ForestTrustInfoRecord *ftr = &fti->records[i].record;
342
0
    TALLOC_CTX *frame = talloc_stackframe();
343
0
    NTSTATUS status;
344
345
0
    status = trust_forest_record_lsa_1to2(frame,
346
0
                  lftr,
347
0
                  &lftr2);
348
0
    if (!NT_STATUS_IS_OK(status)) {
349
0
      TALLOC_FREE(frame);
350
0
      TALLOC_FREE(fti);
351
0
      return status;
352
0
    }
353
354
0
    status = trust_forest_record_from_lsa(fti->records,
355
0
                  &lftr2,
356
0
                  ftr);
357
0
    TALLOC_FREE(frame);
358
0
    if (!NT_STATUS_IS_OK(status)) {
359
0
      TALLOC_FREE(fti);
360
0
      return status;
361
0
    }
362
0
  }
363
364
0
  *_fti = fti;
365
0
  return NT_STATUS_OK;
366
0
}
367
368
static NTSTATUS trust_forest_record_to_lsa(TALLOC_CTX *mem_ctx,
369
          const struct ForestTrustInfoRecord *ftr,
370
          struct lsa_ForestTrustRecord2 *lftr)
371
0
{
372
0
  const struct ForestTrustString *str = NULL;
373
0
  struct lsa_StringLarge *lstr = NULL;
374
0
  const struct ForestTrustDataDomainInfo *info = NULL;
375
0
  struct lsa_ForestTrustDomainInfo *linfo = NULL;
376
0
  DATA_BLOB blob = { .length = 0, };
377
378
0
  lftr->flags = ftr->flags;
379
0
  lftr->time = ftr->timestamp;
380
381
0
  switch (ftr->type) {
382
0
  case FOREST_TRUST_TOP_LEVEL_NAME:
383
0
    lftr->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
384
385
0
    lstr = &lftr->forest_trust_data.top_level_name;
386
0
    str = &ftr->data.name;
387
388
0
    lstr->string = talloc_strdup(mem_ctx, str->string);
389
0
    if (lstr->string == NULL) {
390
0
      return NT_STATUS_NO_MEMORY;
391
0
    }
392
393
0
    return NT_STATUS_OK;
394
395
0
  case FOREST_TRUST_TOP_LEVEL_NAME_EX:
396
0
    lftr->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX;
397
398
0
    lstr = &lftr->forest_trust_data.top_level_name_ex;
399
0
    str = &ftr->data.name;
400
401
0
    lstr->string = talloc_strdup(mem_ctx, str->string);
402
0
    if (lstr->string == NULL) {
403
0
      return NT_STATUS_NO_MEMORY;
404
0
    }
405
406
0
    return NT_STATUS_OK;
407
408
0
  case FOREST_TRUST_DOMAIN_INFO:
409
0
    lftr->type = LSA_FOREST_TRUST_DOMAIN_INFO;
410
411
0
    linfo = &lftr->forest_trust_data.domain_info;
412
0
    info = &ftr->data.info;
413
414
0
    linfo->domain_sid = dom_sid_dup(mem_ctx, &info->sid);
415
0
    if (linfo->domain_sid == NULL) {
416
0
      return NT_STATUS_NO_MEMORY;
417
0
    }
418
419
0
    lstr = &linfo->dns_domain_name;
420
0
    str = &info->dns_name;
421
0
    lstr->string = talloc_strdup(mem_ctx, str->string);
422
0
    if (lstr->string == NULL) {
423
0
      return NT_STATUS_NO_MEMORY;
424
0
    }
425
426
0
    lstr = &linfo->netbios_domain_name;
427
0
    str = &info->netbios_name;
428
0
    lstr->string = talloc_strdup(mem_ctx, str->string);
429
0
    if (lstr->string == NULL) {
430
0
      return NT_STATUS_NO_MEMORY;
431
0
    }
432
433
0
    return NT_STATUS_OK;
434
435
0
  case FOREST_TRUST_BINARY_DATA:
436
0
    lftr->type = LSA_FOREST_TRUST_BINARY_DATA;
437
438
0
    blob = data_blob_talloc_named(mem_ctx,
439
0
                ftr->data.binary.data,
440
0
                ftr->data.binary.size,
441
0
                "BINARY_DATA");
442
0
    if (blob.length != ftr->data.binary.size) {
443
0
      return NT_STATUS_NO_MEMORY;
444
0
    }
445
446
0
    lftr->forest_trust_data.data.data = blob.data;
447
0
    lftr->forest_trust_data.data.length = blob.length;
448
449
0
    return NT_STATUS_OK;
450
451
0
  case FOREST_TRUST_SCANNER_INFO:
452
0
    lftr->type = LSA_FOREST_TRUST_SCANNER_INFO;
453
454
0
    linfo = &lftr->forest_trust_data.scanner_info;
455
0
    info = &ftr->data.scanner_info.info;
456
457
0
    if (info->sid_size != 0) {
458
0
      linfo->domain_sid = dom_sid_dup(mem_ctx,
459
0
              &info->sid);
460
0
      if (linfo->domain_sid == NULL) {
461
0
        return NT_STATUS_NO_MEMORY;
462
0
      }
463
0
    } else {
464
0
      linfo->domain_sid = NULL;
465
0
    }
466
467
0
    lstr = &linfo->dns_domain_name;
468
0
    str = &info->dns_name;
469
0
    lstr->string = talloc_strdup(mem_ctx, str->string);
470
0
    if (lstr->string == NULL) {
471
0
      return NT_STATUS_NO_MEMORY;
472
0
    }
473
0
    lstr = &linfo->netbios_domain_name;
474
0
    str = &info->netbios_name;
475
0
    lstr->string = talloc_strdup(mem_ctx, str->string);
476
0
    if (lstr->string == NULL) {
477
0
      return NT_STATUS_NO_MEMORY;
478
0
    }
479
480
0
    return NT_STATUS_OK;
481
0
  }
482
483
0
  return NT_STATUS_NOT_SUPPORTED;
484
0
}
485
486
static NTSTATUS trust_forest_record_lsa_2to1(TALLOC_CTX *mem_ctx,
487
        const struct lsa_ForestTrustRecord2 *lftr2,
488
        struct lsa_ForestTrustRecord *lftr)
489
0
{
490
0
  const struct lsa_ForestTrustDomainInfo *s_sdi = NULL;
491
0
  union ForestTrustData fta = { .unknown = { .size = 0, }, };
492
0
  struct ForestTrustDataDomainInfo *d_sdi = NULL;
493
0
  enum ndr_err_code ndr_err;
494
0
  DATA_BLOB blob = { .length = 0, };
495
496
0
  if (lftr2 == NULL) {
497
0
    return NT_STATUS_INVALID_PARAMETER;
498
0
  }
499
500
0
  lftr->flags = lftr2->flags;
501
0
  lftr->time = lftr2->time;
502
503
0
  switch (lftr2->type) {
504
0
  case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
505
0
    lftr->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
506
0
    lftr->forest_trust_data.top_level_name =
507
0
      lftr2->forest_trust_data.top_level_name;
508
509
0
    return NT_STATUS_OK;
510
511
0
  case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
512
0
    lftr->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX;
513
0
    lftr->forest_trust_data.top_level_name_ex =
514
0
      lftr2->forest_trust_data.top_level_name_ex;
515
516
0
    return NT_STATUS_OK;
517
518
0
  case LSA_FOREST_TRUST_DOMAIN_INFO:
519
0
    lftr->type = LSA_FOREST_TRUST_DOMAIN_INFO;
520
0
    lftr->forest_trust_data.domain_info =
521
0
      lftr2->forest_trust_data.domain_info;
522
523
0
    return NT_STATUS_OK;
524
525
0
  case LSA_FOREST_TRUST_BINARY_DATA:
526
0
    lftr->type = LSA_FOREST_TRUST_BINARY_DATA;
527
0
    lftr->forest_trust_data.data =
528
0
      lftr2->forest_trust_data.data;
529
530
0
    return NT_STATUS_OK;
531
532
0
  case LSA_FOREST_TRUST_SCANNER_INFO:
533
0
    fta.scanner_info.sub_type = FOREST_TRUST_SCANNER_INFO;
534
0
    s_sdi = &lftr2->forest_trust_data.scanner_info;
535
0
    d_sdi = &fta.scanner_info.info;
536
537
0
    if (s_sdi->domain_sid != NULL) {
538
0
      d_sdi->sid = *s_sdi->domain_sid;
539
0
    } else {
540
0
      d_sdi->sid = (struct dom_sid) { .sid_rev_num = 0, };
541
0
    }
542
543
0
    d_sdi->dns_name.string = s_sdi->dns_domain_name.string;
544
0
    d_sdi->netbios_name.string = s_sdi->netbios_domain_name.string;
545
546
0
    ndr_err = ndr_push_union_blob(&blob,
547
0
                mem_ctx,
548
0
                &fta,
549
0
                FOREST_TRUST_SCANNER_INFO,
550
0
                (ndr_push_flags_fn_t)ndr_push_ForestTrustData);
551
0
    if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
552
0
      return ndr_map_error2ntstatus(ndr_err);
553
0
    }
554
555
0
    lftr->type = LSA_FOREST_TRUST_SCANNER_INFO;
556
0
    lftr->forest_trust_data.data.data = blob.data;
557
0
    lftr->forest_trust_data.data.length = blob.length;
558
559
0
    return NT_STATUS_OK;
560
0
  }
561
562
0
  return NT_STATUS_NOT_SUPPORTED;
563
0
}
564
565
NTSTATUS trust_forest_info_to_lsa(TALLOC_CTX *mem_ctx,
566
          const struct ForestTrustInfo *fti,
567
          struct lsa_ForestTrustInformation **_lfti)
568
0
{
569
0
  struct lsa_ForestTrustInformation *lfti;
570
0
  uint32_t i;
571
572
0
  *_lfti = NULL;
573
574
0
  if (fti->version != 1) {
575
0
    return NT_STATUS_INVALID_PARAMETER;
576
0
  }
577
578
0
  lfti = talloc_zero(mem_ctx, struct lsa_ForestTrustInformation);
579
0
  if (lfti == NULL) {
580
0
    return NT_STATUS_NO_MEMORY;
581
0
  }
582
583
0
  lfti->count = fti->count;
584
0
  lfti->entries = talloc_zero_array(mem_ctx,
585
0
            struct lsa_ForestTrustRecord *,
586
0
            lfti->count);
587
0
  if (lfti->entries == NULL) {
588
0
    TALLOC_FREE(lfti);
589
0
    return NT_STATUS_NO_MEMORY;
590
0
  }
591
592
0
  for (i = 0; i < fti->count; i++) {
593
0
    struct ForestTrustInfoRecord *ftr = &fti->records[i].record;
594
0
    struct lsa_ForestTrustRecord2 lftr2 = { .flags = 0, };
595
0
    struct lsa_ForestTrustRecord *lftr = NULL;
596
0
    NTSTATUS status;
597
598
0
    lftr = talloc_zero(lfti->entries,
599
0
           struct lsa_ForestTrustRecord);
600
0
    if (lftr == NULL) {
601
0
      TALLOC_FREE(lfti);
602
0
      return NT_STATUS_NO_MEMORY;
603
0
    }
604
605
0
    status = trust_forest_record_to_lsa(lftr, ftr, &lftr2);
606
0
    if (!NT_STATUS_IS_OK(status)) {
607
0
      TALLOC_FREE(lfti);
608
0
      return NT_STATUS_NO_MEMORY;
609
0
    }
610
611
0
    status = trust_forest_record_lsa_2to1(lftr, &lftr2, lftr);
612
0
    if (!NT_STATUS_IS_OK(status)) {
613
0
      TALLOC_FREE(lfti);
614
0
      return NT_STATUS_NO_MEMORY;
615
0
    }
616
617
0
    lfti->entries[i] = lftr;
618
0
  }
619
620
0
  *_lfti = lfti;
621
0
  return NT_STATUS_OK;
622
0
}
623
624
static NTSTATUS trust_forest_record_lsa_2to2(TALLOC_CTX *mem_ctx,
625
        const struct lsa_ForestTrustRecord2 *in,
626
        struct lsa_ForestTrustRecord2 *out)
627
0
{
628
0
  const struct lsa_ForestTrustBinaryData *binary = NULL;
629
630
0
  if (in == NULL) {
631
0
    return NT_STATUS_INVALID_PARAMETER;
632
0
  }
633
634
0
  out->flags = in->flags;
635
0
  out->time = in->time;
636
637
0
  switch (in->type) {
638
0
  case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
639
0
    out->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
640
0
    out->forest_trust_data.top_level_name =
641
0
      in->forest_trust_data.top_level_name;
642
643
0
    return NT_STATUS_OK;
644
645
0
  case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
646
0
    out->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX;
647
0
    out->forest_trust_data.top_level_name_ex =
648
0
      in->forest_trust_data.top_level_name_ex;
649
650
0
    return NT_STATUS_OK;
651
652
0
  case LSA_FOREST_TRUST_DOMAIN_INFO:
653
0
    out->type = LSA_FOREST_TRUST_DOMAIN_INFO;
654
0
    out->forest_trust_data.domain_info =
655
0
      in->forest_trust_data.domain_info;
656
657
0
    return NT_STATUS_OK;
658
659
0
  case LSA_FOREST_TRUST_BINARY_DATA:
660
0
    binary = &in->forest_trust_data.data;
661
662
0
    return trust_forest_record_lsa_resolve_binary(mem_ctx,
663
0
                    in->flags,
664
0
                    in->time,
665
0
                    binary,
666
0
                    out);
667
668
0
  case LSA_FOREST_TRUST_SCANNER_INFO:
669
0
    out->type = LSA_FOREST_TRUST_SCANNER_INFO;
670
0
    out->forest_trust_data.domain_info =
671
0
      in->forest_trust_data.domain_info;
672
673
0
    return NT_STATUS_OK;
674
0
  }
675
676
0
  return NT_STATUS_NOT_SUPPORTED;
677
0
}
678
679
NTSTATUS trust_forest_info_from_lsa2(TALLOC_CTX *mem_ctx,
680
        const struct lsa_ForestTrustInformation2 *lfti,
681
        struct ForestTrustInfo **_fti)
682
0
{
683
0
  struct ForestTrustInfo *fti;
684
0
  uint32_t i;
685
686
0
  *_fti = NULL;
687
688
0
  fti = talloc_zero(mem_ctx, struct ForestTrustInfo);
689
0
  if (fti == NULL) {
690
0
    return NT_STATUS_NO_MEMORY;
691
0
  }
692
693
0
  fti->version = 1;
694
0
  fti->count = lfti->count;
695
0
  fti->records = talloc_zero_array(fti,
696
0
           struct ForestTrustInfoRecordArmor,
697
0
           fti->count);
698
0
  if (fti->records == NULL) {
699
0
    TALLOC_FREE(fti);
700
0
    return NT_STATUS_NO_MEMORY;
701
0
  }
702
703
0
  for (i = 0; i < fti->count; i++) {
704
0
    const struct lsa_ForestTrustRecord2 *lftr2 = lfti->entries[i];
705
0
    struct lsa_ForestTrustRecord2 _lftr2 = { .flags = 0, };
706
0
    struct ForestTrustInfoRecord *ftr = &fti->records[i].record;
707
0
    TALLOC_CTX *frame = talloc_stackframe();
708
0
    NTSTATUS status;
709
710
0
    status = trust_forest_record_lsa_2to2(frame,
711
0
                  lftr2,
712
0
                  &_lftr2);
713
0
    if (!NT_STATUS_IS_OK(status)) {
714
0
      TALLOC_FREE(frame);
715
0
      TALLOC_FREE(fti);
716
0
      return status;
717
0
    }
718
719
0
    status = trust_forest_record_from_lsa(fti->records,
720
0
                  &_lftr2,
721
0
                  ftr);
722
0
    TALLOC_FREE(frame);
723
0
    if (!NT_STATUS_IS_OK(status)) {
724
0
      TALLOC_FREE(fti);
725
0
      return status;
726
0
    }
727
0
  }
728
729
0
  *_fti = fti;
730
0
  return NT_STATUS_OK;
731
0
}
732
733
NTSTATUS trust_forest_info_to_lsa2(TALLOC_CTX *mem_ctx,
734
           const struct ForestTrustInfo *fti,
735
           struct lsa_ForestTrustInformation2 **_lfti)
736
0
{
737
0
  struct lsa_ForestTrustInformation2 *lfti;
738
0
  uint32_t i;
739
740
0
  *_lfti = NULL;
741
742
0
  if (fti->version != 1) {
743
0
    return NT_STATUS_INVALID_PARAMETER;
744
0
  }
745
746
0
  lfti = talloc_zero(mem_ctx, struct lsa_ForestTrustInformation2);
747
0
  if (lfti == NULL) {
748
0
    return NT_STATUS_NO_MEMORY;
749
0
  }
750
751
0
  lfti->count = fti->count;
752
0
  lfti->entries = talloc_zero_array(mem_ctx,
753
0
            struct lsa_ForestTrustRecord2 *,
754
0
            lfti->count);
755
0
  if (lfti->entries == NULL) {
756
0
    TALLOC_FREE(lfti);
757
0
    return NT_STATUS_NO_MEMORY;
758
0
  }
759
760
0
  for (i = 0; i < fti->count; i++) {
761
0
    struct ForestTrustInfoRecord *ftr = &fti->records[i].record;
762
0
    struct lsa_ForestTrustRecord2 *lftr2 = NULL;
763
0
    NTSTATUS status;
764
765
0
    lftr2 = talloc_zero(lfti->entries,
766
0
            struct lsa_ForestTrustRecord2);
767
0
    if (lftr2 == NULL) {
768
0
      TALLOC_FREE(lfti);
769
0
      return NT_STATUS_NO_MEMORY;
770
0
    }
771
772
0
    status = trust_forest_record_to_lsa(lftr2, ftr, lftr2);
773
0
    if (!NT_STATUS_IS_OK(status)) {
774
0
      TALLOC_FREE(lfti);
775
0
      return NT_STATUS_NO_MEMORY;
776
0
    }
777
778
0
    lfti->entries[i] = lftr2;
779
0
  }
780
781
0
  *_lfti = lfti;
782
0
  return NT_STATUS_OK;
783
0
}
784
785
NTSTATUS trust_forest_info_lsa_1to2(TALLOC_CTX *mem_ctx,
786
        const struct lsa_ForestTrustInformation *lfti,
787
        struct lsa_ForestTrustInformation2 **_lfti2)
788
0
{
789
0
  TALLOC_CTX *frame = talloc_stackframe();
790
0
  struct ForestTrustInfo *fti = NULL;
791
0
  struct lsa_ForestTrustInformation2 *lfti2 = NULL;
792
0
  NTSTATUS status;
793
794
0
  status = trust_forest_info_from_lsa(frame, lfti, &fti);
795
0
  if (!NT_STATUS_IS_OK(status)) {
796
0
    TALLOC_FREE(frame);
797
0
    return status;
798
0
  }
799
800
0
  status = trust_forest_info_to_lsa2(mem_ctx,
801
0
             fti,
802
0
             &lfti2);
803
0
  if (!NT_STATUS_IS_OK(status)) {
804
0
    TALLOC_FREE(frame);
805
0
    return status;
806
0
  }
807
808
0
  *_lfti2 = lfti2;
809
0
  TALLOC_FREE(frame);
810
0
  return NT_STATUS_OK;
811
0
}
812
813
NTSTATUS trust_forest_info_lsa_2to1(TALLOC_CTX *mem_ctx,
814
        const struct lsa_ForestTrustInformation2 *lfti2,
815
        struct lsa_ForestTrustInformation **_lfti)
816
0
{
817
0
  TALLOC_CTX *frame = talloc_stackframe();
818
0
  struct ForestTrustInfo *fti = NULL;
819
0
  struct lsa_ForestTrustInformation *lfti = NULL;
820
0
  NTSTATUS status;
821
822
0
  status = trust_forest_info_from_lsa2(frame, lfti2, &fti);
823
0
  if (!NT_STATUS_IS_OK(status)) {
824
0
    TALLOC_FREE(frame);
825
0
    return status;
826
0
  }
827
828
0
  status = trust_forest_info_to_lsa(mem_ctx,
829
0
            fti,
830
0
            &lfti);
831
0
  if (!NT_STATUS_IS_OK(status)) {
832
0
    TALLOC_FREE(frame);
833
0
    return status;
834
0
  }
835
836
0
  *_lfti = lfti;
837
0
  TALLOC_FREE(frame);
838
0
  return NT_STATUS_OK;
839
0
}
840
841
NTSTATUS trust_forest_info_lsa_2to2(TALLOC_CTX *mem_ctx,
842
        const struct lsa_ForestTrustInformation2 *in,
843
        struct lsa_ForestTrustInformation2 **_out)
844
0
{
845
0
  TALLOC_CTX *frame = talloc_stackframe();
846
0
  struct ForestTrustInfo *fti = NULL;
847
0
  struct lsa_ForestTrustInformation2 *out = NULL;
848
0
  NTSTATUS status;
849
850
0
  status = trust_forest_info_from_lsa2(frame, in, &fti);
851
0
  if (!NT_STATUS_IS_OK(status)) {
852
0
    TALLOC_FREE(frame);
853
0
    return status;
854
0
  }
855
856
0
  status = trust_forest_info_to_lsa2(mem_ctx,
857
0
             fti,
858
0
             &out);
859
0
  if (!NT_STATUS_IS_OK(status)) {
860
0
    TALLOC_FREE(frame);
861
0
    return status;
862
0
  }
863
864
0
  *_out = out;
865
0
  TALLOC_FREE(frame);
866
0
  return NT_STATUS_OK;
867
0
}
868
869
static int trust_forest_info_tln_match_internal(
870
    const struct lsa_ForestTrustInformation2 *info,
871
    enum lsa_ForestTrustRecordType type,
872
    uint32_t disable_mask,
873
    const char *tln)
874
0
{
875
0
  uint32_t i;
876
877
0
  for (i = 0; i < info->count; i++) {
878
0
    struct lsa_ForestTrustRecord2 *e = info->entries[i];
879
0
    struct lsa_StringLarge *t = NULL;
880
0
    int cmp;
881
882
0
    if (e == NULL) {
883
0
      continue;
884
0
    }
885
886
0
    if (e->type != type) {
887
0
      continue;
888
0
    }
889
890
0
    if (e->flags & disable_mask) {
891
0
      continue;
892
0
    }
893
894
0
    switch (type) {
895
0
    case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
896
0
      t = &e->forest_trust_data.top_level_name;
897
0
      break;
898
0
    case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
899
0
      t = &e->forest_trust_data.top_level_name_ex;
900
0
      break;
901
0
    default:
902
0
      break;
903
0
    }
904
905
0
    if (t == NULL) {
906
0
      continue;
907
0
    }
908
909
0
    cmp = dns_cmp(tln, t->string);
910
0
    switch (cmp) {
911
0
    case DNS_CMP_MATCH:
912
0
    case DNS_CMP_FIRST_IS_CHILD:
913
0
      return i;
914
0
    }
915
0
  }
916
917
0
  return -1;
918
0
}
919
920
bool trust_forest_info_tln_match(
921
    const struct lsa_ForestTrustInformation2 *info,
922
    const char *tln)
923
0
{
924
0
  int m;
925
926
0
  m = trust_forest_info_tln_match_internal(info,
927
0
          LSA_FOREST_TRUST_TOP_LEVEL_NAME,
928
0
          LSA_TLN_DISABLED_MASK,
929
0
          tln);
930
0
  if (m != -1) {
931
0
    return true;
932
0
  }
933
934
0
  return false;
935
0
}
936
937
bool trust_forest_info_tln_ex_match(
938
    const struct lsa_ForestTrustInformation2 *info,
939
    const char *tln)
940
0
{
941
0
  int m;
942
943
0
  m = trust_forest_info_tln_match_internal(info,
944
0
          LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX,
945
0
          0,
946
0
          tln);
947
0
  if (m != -1) {
948
0
    return true;
949
0
  }
950
951
0
  return false;
952
0
}
953
954
bool trust_forest_info_match_tln_namespace(
955
    const struct lsa_ForestTrustInformation2 *info,
956
    const char *tln)
957
0
{
958
0
  bool match;
959
960
0
  match = trust_forest_info_tln_ex_match(info, tln);
961
0
  if (match) {
962
0
    return false;
963
0
  }
964
965
0
  match = trust_forest_info_tln_match(info, tln);
966
0
  if (!match) {
967
0
    return false;
968
0
  }
969
970
0
  return true;
971
0
}