Coverage Report

Created: 2026-07-25 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source4/dsdb/common/util_trusts.c
Line
Count
Source
1
/*
2
   Unix SMB/CIFS implementation.
3
4
   Copyright (C) Stefan Metzmacher 2015
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 "includes.h"
21
#include "ldb.h"
22
#include "../lib/util/util_ldb.h"
23
#include "../lib/util/dns_cmp.h"
24
#include "../libcli/lsarpc/util_lsarpc.h"
25
#include "dsdb/samdb/samdb.h"
26
#include "libcli/security/security.h"
27
#include "librpc/gen_ndr/ndr_security.h"
28
#include "librpc/gen_ndr/ndr_misc.h"
29
#include "../libds/common/flags.h"
30
#include "dsdb/common/proto.h"
31
#include "param/param.h"
32
#include "librpc/gen_ndr/ndr_drsblobs.h"
33
#include "lib/util/tsort.h"
34
#include "dsdb/common/util.h"
35
#include "libds/common/flag_mapping.h"
36
#include "../lib/util/dlinklist.h"
37
#include "lib/crypto/md4.h"
38
#include "libcli/ldap/ldap_ndr.h"
39
#include "libcli/security/claims_transformation.h"
40
41
#undef strcasecmp
42
43
static NTSTATUS dsdb_trust_forest_info_add_record(struct lsa_ForestTrustInformation2 *fti,
44
              const struct lsa_ForestTrustRecord2 *ftr)
45
0
{
46
0
  struct lsa_ForestTrustRecord2 **es = NULL;
47
0
  struct lsa_ForestTrustRecord2 *e = NULL;
48
0
  const struct lsa_StringLarge *dns1 = NULL;
49
0
  struct lsa_StringLarge *dns2 = NULL;
50
0
  const struct lsa_ForestTrustDomainInfo *d1 = NULL;
51
0
  struct lsa_ForestTrustDomainInfo *d2 = NULL;
52
0
  DATA_BLOB blob = { .length = 0, };
53
0
  size_t len = 0;
54
0
  bool scanner = false;
55
56
0
  es = talloc_realloc(fti, fti->entries,
57
0
          struct lsa_ForestTrustRecord2 *,
58
0
          fti->count + 1);
59
0
  if (!es) {
60
0
    return NT_STATUS_NO_MEMORY;
61
0
  }
62
0
  fti->entries = es;
63
64
0
  e = talloc_zero(es, struct lsa_ForestTrustRecord2);
65
0
  if (e == NULL) {
66
0
    return NT_STATUS_NO_MEMORY;
67
0
  }
68
69
0
  e->type = ftr->type;
70
0
  e->flags = ftr->flags;
71
0
  e->time = ftr->time;
72
73
0
  switch (ftr->type) {
74
0
  case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
75
0
    dns1 = &ftr->forest_trust_data.top_level_name;
76
0
    dns2 = &e->forest_trust_data.top_level_name;
77
0
    break;
78
79
0
  case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
80
0
    dns1 = &ftr->forest_trust_data.top_level_name_ex;
81
0
    dns2 = &e->forest_trust_data.top_level_name_ex;
82
0
    break;
83
84
0
  case LSA_FOREST_TRUST_DOMAIN_INFO:
85
0
    dns1 = &ftr->forest_trust_data.domain_info.dns_domain_name;
86
0
    dns2 = &e->forest_trust_data.domain_info.dns_domain_name;
87
0
    d1 = &ftr->forest_trust_data.domain_info;
88
0
    d2 = &e->forest_trust_data.domain_info;
89
0
    break;
90
91
0
  case LSA_FOREST_TRUST_BINARY_DATA:
92
0
    blob = data_blob_talloc_named(e,
93
0
                ftr->forest_trust_data.data.data,
94
0
                ftr->forest_trust_data.data.length,
95
0
                "BINARY_DATA");
96
0
    if (blob.length != ftr->forest_trust_data.data.length) {
97
0
      return NT_STATUS_NO_MEMORY;
98
0
    }
99
0
    e->forest_trust_data.data.data = blob.data;
100
0
    e->forest_trust_data.data.length = blob.length;
101
0
    goto done;
102
103
0
  case LSA_FOREST_TRUST_SCANNER_INFO:
104
0
    dns1 = &ftr->forest_trust_data.scanner_info.dns_domain_name;
105
0
    dns2 = &e->forest_trust_data.scanner_info.dns_domain_name;
106
0
    d1 = &ftr->forest_trust_data.scanner_info;
107
0
    d2 = &e->forest_trust_data.scanner_info;
108
0
    scanner = true;
109
0
    break;
110
111
0
  default:
112
0
    return NT_STATUS_INVALID_PARAMETER;
113
0
  }
114
115
0
  if (dns1->string == NULL) {
116
0
    TALLOC_FREE(e);
117
0
    return NT_STATUS_INVALID_PARAMETER;
118
0
  }
119
120
0
  len = strlen(dns1->string);
121
0
  if (len == 0) {
122
0
    TALLOC_FREE(e);
123
0
    return NT_STATUS_INVALID_PARAMETER;
124
0
  }
125
126
0
  dns2->string = talloc_strdup(e, dns1->string);
127
0
  if (dns2->string == NULL) {
128
0
    TALLOC_FREE(e);
129
0
    return NT_STATUS_NO_MEMORY;
130
0
  }
131
132
0
  if (d1 != NULL) {
133
0
    const struct lsa_StringLarge *nb1 = &d1->netbios_domain_name;
134
0
    struct lsa_StringLarge *nb2 = &d2->netbios_domain_name;
135
136
0
    if (nb1->string == NULL) {
137
0
      TALLOC_FREE(e);
138
0
      return NT_STATUS_INVALID_PARAMETER;
139
0
    }
140
141
0
    len = strlen(nb1->string);
142
0
    if (len == 0) {
143
0
      TALLOC_FREE(e);
144
0
      return NT_STATUS_INVALID_PARAMETER;
145
0
    }
146
0
    if (len > 15) {
147
0
      TALLOC_FREE(e);
148
0
      return NT_STATUS_INVALID_PARAMETER;
149
0
    }
150
151
0
    nb2->string = talloc_strdup(e, nb1->string);
152
0
    if (nb2->string == NULL) {
153
0
      TALLOC_FREE(e);
154
0
      return NT_STATUS_NO_MEMORY;
155
0
    }
156
157
0
    if (d1->domain_sid == NULL) {
158
      /*
159
       * scanner records typically don't have
160
       * a sid, but it's just ignored if present.
161
       */
162
0
      if (!scanner) {
163
0
        TALLOC_FREE(e);
164
0
        return NT_STATUS_INVALID_PARAMETER;
165
0
      }
166
167
0
    } else {
168
0
      d2->domain_sid = dom_sid_dup(e, d1->domain_sid);
169
0
      if (d2->domain_sid == NULL) {
170
0
        TALLOC_FREE(e);
171
0
        return NT_STATUS_NO_MEMORY;
172
0
      }
173
0
    }
174
0
  }
175
176
0
done:
177
0
  fti->entries[fti->count++] = e;
178
0
  return NT_STATUS_OK;
179
0
}
180
181
static NTSTATUS dsdb_trust_parse_crossref_info(TALLOC_CTX *mem_ctx,
182
          struct ldb_context *sam_ctx,
183
          const struct ldb_message *msg,
184
          struct lsa_TrustDomainInfoInfoEx **_tdo)
185
0
{
186
0
  TALLOC_CTX *frame = talloc_stackframe();
187
0
  struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
188
0
  const char *dns = NULL;
189
0
  const char *netbios = NULL;
190
0
  struct ldb_dn *nc_dn = NULL;
191
0
  struct dom_sid sid = {
192
0
    .num_auths = 0,
193
0
  };
194
0
  NTSTATUS status;
195
196
0
  *_tdo = NULL;
197
0
  tdo = talloc_zero(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
198
0
  if (tdo == NULL) {
199
0
    TALLOC_FREE(frame);
200
0
    return NT_STATUS_NO_MEMORY;
201
0
  }
202
0
  talloc_steal(frame, tdo);
203
204
0
  dns = ldb_msg_find_attr_as_string(msg, "dnsRoot", NULL);
205
0
  if (dns == NULL) {
206
0
    TALLOC_FREE(frame);
207
0
    return NT_STATUS_INTERNAL_DB_CORRUPTION;
208
0
  }
209
0
  tdo->domain_name.string = talloc_strdup(tdo, dns);
210
0
  if (tdo->domain_name.string == NULL) {
211
0
    TALLOC_FREE(frame);
212
0
    return NT_STATUS_NO_MEMORY;
213
0
  }
214
215
0
  netbios = ldb_msg_find_attr_as_string(msg, "nETBIOSName", NULL);
216
0
  if (netbios == NULL) {
217
0
    TALLOC_FREE(frame);
218
0
    return NT_STATUS_INTERNAL_DB_CORRUPTION;
219
0
  }
220
0
  tdo->netbios_name.string = talloc_strdup(tdo, netbios);
221
0
  if (tdo->netbios_name.string == NULL) {
222
0
    TALLOC_FREE(frame);
223
0
    return NT_STATUS_NO_MEMORY;
224
0
  }
225
226
0
  nc_dn = samdb_result_dn(sam_ctx, frame, msg, "ncName", NULL);
227
0
  if (nc_dn == NULL) {
228
0
    TALLOC_FREE(frame);
229
0
    return NT_STATUS_INTERNAL_DB_CORRUPTION;
230
0
  }
231
232
0
  status = dsdb_get_extended_dn_sid(nc_dn, &sid, "SID");
233
0
  if (!NT_STATUS_IS_OK(status)) {
234
0
    TALLOC_FREE(frame);
235
0
    return status;
236
0
  }
237
0
  tdo->sid = dom_sid_dup(tdo, &sid);
238
0
  if (tdo->sid == NULL) {
239
0
    TALLOC_FREE(frame);
240
0
    return NT_STATUS_NO_MEMORY;
241
0
  }
242
243
0
  tdo->trust_type = LSA_TRUST_TYPE_UPLEVEL;
244
0
  tdo->trust_direction = LSA_TRUST_DIRECTION_INBOUND |
245
0
             LSA_TRUST_DIRECTION_OUTBOUND;
246
0
  tdo->trust_attributes = LSA_TRUST_ATTRIBUTE_WITHIN_FOREST;
247
248
0
  *_tdo = talloc_move(mem_ctx, &tdo);
249
0
  TALLOC_FREE(frame);
250
0
  return NT_STATUS_OK;
251
0
}
252
253
static NTSTATUS dsdb_trust_crossref_tdo_info(TALLOC_CTX *mem_ctx,
254
      struct ldb_context *sam_ctx,
255
      struct ldb_dn *domain_dn,
256
      const char *extra_filter,
257
      struct lsa_TrustDomainInfoInfoEx **_tdo,
258
      struct lsa_TrustDomainInfoInfoEx **_root_trust_tdo,
259
      struct lsa_TrustDomainInfoInfoEx **_trust_parent_tdo)
260
0
{
261
0
  TALLOC_CTX *frame = talloc_stackframe();
262
0
  struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
263
0
  struct lsa_TrustDomainInfoInfoEx *root_trust_tdo = NULL;
264
0
  struct lsa_TrustDomainInfoInfoEx *trust_parent_tdo = NULL;
265
0
  struct ldb_dn *partitions_dn = NULL;
266
0
  const char * const cross_attrs[] = {
267
0
    "dnsRoot",
268
0
    "nETBIOSName",
269
0
    "nCName",
270
0
    "rootTrust",
271
0
    "trustParent",
272
0
    NULL,
273
0
  };
274
0
  struct ldb_result *cross_res = NULL;
275
0
  struct ldb_message *msg = NULL;
276
0
  struct ldb_dn *root_trust_dn = NULL;
277
0
  struct ldb_dn *trust_parent_dn = NULL;
278
0
  NTSTATUS status;
279
0
  int ret;
280
281
0
  if (extra_filter == NULL) {
282
0
    extra_filter = "";
283
0
  }
284
285
0
  *_tdo = NULL;
286
0
  if (_root_trust_tdo != NULL) {
287
0
    *_root_trust_tdo = NULL;
288
0
  }
289
0
  if (_trust_parent_tdo != NULL) {
290
0
    *_trust_parent_tdo = NULL;
291
0
  }
292
293
0
  partitions_dn = samdb_partitions_dn(sam_ctx, frame);
294
0
  if (partitions_dn == NULL) {
295
0
    TALLOC_FREE(frame);
296
0
    return NT_STATUS_NO_MEMORY;
297
0
  }
298
299
0
  ret = dsdb_search(sam_ctx, partitions_dn, &cross_res,
300
0
        partitions_dn, LDB_SCOPE_ONELEVEL,
301
0
        cross_attrs,
302
0
        DSDB_SEARCH_ONE_ONLY |
303
0
        DSDB_SEARCH_SHOW_EXTENDED_DN,
304
0
        "(&"
305
0
          "(ncName=%s)"
306
0
          "(objectClass=crossRef)"
307
0
          "(systemFlags:%s:=%u)"
308
0
          "%s"
309
0
        ")",
310
0
        ldb_dn_get_linearized(domain_dn),
311
0
        LDB_OID_COMPARATOR_AND,
312
0
        SYSTEM_FLAG_CR_NTDS_DOMAIN,
313
0
        extra_filter);
314
0
  if (ret != LDB_SUCCESS) {
315
0
    TALLOC_FREE(frame);
316
0
    return dsdb_ldb_err_to_ntstatus(ret);
317
0
  }
318
0
  msg = cross_res->msgs[0];
319
320
0
  status = dsdb_trust_parse_crossref_info(mem_ctx, sam_ctx, msg, &tdo);
321
0
  if (!NT_STATUS_IS_OK(status)) {
322
0
    TALLOC_FREE(frame);
323
0
    return status;
324
0
  }
325
0
  talloc_steal(frame, tdo);
326
327
0
  if (_root_trust_tdo != NULL) {
328
0
    root_trust_dn = samdb_result_dn(sam_ctx, frame, msg,
329
0
            "rootTrust", NULL);
330
0
  }
331
0
  if (_trust_parent_tdo != NULL) {
332
0
    trust_parent_dn = samdb_result_dn(sam_ctx, frame, msg,
333
0
               "trustParent", NULL);
334
0
  }
335
336
0
  if (root_trust_dn != NULL) {
337
0
    struct ldb_message *root_trust_msg = NULL;
338
339
0
    ret = dsdb_search_one(sam_ctx, frame,
340
0
              &root_trust_msg,
341
0
              root_trust_dn,
342
0
              LDB_SCOPE_BASE,
343
0
              cross_attrs,
344
0
              DSDB_SEARCH_NO_GLOBAL_CATALOG,
345
0
              "(objectClass=crossRef)");
346
0
    if (ret != LDB_SUCCESS) {
347
0
      status = dsdb_ldb_err_to_ntstatus(ret);
348
0
      DEBUG(3, ("Failed to search for %s: %s - %s\n",
349
0
          ldb_dn_get_linearized(root_trust_dn),
350
0
          nt_errstr(status), ldb_errstring(sam_ctx)));
351
0
      TALLOC_FREE(frame);
352
0
      return status;
353
0
    }
354
355
0
    status = dsdb_trust_parse_crossref_info(mem_ctx, sam_ctx,
356
0
              root_trust_msg,
357
0
              &root_trust_tdo);
358
0
    if (!NT_STATUS_IS_OK(status)) {
359
0
      TALLOC_FREE(frame);
360
0
      return status;
361
0
    }
362
0
    talloc_steal(frame, root_trust_tdo);
363
0
  }
364
365
0
  if (trust_parent_dn != NULL) {
366
0
    struct ldb_message *trust_parent_msg = NULL;
367
368
0
    ret = dsdb_search_one(sam_ctx, frame,
369
0
              &trust_parent_msg,
370
0
              trust_parent_dn,
371
0
              LDB_SCOPE_BASE,
372
0
              cross_attrs,
373
0
              DSDB_SEARCH_NO_GLOBAL_CATALOG,
374
0
              "(objectClass=crossRef)");
375
0
    if (ret != LDB_SUCCESS) {
376
0
      status = dsdb_ldb_err_to_ntstatus(ret);
377
0
      DEBUG(3, ("Failed to search for %s: %s - %s\n",
378
0
          ldb_dn_get_linearized(trust_parent_dn),
379
0
          nt_errstr(status), ldb_errstring(sam_ctx)));
380
0
      TALLOC_FREE(frame);
381
0
      return status;
382
0
    }
383
384
0
    status = dsdb_trust_parse_crossref_info(mem_ctx, sam_ctx,
385
0
              trust_parent_msg,
386
0
              &trust_parent_tdo);
387
0
    if (!NT_STATUS_IS_OK(status)) {
388
0
      TALLOC_FREE(frame);
389
0
      return status;
390
0
    }
391
0
    talloc_steal(frame, trust_parent_tdo);
392
0
  }
393
394
0
  *_tdo = talloc_move(mem_ctx, &tdo);
395
0
  if (_root_trust_tdo != NULL) {
396
0
    *_root_trust_tdo = talloc_move(mem_ctx, &root_trust_tdo);
397
0
  }
398
0
  if (_trust_parent_tdo != NULL) {
399
0
    *_trust_parent_tdo = talloc_move(mem_ctx, &trust_parent_tdo);
400
0
  }
401
0
  TALLOC_FREE(frame);
402
0
  return NT_STATUS_OK;
403
0
}
404
405
NTSTATUS dsdb_trust_local_tdo_info(TALLOC_CTX *mem_ctx,
406
           struct ldb_context *sam_ctx,
407
           struct lsa_TrustDomainInfoInfoEx **_tdo)
408
0
{
409
0
  struct ldb_dn *domain_dn = NULL;
410
411
0
  domain_dn = ldb_get_default_basedn(sam_ctx);
412
0
  if (domain_dn == NULL) {
413
0
    return NT_STATUS_INTERNAL_ERROR;
414
0
  }
415
416
0
  return dsdb_trust_crossref_tdo_info(mem_ctx, sam_ctx,
417
0
              domain_dn, NULL,
418
0
              _tdo, NULL, NULL);
419
0
}
420
421
NTSTATUS dsdb_trust_xref_tdo_info(TALLOC_CTX *mem_ctx,
422
          struct ldb_context *sam_ctx,
423
          struct lsa_TrustDomainInfoInfoEx **_tdo)
424
0
{
425
  /*
426
   * The extra filter makes sure we only find the forest root domain
427
   */
428
0
  const char *extra_filter = "(!(|(rootTrust=*)(trustParent=*)))";
429
0
  struct ldb_dn *domain_dn = NULL;
430
431
0
  domain_dn = ldb_get_default_basedn(sam_ctx);
432
0
  if (domain_dn == NULL) {
433
0
    return NT_STATUS_INTERNAL_ERROR;
434
0
  }
435
436
0
  return dsdb_trust_crossref_tdo_info(mem_ctx, sam_ctx,
437
0
              domain_dn, extra_filter,
438
0
              _tdo, NULL, NULL);
439
0
}
440
441
static int dsdb_trust_xref_sort_msgs(struct ldb_message **_m1,
442
             struct ldb_message **_m2)
443
0
{
444
0
  struct ldb_message *m1 = *_m1;
445
0
  struct ldb_message *m2 = *_m2;
446
0
  const char *dns1 = NULL;
447
0
  const char *dns2 = NULL;
448
0
  int cmp;
449
0
  struct ldb_message_element *rootTrust1 = NULL;
450
0
  struct ldb_message_element *trustParent1 = NULL;
451
0
  struct ldb_message_element *rootTrust2 = NULL;
452
0
  struct ldb_message_element *trustParent2 = NULL;
453
454
0
  dns1 = ldb_msg_find_attr_as_string(m1, "dnsRoot", NULL);
455
0
  dns2 = ldb_msg_find_attr_as_string(m2, "dnsRoot", NULL);
456
457
0
  cmp = dns_cmp(dns1, dns2);
458
0
  switch (cmp) {
459
0
  case DNS_CMP_FIRST_IS_CHILD:
460
0
    return -1;
461
0
  case DNS_CMP_SECOND_IS_CHILD:
462
0
    return 1;
463
0
  }
464
465
0
  rootTrust1 = ldb_msg_find_element(m1, "rootTrust");
466
0
  trustParent1 = ldb_msg_find_element(m1, "trustParent");
467
0
  rootTrust2 = ldb_msg_find_element(m2, "rootTrust");
468
0
  trustParent2 = ldb_msg_find_element(m2, "trustParent");
469
470
0
  if (rootTrust1 == NULL && trustParent1 == NULL) {
471
    /* m1 is the forest root */
472
0
    return -1;
473
0
  }
474
0
  if (rootTrust2 == NULL && trustParent2 == NULL) {
475
    /* m2 is the forest root */
476
0
    return 1;
477
0
  }
478
479
0
  return cmp;
480
0
}
481
482
static int dsdb_trust_xref_sort_vals(struct ldb_val *v1,
483
             struct ldb_val *v2)
484
0
{
485
0
  const char *dns1 = (const char *)v1->data;
486
0
  const char *dns2 = (const char *)v2->data;
487
488
0
  return dns_cmp(dns1, dns2);
489
0
}
490
491
NTSTATUS dsdb_trust_xref_forest_info(TALLOC_CTX *mem_ctx,
492
             struct ldb_context *sam_ctx,
493
             struct lsa_ForestTrustInformation2 **_info)
494
0
{
495
0
  TALLOC_CTX *frame = talloc_stackframe();
496
0
  struct lsa_ForestTrustInformation2 *info = NULL;
497
0
  struct ldb_dn *partitions_dn = NULL;
498
0
  const char * const cross_attrs1[] = {
499
0
    "uPNSuffixes",
500
0
    "msDS-SPNSuffixes",
501
0
    NULL,
502
0
  };
503
0
  struct ldb_result *cross_res1 = NULL;
504
0
  struct ldb_message_element *upn_el = NULL;
505
0
  struct ldb_message_element *spn_el = NULL;
506
0
  struct ldb_message *tln_msg = NULL;
507
0
  struct ldb_message_element *tln_el = NULL;
508
0
  const char * const cross_attrs2[] = {
509
0
    "dnsRoot",
510
0
    "nETBIOSName",
511
0
    "nCName",
512
0
    "rootTrust",
513
0
    "trustParent",
514
0
    NULL,
515
0
  };
516
0
  struct ldb_result *cross_res2 = NULL;
517
0
  int ret;
518
0
  unsigned int i;
519
0
  bool restart = false;
520
521
0
  *_info = NULL;
522
0
  info = talloc_zero(mem_ctx, struct lsa_ForestTrustInformation2);
523
0
  if (info == NULL) {
524
0
    TALLOC_FREE(frame);
525
0
    return NT_STATUS_NO_MEMORY;
526
0
  }
527
0
  talloc_steal(frame, info);
528
529
0
  partitions_dn = samdb_partitions_dn(sam_ctx, frame);
530
0
  if (partitions_dn == NULL) {
531
0
    TALLOC_FREE(frame);
532
0
    return NT_STATUS_NO_MEMORY;
533
0
  }
534
535
0
  ret = dsdb_search_dn(sam_ctx, partitions_dn, &cross_res1,
536
0
           partitions_dn, cross_attrs1, 0);
537
0
  if (ret != LDB_SUCCESS) {
538
0
    TALLOC_FREE(frame);
539
0
    return dsdb_ldb_err_to_ntstatus(ret);
540
0
  }
541
542
0
  ret = dsdb_search(sam_ctx, partitions_dn, &cross_res2,
543
0
        partitions_dn, LDB_SCOPE_ONELEVEL,
544
0
        cross_attrs2,
545
0
        DSDB_SEARCH_SHOW_EXTENDED_DN,
546
0
        "(&(objectClass=crossRef)"
547
0
         "(systemFlags:%s:=%u))",
548
0
        LDB_OID_COMPARATOR_AND,
549
0
        SYSTEM_FLAG_CR_NTDS_DOMAIN);
550
0
  if (ret != LDB_SUCCESS) {
551
0
    TALLOC_FREE(frame);
552
0
    return dsdb_ldb_err_to_ntstatus(ret);
553
0
  }
554
555
  /*
556
   * Sort the domains as trees, starting with the forest root
557
   */
558
0
  TYPESAFE_QSORT(cross_res2->msgs, cross_res2->count,
559
0
           dsdb_trust_xref_sort_msgs);
560
561
0
  upn_el = ldb_msg_find_element(cross_res1->msgs[0], "uPNSuffixes");
562
0
  if (upn_el != NULL) {
563
0
    upn_el->name = "__tln__";
564
0
  }
565
0
  spn_el = ldb_msg_find_element(cross_res1->msgs[0], "msDS-SPNSuffixes");
566
0
  if (spn_el != NULL) {
567
0
    spn_el->name = "__tln__";
568
0
  }
569
0
  ret = ldb_msg_normalize(sam_ctx, frame, cross_res1->msgs[0], &tln_msg);
570
0
  if (ret != LDB_SUCCESS) {
571
0
    TALLOC_FREE(frame);
572
0
    return dsdb_ldb_err_to_ntstatus(ret);
573
0
  }
574
0
  tln_el = ldb_msg_find_element(tln_msg, "__tln__");
575
0
  if (tln_el != NULL) {
576
    /*
577
     * Sort the domains as trees
578
     */
579
0
    TYPESAFE_QSORT(tln_el->values, tln_el->num_values,
580
0
             dsdb_trust_xref_sort_vals);
581
0
  }
582
583
0
  for (i=0; i < cross_res2->count; i++) {
584
0
    struct ldb_message *m = cross_res2->msgs[i];
585
0
    const char *dns = NULL;
586
0
    const char *netbios = NULL;
587
0
    struct ldb_dn *nc_dn = NULL;
588
0
    struct dom_sid sid = {
589
0
      .num_auths = 0,
590
0
    };
591
0
    struct lsa_ForestTrustRecord2 e = {
592
0
      .flags = 0,
593
0
    };
594
0
    struct lsa_ForestTrustDomainInfo *d = NULL;
595
0
    struct lsa_StringLarge *t = NULL;
596
0
    bool match = false;
597
0
    NTSTATUS status;
598
599
0
    dns = ldb_msg_find_attr_as_string(m, "dnsRoot", NULL);
600
0
    if (dns == NULL) {
601
0
      TALLOC_FREE(frame);
602
0
      return NT_STATUS_INTERNAL_DB_CORRUPTION;
603
0
    }
604
605
0
    netbios = ldb_msg_find_attr_as_string(m, "nETBIOSName", NULL);
606
0
    if (netbios == NULL) {
607
0
      TALLOC_FREE(frame);
608
0
      return NT_STATUS_INTERNAL_DB_CORRUPTION;
609
0
    }
610
611
0
    nc_dn = samdb_result_dn(sam_ctx, m, m, "ncName", NULL);
612
0
    if (nc_dn == NULL) {
613
0
      TALLOC_FREE(frame);
614
0
      return NT_STATUS_INTERNAL_DB_CORRUPTION;
615
0
    }
616
617
0
    status = dsdb_get_extended_dn_sid(nc_dn, &sid, "SID");
618
0
    if (!NT_STATUS_IS_OK(status)) {
619
0
      TALLOC_FREE(frame);
620
0
      return status;
621
0
    }
622
623
0
    match = trust_forest_info_tln_match(info, dns);
624
0
    if (!match) {
625
      /*
626
       * First the TOP_LEVEL_NAME, if required
627
       */
628
0
      e = (struct lsa_ForestTrustRecord2) {
629
0
        .flags = 0,
630
0
        .type = LSA_FOREST_TRUST_TOP_LEVEL_NAME,
631
0
        .time = 0, /* so far always 0 in traces. */
632
0
      };
633
634
0
      t = &e.forest_trust_data.top_level_name;
635
0
      t->string = dns;
636
637
0
      status = dsdb_trust_forest_info_add_record(info, &e);
638
0
      if (!NT_STATUS_IS_OK(status)) {
639
0
        TALLOC_FREE(frame);
640
0
        return status;
641
0
      }
642
0
    }
643
644
    /*
645
     * Then the DOMAIN_INFO
646
     */
647
0
    e = (struct lsa_ForestTrustRecord2) {
648
0
      .flags = 0,
649
0
      .type = LSA_FOREST_TRUST_DOMAIN_INFO,
650
0
      .time = 0, /* so far always 0 in traces. */
651
0
    };
652
0
    d = &e.forest_trust_data.domain_info;
653
0
    d->domain_sid = &sid;
654
0
    d->dns_domain_name.string = dns;
655
0
    d->netbios_domain_name.string = netbios;
656
657
0
    status = dsdb_trust_forest_info_add_record(info, &e);
658
0
    if (!NT_STATUS_IS_OK(status)) {
659
0
      TALLOC_FREE(frame);
660
0
      return status;
661
0
    }
662
0
  }
663
664
0
  for (i=0; (tln_el != NULL) && i < tln_el->num_values; i++) {
665
0
    const struct ldb_val *v = &tln_el->values[i];
666
0
    const char *dns = (const char *)v->data;
667
0
    struct lsa_ForestTrustRecord2 e = {
668
0
      .flags = 0,
669
0
    };
670
0
    struct lsa_StringLarge *t = NULL;
671
0
    bool match = false;
672
0
    NTSTATUS status;
673
674
0
    if (dns == NULL) {
675
0
      TALLOC_FREE(frame);
676
0
      return NT_STATUS_INTERNAL_DB_CORRUPTION;
677
0
    }
678
679
0
    match = trust_forest_info_tln_match(info, dns);
680
0
    if (match) {
681
0
      continue;
682
0
    }
683
684
    /*
685
     * an additional the TOP_LEVEL_NAME
686
     */
687
0
    e = (struct lsa_ForestTrustRecord2) {
688
0
      .flags = 0,
689
0
      .type = LSA_FOREST_TRUST_TOP_LEVEL_NAME,
690
0
      .time = 0, /* so far always 0 in traces. */
691
0
    };
692
0
    t = &e.forest_trust_data.top_level_name;
693
0
    t->string = dns;
694
695
0
    status = dsdb_trust_forest_info_add_record(info, &e);
696
0
    if (!NT_STATUS_IS_OK(status)) {
697
0
      TALLOC_FREE(frame);
698
0
      return status;
699
0
    }
700
0
  }
701
702
0
  for (i=0; i < info->count; restart ? i=0 : i++) {
703
0
    struct lsa_ForestTrustRecord2 *tr = info->entries[i];
704
0
    const struct lsa_StringLarge *ts = NULL;
705
0
    uint32_t c;
706
707
0
    restart = false;
708
709
0
    if (tr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
710
0
      continue;
711
0
    }
712
713
0
    ts = &tr->forest_trust_data.top_level_name;
714
715
0
    for (c = i + 1; c < info->count; c++) {
716
0
      struct lsa_ForestTrustRecord2 *cr = info->entries[c];
717
0
      const struct lsa_StringLarge *cs = NULL;
718
0
      uint32_t j;
719
0
      int cmp;
720
721
0
      if (cr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
722
0
        continue;
723
0
      }
724
725
0
      cs = &cr->forest_trust_data.top_level_name;
726
727
0
      cmp = dns_cmp(ts->string, cs->string);
728
0
      if (DNS_CMP_IS_NO_MATCH(cmp)) {
729
0
        continue;
730
0
      }
731
0
      if (cmp != DNS_CMP_FIRST_IS_CHILD) {
732
        /* can't happen ... */
733
0
        continue;
734
0
      }
735
736
0
      ts = NULL;
737
0
      tr = NULL;
738
0
      TALLOC_FREE(info->entries[i]);
739
0
      info->entries[i] = info->entries[c];
740
741
0
      for (j = c + 1; j < info->count; j++) {
742
0
        info->entries[j-1] = info->entries[j];
743
0
      }
744
0
      info->count -= 1;
745
0
      restart = true;
746
0
      break;
747
0
    }
748
0
  }
749
750
0
  *_info = talloc_move(mem_ctx, &info);
751
0
  TALLOC_FREE(frame);
752
0
  return NT_STATUS_OK;
753
0
}
754
755
NTSTATUS dsdb_trust_parse_tdo_info(TALLOC_CTX *mem_ctx,
756
           struct ldb_message *m,
757
           struct lsa_TrustDomainInfoInfoEx **_tdo)
758
0
{
759
0
  struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
760
0
  const char *dns = NULL;
761
0
  const char *netbios = NULL;
762
763
0
  *_tdo = NULL;
764
765
0
  tdo = talloc_zero(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
766
0
  if (tdo == NULL) {
767
0
    return NT_STATUS_NO_MEMORY;
768
0
  }
769
770
0
  dns = ldb_msg_find_attr_as_string(m, "trustPartner", NULL);
771
0
  if (dns == NULL) {
772
0
    TALLOC_FREE(tdo);
773
0
    return NT_STATUS_INTERNAL_DB_CORRUPTION;
774
0
  }
775
0
  tdo->domain_name.string = talloc_strdup(tdo, dns);
776
0
  if (tdo->domain_name.string == NULL) {
777
0
    TALLOC_FREE(tdo);
778
0
    return NT_STATUS_NO_MEMORY;
779
0
  }
780
781
0
  netbios = ldb_msg_find_attr_as_string(m, "flatName", NULL);
782
0
  if (netbios == NULL) {
783
0
    TALLOC_FREE(tdo);
784
0
    return NT_STATUS_INTERNAL_DB_CORRUPTION;
785
0
  }
786
0
  tdo->netbios_name.string = talloc_strdup(tdo, netbios);
787
0
  if (tdo->netbios_name.string == NULL) {
788
0
    TALLOC_FREE(tdo);
789
0
    return NT_STATUS_NO_MEMORY;
790
0
  }
791
792
0
  tdo->sid = samdb_result_dom_sid(tdo, m, "securityIdentifier");
793
0
  if (tdo->sid == NULL) {
794
0
    TALLOC_FREE(tdo);
795
0
    return NT_STATUS_INTERNAL_DB_CORRUPTION;
796
0
  }
797
798
0
  tdo->trust_type = ldb_msg_find_attr_as_uint(m, "trustType", 0);
799
0
  tdo->trust_direction = ldb_msg_find_attr_as_uint(m, "trustDirection", 0);
800
0
  tdo->trust_attributes = ldb_msg_find_attr_as_uint(m, "trustAttributes", 0);
801
802
0
  *_tdo = tdo;
803
0
  return NT_STATUS_OK;
804
0
}
805
806
NTSTATUS dsdb_trust_parse_forest_info(TALLOC_CTX *mem_ctx,
807
              struct ldb_message *m,
808
              struct ForestTrustInfo **_fti)
809
0
{
810
0
  const struct ldb_val *ft_blob = NULL;
811
0
  struct ForestTrustInfo *fti = NULL;
812
0
  enum ndr_err_code ndr_err;
813
814
0
  *_fti = NULL;
815
816
0
  ft_blob = ldb_msg_find_ldb_val(m, "msDS-TrustForestTrustInfo");
817
0
  if (ft_blob == NULL) {
818
0
    return NT_STATUS_NOT_FOUND;
819
0
  }
820
821
0
  fti = talloc_zero(mem_ctx, struct ForestTrustInfo);
822
0
  if (fti == NULL) {
823
0
    return NT_STATUS_NO_MEMORY;
824
0
  }
825
826
  /* ldb_val is equivalent to DATA_BLOB */
827
0
  ndr_err = ndr_pull_struct_blob_all(ft_blob, fti, fti,
828
0
        (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
829
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
830
0
    TALLOC_FREE(fti);
831
0
    return NT_STATUS_INTERNAL_DB_CORRUPTION;
832
0
  }
833
834
0
  *_fti = fti;
835
0
  return NT_STATUS_OK;
836
0
}
837
838
NTSTATUS dsdb_trust_default_forest_info(TALLOC_CTX *mem_ctx,
839
          const struct dom_sid *sid,
840
          const char *dns_name,
841
          const char *nbt_name,
842
          NTTIME now,
843
          struct ForestTrustInfo **_fti)
844
0
{
845
0
  struct ForestTrustInfo *trust_fti = NULL;
846
0
  struct ForestTrustInfoRecordArmor *ra = NULL;
847
0
  struct ForestTrustInfoRecord *r = NULL;
848
849
0
  trust_fti = talloc_zero(mem_ctx, struct ForestTrustInfo);
850
0
  if (trust_fti == NULL) {
851
0
    return NT_STATUS_NO_MEMORY;
852
0
  }
853
854
0
  ra = talloc_zero_array(trust_fti,
855
0
             struct ForestTrustInfoRecordArmor,
856
0
             2);
857
0
  if (ra == NULL) {
858
0
    TALLOC_FREE(trust_fti);
859
0
    return NT_STATUS_NO_MEMORY;
860
0
  }
861
862
0
  r = &ra[0].record;
863
0
  r->type = FOREST_TRUST_TOP_LEVEL_NAME;
864
0
  r->timestamp = now;
865
0
  r->flags = 0;
866
0
  r->data.name.string = talloc_strdup(ra, dns_name);
867
0
  if (r->data.name.string == NULL) {
868
0
    TALLOC_FREE(trust_fti);
869
0
    return NT_STATUS_NO_MEMORY;
870
0
  }
871
872
0
  r = &ra[1].record;
873
0
  r->type = FOREST_TRUST_DOMAIN_INFO;
874
0
  r->timestamp = now;
875
0
  r->flags = 0;
876
0
  r->data.info.sid = *sid;
877
0
  r->data.info.dns_name.string = talloc_strdup(ra, dns_name);
878
0
  if (r->data.info.dns_name.string == NULL) {
879
0
    TALLOC_FREE(trust_fti);
880
0
    return NT_STATUS_NO_MEMORY;
881
0
  }
882
0
  r->data.info.netbios_name.string = talloc_strdup(ra, nbt_name);
883
0
  if (r->data.info.netbios_name.string == NULL) {
884
0
    TALLOC_FREE(trust_fti);
885
0
    return NT_STATUS_NO_MEMORY;
886
0
  }
887
888
0
  trust_fti->version = 1;
889
0
  trust_fti->records = ra;
890
0
  trust_fti->count = 2;
891
892
0
  *_fti = trust_fti;
893
0
  return NT_STATUS_OK;
894
0
}
895
896
NTSTATUS dsdb_trust_normalize_forest_info_step1(TALLOC_CTX *mem_ctx,
897
        const struct lsa_ForestTrustInformation2 *gfti,
898
        struct lsa_ForestTrustInformation2 **_nfti)
899
0
{
900
0
  TALLOC_CTX *frame = talloc_stackframe();
901
0
  struct lsa_ForestTrustInformation2 *nfti;
902
0
  uint32_t n;
903
904
0
  *_nfti = NULL;
905
906
0
  nfti = talloc_zero(mem_ctx, struct lsa_ForestTrustInformation2);
907
0
  if (nfti == NULL) {
908
0
    TALLOC_FREE(frame);
909
0
    return NT_STATUS_NO_MEMORY;
910
0
  }
911
0
  talloc_steal(frame, nfti);
912
913
  /*
914
   * First we copy every record and remove possible trailing dots
915
   * from dns names.
916
   *
917
   * We also NULL out duplicates. The first one wins and
918
   * we keep 'count' as is. This is required in order to
919
   * provide the correct index for collision records.
920
   */
921
0
  for (n = 0; n < gfti->count; n++) {
922
0
    const struct lsa_ForestTrustRecord2 *gftr = gfti->entries[n];
923
0
    struct lsa_ForestTrustRecord2 *nftr = NULL;
924
0
    struct lsa_ForestTrustDomainInfo *ninfo = NULL;
925
0
    struct lsa_StringLarge *ntln = NULL;
926
0
    struct lsa_StringLarge *nnb = NULL;
927
0
    struct dom_sid *nsid = NULL;
928
0
    NTSTATUS status;
929
0
    size_t len = 0;
930
0
    char *p = NULL;
931
0
    uint32_t c;
932
933
0
    if (gftr == NULL) {
934
0
      TALLOC_FREE(frame);
935
0
      return NT_STATUS_INVALID_PARAMETER;
936
0
    }
937
938
0
    status = dsdb_trust_forest_info_add_record(nfti, gftr);
939
0
    if (!NT_STATUS_IS_OK(status)) {
940
0
      TALLOC_FREE(frame);
941
0
      return status;
942
0
    }
943
944
0
    nftr = nfti->entries[n];
945
946
0
    switch (nftr->type) {
947
0
    case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
948
0
      ntln = &nftr->forest_trust_data.top_level_name;
949
0
      break;
950
951
0
    case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
952
0
      ntln = &nftr->forest_trust_data.top_level_name_ex;
953
0
      break;
954
955
0
    case LSA_FOREST_TRUST_DOMAIN_INFO:
956
0
      ninfo = &nftr->forest_trust_data.domain_info;
957
0
      ntln = &ninfo->dns_domain_name;
958
0
      nnb = &ninfo->netbios_domain_name;
959
0
      nsid = ninfo->domain_sid;
960
0
      break;
961
962
0
    case LSA_FOREST_TRUST_BINARY_DATA:
963
0
      continue;
964
965
0
    case LSA_FOREST_TRUST_SCANNER_INFO:
966
0
      if (nftr->flags & ~LSA_TLN_DISABLED_NEW) {
967
0
        return NT_STATUS_INVALID_PARAMETER;
968
0
      }
969
0
      ninfo = &nftr->forest_trust_data.scanner_info;
970
0
      ntln = &ninfo->dns_domain_name;
971
0
      nnb = &ninfo->netbios_domain_name;
972
0
      nsid = ninfo->domain_sid;
973
0
      break;
974
975
0
    default:
976
0
      TALLOC_FREE(frame);
977
0
      return NT_STATUS_INVALID_PARAMETER;
978
0
    }
979
980
    /*
981
     * We remove one trailing '.' before checking
982
     * for invalid dots.
983
     *
984
     * domain.com.  becomes domain.com
985
     * domain.com.. becomes domain.com.
986
     *
987
     * Then the following is invalid:
988
     *
989
     * domain..com
990
     * .domain.com
991
     * domain.com.
992
     */
993
0
    len = strlen(ntln->string);
994
0
    if (len > 1 && ntln->string[len - 1] == '.') {
995
0
      const char *cp = &ntln->string[len - 1];
996
0
      p = discard_const_p(char, cp);
997
0
      *p= '\0';
998
0
    }
999
0
    if (ntln->string[0] == '.') {
1000
0
      TALLOC_FREE(frame);
1001
0
      return NT_STATUS_INVALID_PARAMETER;
1002
0
    }
1003
0
    {
1004
0
      const char *dots = NULL;
1005
1006
0
      dots = strstr_m(ntln->string, "..");
1007
0
      if (dots != NULL) {
1008
0
        TALLOC_FREE(frame);
1009
0
        return NT_STATUS_INVALID_PARAMETER;
1010
0
      }
1011
0
    }
1012
1013
0
    if (nnb != NULL &&
1014
0
       (nnb->string == NULL ||
1015
0
        strlen(nnb->string) > 15))
1016
0
    {
1017
0
      TALLOC_FREE(frame);
1018
0
      return NT_STATUS_INVALID_PARAMETER;
1019
0
    }
1020
1021
0
    for (c = 0; c < n; c++) {
1022
0
      const struct lsa_ForestTrustRecord2 *cftr = nfti->entries[c];
1023
0
      const struct lsa_ForestTrustDomainInfo *cinfo = NULL;
1024
0
      const struct lsa_StringLarge *ctln = NULL;
1025
0
      const struct lsa_StringLarge *cnb = NULL;
1026
0
      const struct dom_sid *csid = NULL;
1027
0
      int cmp;
1028
1029
0
      if (cftr == NULL) {
1030
0
        continue;
1031
0
      }
1032
1033
0
      if (cftr->type != nftr->type) {
1034
0
        continue;
1035
0
      }
1036
1037
0
      switch (cftr->type) {
1038
0
      case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
1039
0
        ctln = &cftr->forest_trust_data.top_level_name;
1040
0
        break;
1041
1042
0
      case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
1043
0
        ctln = &cftr->forest_trust_data.top_level_name_ex;
1044
0
        break;
1045
1046
0
      case LSA_FOREST_TRUST_DOMAIN_INFO:
1047
0
        cinfo = &cftr->forest_trust_data.domain_info;
1048
0
        ctln = &cinfo->dns_domain_name;
1049
0
        cnb = &cinfo->netbios_domain_name;
1050
0
        csid = cinfo->domain_sid;
1051
0
        break;
1052
1053
0
      case LSA_FOREST_TRUST_SCANNER_INFO:
1054
0
        cinfo = &cftr->forest_trust_data.scanner_info;
1055
0
        ctln = &cinfo->dns_domain_name;
1056
0
        cnb = &cinfo->netbios_domain_name;
1057
0
        csid = cinfo->domain_sid;
1058
0
        break;
1059
1060
0
      default:
1061
0
        TALLOC_FREE(frame);
1062
0
        return NT_STATUS_INVALID_PARAMETER;
1063
0
      }
1064
1065
0
      cmp = dns_cmp(ntln->string, ctln->string);
1066
0
      if (cmp == DNS_CMP_MATCH) {
1067
0
        nftr = NULL;
1068
0
        TALLOC_FREE(nfti->entries[n]);
1069
0
        break;
1070
0
      }
1071
1072
0
      if (cinfo == NULL) {
1073
0
        continue;
1074
0
      }
1075
1076
0
      cmp = strcasecmp_m(nnb->string, cnb->string);
1077
0
      if (cmp == 0) {
1078
0
        nftr = NULL;
1079
0
        TALLOC_FREE(nfti->entries[n]);
1080
0
        break;
1081
0
      }
1082
1083
0
      if (cftr->type == LSA_FOREST_TRUST_SCANNER_INFO) {
1084
        /*
1085
         * ignore the sid
1086
         */
1087
0
        continue;
1088
0
      }
1089
1090
0
      cmp = dom_sid_compare(nsid, csid);
1091
0
      if (cmp == 0) {
1092
0
        nftr = NULL;
1093
0
        TALLOC_FREE(nfti->entries[n]);
1094
0
        break;
1095
0
      }
1096
0
    }
1097
0
  }
1098
1099
  /*
1100
   * Now we check that only true top level names are provided
1101
   */
1102
0
  for (n = 0; n < nfti->count; n++) {
1103
0
    const struct lsa_ForestTrustRecord2 *nftr = nfti->entries[n];
1104
0
    const struct lsa_StringLarge *ntln = NULL;
1105
0
    uint32_t c;
1106
1107
0
    if (nftr == NULL) {
1108
0
      continue;
1109
0
    }
1110
1111
0
    if (nftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
1112
0
      continue;
1113
0
    }
1114
1115
0
    ntln = &nftr->forest_trust_data.top_level_name;
1116
1117
0
    for (c = 0; c < nfti->count; c++) {
1118
0
      const struct lsa_ForestTrustRecord2 *cftr = nfti->entries[c];
1119
0
      const struct lsa_StringLarge *ctln = NULL;
1120
0
      int cmp;
1121
1122
0
      if (cftr == NULL) {
1123
0
        continue;
1124
0
      }
1125
1126
0
      if (cftr == nftr) {
1127
0
        continue;
1128
0
      }
1129
1130
0
      if (cftr->type != nftr->type) {
1131
0
        continue;
1132
0
      }
1133
1134
0
      ctln = &cftr->forest_trust_data.top_level_name;
1135
1136
0
      cmp = dns_cmp(ntln->string, ctln->string);
1137
0
      if (DNS_CMP_IS_NO_MATCH(cmp)) {
1138
0
        continue;
1139
0
      }
1140
1141
0
      TALLOC_FREE(frame);
1142
0
      return NT_STATUS_INVALID_PARAMETER;
1143
0
    }
1144
0
  }
1145
1146
  /*
1147
   * Now we check that only true sub level excludes are provided
1148
   */
1149
0
  for (n = 0; n < nfti->count; n++) {
1150
0
    const struct lsa_ForestTrustRecord2 *nftr = nfti->entries[n];
1151
0
    const struct lsa_StringLarge *ntln = NULL;
1152
0
    uint32_t c;
1153
0
    bool found_tln = false;
1154
1155
0
    if (nftr == NULL) {
1156
0
      continue;
1157
0
    }
1158
1159
0
    if (nftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX) {
1160
0
      continue;
1161
0
    }
1162
1163
0
    ntln = &nftr->forest_trust_data.top_level_name;
1164
1165
0
    for (c = 0; c < nfti->count; c++) {
1166
0
      const struct lsa_ForestTrustRecord2 *cftr = nfti->entries[c];
1167
0
      const struct lsa_StringLarge *ctln = NULL;
1168
0
      int cmp;
1169
1170
0
      if (cftr == NULL) {
1171
0
        continue;
1172
0
      }
1173
1174
0
      if (cftr == nftr) {
1175
0
        continue;
1176
0
      }
1177
1178
0
      if (cftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
1179
0
        continue;
1180
0
      }
1181
1182
0
      ctln = &cftr->forest_trust_data.top_level_name;
1183
1184
0
      cmp = dns_cmp(ntln->string, ctln->string);
1185
0
      if (cmp == DNS_CMP_FIRST_IS_CHILD) {
1186
0
        found_tln = true;
1187
0
        break;
1188
0
      }
1189
0
    }
1190
1191
0
    if (found_tln) {
1192
0
      continue;
1193
0
    }
1194
1195
0
    TALLOC_FREE(frame);
1196
0
    return NT_STATUS_INVALID_PARAMETER;
1197
0
  }
1198
1199
  /*
1200
   * Now we check that there's a top level name for each domain
1201
   */
1202
0
  for (n = 0; n < nfti->count; n++) {
1203
0
    const struct lsa_ForestTrustRecord2 *nftr = nfti->entries[n];
1204
0
    const struct lsa_ForestTrustDomainInfo *ninfo = NULL;
1205
0
    const struct lsa_StringLarge *ntln = NULL;
1206
0
    uint32_t c;
1207
0
    bool found_tln = false;
1208
1209
0
    if (nftr == NULL) {
1210
0
      continue;
1211
0
    }
1212
1213
0
    if (nftr->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
1214
0
      continue;
1215
0
    }
1216
1217
0
    ninfo = &nftr->forest_trust_data.domain_info;
1218
0
    ntln = &ninfo->dns_domain_name;
1219
1220
0
    for (c = 0; c < nfti->count; c++) {
1221
0
      const struct lsa_ForestTrustRecord2 *cftr = nfti->entries[c];
1222
0
      const struct lsa_StringLarge *ctln = NULL;
1223
0
      int cmp;
1224
1225
0
      if (cftr == NULL) {
1226
0
        continue;
1227
0
      }
1228
1229
0
      if (cftr == nftr) {
1230
0
        continue;
1231
0
      }
1232
1233
0
      if (cftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
1234
0
        continue;
1235
0
      }
1236
1237
0
      ctln = &cftr->forest_trust_data.top_level_name;
1238
1239
0
      cmp = dns_cmp(ntln->string, ctln->string);
1240
0
      if (cmp == DNS_CMP_MATCH) {
1241
0
        found_tln = true;
1242
0
        break;
1243
0
      }
1244
0
      if (cmp == DNS_CMP_FIRST_IS_CHILD) {
1245
0
        found_tln = true;
1246
0
        break;
1247
0
      }
1248
0
    }
1249
1250
0
    if (found_tln) {
1251
0
      continue;
1252
0
    }
1253
1254
0
    TALLOC_FREE(frame);
1255
0
    return NT_STATUS_INVALID_PARAMETER;
1256
0
  }
1257
1258
0
  *_nfti = talloc_move(mem_ctx, &nfti);
1259
0
  TALLOC_FREE(frame);
1260
0
  return NT_STATUS_OK;
1261
0
}
1262
1263
NTSTATUS dsdb_trust_normalize_forest_info_step2(TALLOC_CTX *mem_ctx,
1264
        const struct lsa_ForestTrustInformation2 *gfti,
1265
        struct lsa_ForestTrustInformation2 **_nfti)
1266
0
{
1267
0
  TALLOC_CTX *frame = talloc_stackframe();
1268
0
  struct timeval tv = timeval_current();
1269
0
  NTTIME now = timeval_to_nttime(&tv);
1270
0
  struct lsa_ForestTrustInformation2 *nfti;
1271
0
  uint32_t g;
1272
1273
0
  *_nfti = NULL;
1274
1275
0
  nfti = talloc_zero(mem_ctx, struct lsa_ForestTrustInformation2);
1276
0
  if (nfti == NULL) {
1277
0
    TALLOC_FREE(frame);
1278
0
    return NT_STATUS_NO_MEMORY;
1279
0
  }
1280
0
  talloc_steal(frame, nfti);
1281
1282
  /*
1283
   * Now we add TOP_LEVEL_NAME[_EX] in reverse order
1284
   * followed by LSA_FOREST_TRUST_DOMAIN_INFO in reverse order.
1285
   *
1286
   * LSA_FOREST_TRUST_SCANNER_INFO and LSA_FOREST_TRUST_BINARY_DATA
1287
   * are added last.
1288
   *
1289
   * This also removes the possible NULL entries generated in step1.
1290
   */
1291
1292
0
  for (g = 0; g < gfti->count; g++) {
1293
0
    const struct lsa_ForestTrustRecord2 *gftr = gfti->entries[gfti->count - (g+1)];
1294
0
    struct lsa_ForestTrustRecord2 tftr;
1295
0
    bool skip = false;
1296
0
    NTSTATUS status;
1297
1298
0
    if (gftr == NULL) {
1299
0
      continue;
1300
0
    }
1301
1302
0
    switch (gftr->type) {
1303
0
    case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
1304
0
    case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
1305
0
      break;
1306
1307
0
    case LSA_FOREST_TRUST_DOMAIN_INFO:
1308
0
    case LSA_FOREST_TRUST_BINARY_DATA:
1309
0
    case LSA_FOREST_TRUST_SCANNER_INFO:
1310
0
      skip = true;
1311
0
      break;
1312
1313
0
    default:
1314
0
      TALLOC_FREE(frame);
1315
0
      return NT_STATUS_INVALID_PARAMETER;
1316
0
    }
1317
1318
0
    if (skip) {
1319
0
      continue;
1320
0
    }
1321
1322
    /* make a copy in order to update the time. */
1323
0
    tftr = *gftr;
1324
0
    if (tftr.time == 0) {
1325
0
      tftr.time = now;
1326
0
    }
1327
1328
0
    status = dsdb_trust_forest_info_add_record(nfti, &tftr);
1329
0
    if (!NT_STATUS_IS_OK(status)) {
1330
0
      TALLOC_FREE(frame);
1331
0
      return status;
1332
0
    }
1333
0
  }
1334
1335
0
  for (g = 0; g < gfti->count; g++) {
1336
0
    const struct lsa_ForestTrustRecord2 *gftr = gfti->entries[gfti->count - (g+1)];
1337
0
    struct lsa_ForestTrustRecord2 tftr;
1338
0
    bool skip = false;
1339
0
    NTSTATUS status;
1340
1341
0
    if (gftr == NULL) {
1342
0
      continue;
1343
0
    }
1344
1345
0
    switch (gftr->type) {
1346
0
    case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
1347
0
    case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
1348
0
    case LSA_FOREST_TRUST_BINARY_DATA:
1349
0
    case LSA_FOREST_TRUST_SCANNER_INFO:
1350
0
      skip = true;
1351
0
      break;
1352
1353
0
    case LSA_FOREST_TRUST_DOMAIN_INFO:
1354
0
      break;
1355
1356
0
    default:
1357
0
      TALLOC_FREE(frame);
1358
0
      return NT_STATUS_INVALID_PARAMETER;
1359
0
    }
1360
1361
0
    if (skip) {
1362
0
      continue;
1363
0
    }
1364
1365
    /* make a copy in order to update the time. */
1366
0
    tftr = *gftr;
1367
0
    if (tftr.time == 0) {
1368
0
      tftr.time = now;
1369
0
    }
1370
1371
0
    status = dsdb_trust_forest_info_add_record(nfti, &tftr);
1372
0
    if (!NT_STATUS_IS_OK(status)) {
1373
0
      TALLOC_FREE(frame);
1374
0
      return status;
1375
0
    }
1376
0
  }
1377
1378
0
  for (g = 0; g < gfti->count; g++) {
1379
0
    const struct lsa_ForestTrustRecord2 *gftr = gfti->entries[gfti->count - (g+1)];
1380
0
    struct lsa_ForestTrustRecord2 tftr;
1381
0
    bool skip = false;
1382
0
    NTSTATUS status;
1383
1384
0
    if (gftr == NULL) {
1385
0
      continue;
1386
0
    }
1387
1388
0
    switch (gftr->type) {
1389
0
    case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
1390
0
    case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
1391
0
    case LSA_FOREST_TRUST_DOMAIN_INFO:
1392
0
    case LSA_FOREST_TRUST_BINARY_DATA:
1393
0
      skip = true;
1394
0
      break;
1395
1396
0
    case LSA_FOREST_TRUST_SCANNER_INFO:
1397
0
      break;
1398
1399
0
    default:
1400
0
      TALLOC_FREE(frame);
1401
0
      return NT_STATUS_INVALID_PARAMETER;
1402
0
    }
1403
1404
0
    if (skip) {
1405
0
      continue;
1406
0
    }
1407
1408
    /* make a copy in order to update the time. */
1409
0
    tftr = *gftr;
1410
0
    if (tftr.time == 0) {
1411
0
      tftr.time = now;
1412
0
    }
1413
1414
0
    status = dsdb_trust_forest_info_add_record(nfti, &tftr);
1415
0
    if (!NT_STATUS_IS_OK(status)) {
1416
0
      TALLOC_FREE(frame);
1417
0
      return status;
1418
0
    }
1419
0
  }
1420
1421
0
  for (g = 0; g < gfti->count; g++) {
1422
0
    const struct lsa_ForestTrustRecord2 *gftr = gfti->entries[gfti->count - (g+1)];
1423
0
    struct lsa_ForestTrustRecord2 tftr;
1424
0
    bool skip = false;
1425
0
    NTSTATUS status;
1426
1427
0
    if (gftr == NULL) {
1428
0
      continue;
1429
0
    }
1430
1431
0
    switch (gftr->type) {
1432
0
    case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
1433
0
    case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
1434
0
    case LSA_FOREST_TRUST_DOMAIN_INFO:
1435
0
    case LSA_FOREST_TRUST_SCANNER_INFO:
1436
0
      skip = true;
1437
0
      break;
1438
1439
0
    case LSA_FOREST_TRUST_BINARY_DATA:
1440
0
      break;
1441
1442
0
    default:
1443
0
      TALLOC_FREE(frame);
1444
0
      return NT_STATUS_INVALID_PARAMETER;
1445
0
    }
1446
1447
0
    if (skip) {
1448
0
      continue;
1449
0
    }
1450
1451
    /* make a copy in order to update the time. */
1452
0
    tftr = *gftr;
1453
0
    if (tftr.time == 0) {
1454
0
      tftr.time = now;
1455
0
    }
1456
1457
0
    status = dsdb_trust_forest_info_add_record(nfti, &tftr);
1458
0
    if (!NT_STATUS_IS_OK(status)) {
1459
0
      TALLOC_FREE(frame);
1460
0
      return status;
1461
0
    }
1462
0
  }
1463
1464
0
  *_nfti = talloc_move(mem_ctx, &nfti);
1465
0
  TALLOC_FREE(frame);
1466
0
  return NT_STATUS_OK;
1467
0
}
1468
1469
static NTSTATUS dsdb_trust_add_collision(
1470
      struct lsa_ForestTrustCollisionInfo *c_info,
1471
      enum lsa_ForestTrustCollisionRecordType type,
1472
      uint32_t idx, uint32_t flags,
1473
      const char *tdo_name)
1474
0
{
1475
0
  struct lsa_ForestTrustCollisionRecord **es;
1476
0
  uint32_t i = c_info->count;
1477
1478
0
  es = talloc_realloc(c_info, c_info->entries,
1479
0
          struct lsa_ForestTrustCollisionRecord *, i + 1);
1480
0
  if (es == NULL) {
1481
0
    return NT_STATUS_NO_MEMORY;
1482
0
  }
1483
0
  c_info->entries = es;
1484
0
  c_info->count = i + 1;
1485
1486
0
  es[i] = talloc_zero(es, struct lsa_ForestTrustCollisionRecord);
1487
0
  if (es[i] == NULL) {
1488
0
    return NT_STATUS_NO_MEMORY;
1489
0
  }
1490
1491
0
  es[i]->index = idx;
1492
0
  es[i]->type = type;
1493
0
  es[i]->flags = flags;
1494
0
  es[i]->name.string = talloc_strdup(es[i], tdo_name);
1495
0
  if (es[i]->name.string == NULL) {
1496
0
    return NT_STATUS_NO_MEMORY;
1497
0
  }
1498
1499
0
  return NT_STATUS_OK;
1500
0
}
1501
1502
NTSTATUS dsdb_trust_verify_forest_info(const struct lsa_TrustDomainInfoInfoEx *ref_tdo,
1503
        const struct lsa_ForestTrustInformation2 *ref_fti,
1504
        enum lsa_ForestTrustCollisionRecordType collision_type,
1505
        struct lsa_ForestTrustCollisionInfo *c_info,
1506
        struct lsa_ForestTrustInformation2 *new_fti)
1507
0
{
1508
0
  uint32_t n;
1509
1510
0
  for (n = 0; n < new_fti->count; n++) {
1511
0
    struct lsa_ForestTrustRecord2 *nftr = new_fti->entries[n];
1512
0
    struct lsa_StringLarge *ntln = NULL;
1513
0
    bool ntln_excluded = false;
1514
0
    uint32_t flags = 0;
1515
0
    uint32_t r;
1516
0
    NTSTATUS status;
1517
1518
0
    if (nftr == NULL) {
1519
0
      continue;
1520
0
    }
1521
1522
0
    if (nftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
1523
0
      continue;
1524
0
    }
1525
1526
0
    ntln = &nftr->forest_trust_data.top_level_name;
1527
0
    if (ntln->string == NULL) {
1528
0
      return NT_STATUS_INVALID_PARAMETER;
1529
0
    }
1530
1531
0
    ntln_excluded = trust_forest_info_tln_ex_match(ref_fti,
1532
0
                     ntln->string);
1533
1534
    /* check if this is already taken and not excluded */
1535
0
    for (r = 0; r < ref_fti->count; r++) {
1536
0
      const struct lsa_ForestTrustRecord2 *rftr =
1537
0
        ref_fti->entries[r];
1538
0
      const struct lsa_StringLarge *rtln = NULL;
1539
0
      int cmp;
1540
1541
0
      if (rftr == NULL) {
1542
0
        continue;
1543
0
      }
1544
1545
0
      if (rftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
1546
0
        continue;
1547
0
      }
1548
1549
0
      rtln = &rftr->forest_trust_data.top_level_name;
1550
0
      if (rtln->string == NULL) {
1551
0
        continue;
1552
0
      }
1553
1554
0
      cmp = dns_cmp(ntln->string, rtln->string);
1555
0
      if (DNS_CMP_IS_NO_MATCH(cmp)) {
1556
0
        continue;
1557
0
      }
1558
0
      if (cmp == DNS_CMP_MATCH) {
1559
        /* We need to normalize the string */
1560
0
        ntln->string = talloc_strdup(nftr,
1561
0
                   rtln->string);
1562
0
        if (ntln->string == NULL) {
1563
0
          return NT_STATUS_NO_MEMORY;
1564
0
        }
1565
0
      }
1566
1567
0
      if (ntln_excluded) {
1568
0
        continue;
1569
0
      }
1570
1571
0
      if (rftr->flags & LSA_TLN_DISABLED_MASK) {
1572
0
        continue;
1573
0
      }
1574
1575
0
      if (nftr->flags & LSA_TLN_DISABLED_MASK) {
1576
0
        continue;
1577
0
      }
1578
1579
0
      if (cmp == DNS_CMP_SECOND_IS_CHILD) {
1580
0
        bool m;
1581
1582
        /*
1583
         * If the conflicting tln is a child, check if
1584
         * we have an exclusion record for it.
1585
         */
1586
0
        m = trust_forest_info_tln_ex_match(new_fti,
1587
0
                   rtln->string);
1588
0
        if (m) {
1589
0
          continue;
1590
0
        }
1591
0
      }
1592
1593
0
      flags |= LSA_TLN_DISABLED_CONFLICT;
1594
0
    }
1595
1596
0
    if (flags == 0) {
1597
0
      continue;
1598
0
    }
1599
1600
0
    nftr->flags |= flags;
1601
1602
0
    status = dsdb_trust_add_collision(c_info,
1603
0
              collision_type,
1604
0
              n, nftr->flags,
1605
0
              ref_tdo->domain_name.string);
1606
0
    if (!NT_STATUS_IS_OK(status)) {
1607
0
      return status;
1608
0
    }
1609
0
  }
1610
1611
0
  for (n = 0; n < new_fti->count; n++) {
1612
0
    struct lsa_ForestTrustRecord2 *nftr = new_fti->entries[n];
1613
0
    struct lsa_ForestTrustDomainInfo *ninfo = NULL;
1614
0
    struct lsa_StringLarge *ntln = NULL;
1615
0
    struct lsa_StringLarge *nnb = NULL;
1616
0
    struct dom_sid *nsid = NULL;
1617
0
    bool ntln_found = false;
1618
0
    uint32_t flags = 0;
1619
0
    uint32_t r;
1620
0
    NTSTATUS status;
1621
1622
0
    if (nftr == NULL) {
1623
0
      continue;
1624
0
    }
1625
1626
0
    if (nftr->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
1627
0
      continue;
1628
0
    }
1629
1630
0
    ninfo = &nftr->forest_trust_data.domain_info;
1631
0
    ntln = &ninfo->dns_domain_name;
1632
0
    if (ntln->string == NULL) {
1633
0
      return NT_STATUS_INVALID_PARAMETER;
1634
0
    }
1635
0
    nnb = &ninfo->netbios_domain_name;
1636
0
    if (nnb->string == NULL) {
1637
0
      return NT_STATUS_INVALID_PARAMETER;
1638
0
    }
1639
0
    nsid = ninfo->domain_sid;
1640
0
    if (nsid == NULL) {
1641
0
      return NT_STATUS_INVALID_PARAMETER;
1642
0
    }
1643
1644
0
    ntln_found = trust_forest_info_tln_match(ref_fti, ntln->string);
1645
1646
    /* check if this is already taken and not excluded */
1647
0
    for (r = 0; r < ref_fti->count; r++) {
1648
0
      const struct lsa_ForestTrustRecord2 *rftr =
1649
0
        ref_fti->entries[r];
1650
0
      const struct lsa_ForestTrustDomainInfo *rinfo = NULL;
1651
0
      const struct lsa_StringLarge *rtln = NULL;
1652
0
      const struct lsa_StringLarge *rnb = NULL;
1653
0
      const struct dom_sid *rsid = NULL;
1654
0
      bool nb_possible = true;
1655
0
      bool sid_possible = true;
1656
0
      int cmp;
1657
1658
0
      if (rftr == NULL) {
1659
0
        continue;
1660
0
      }
1661
1662
0
      if (!ntln_found) {
1663
        /*
1664
         * If the dns name doesn't match any existing
1665
         * tln any conflict is ignored, but name
1666
         * normalization still happens.
1667
         *
1668
         * I guess that's a bug in Windows
1669
         * (tested with Windows 2012r2).
1670
         */
1671
0
        nb_possible = false;
1672
0
        sid_possible = false;
1673
0
      }
1674
1675
0
      if (nftr->flags & LSA_SID_DISABLED_MASK) {
1676
0
        sid_possible = false;
1677
0
      }
1678
1679
0
      if (nftr->flags & LSA_NB_DISABLED_MASK) {
1680
0
        nb_possible = false;
1681
0
      }
1682
1683
0
      switch (rftr->type) {
1684
0
      case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
1685
0
        rtln = &rftr->forest_trust_data.top_level_name;
1686
0
        nb_possible = false;
1687
0
        sid_possible = false;
1688
0
        break;
1689
1690
0
      case LSA_FOREST_TRUST_DOMAIN_INFO:
1691
0
        rinfo = &rftr->forest_trust_data.domain_info;
1692
0
        rtln = &rinfo->dns_domain_name;
1693
0
        rnb = &rinfo->netbios_domain_name;
1694
0
        rsid = rinfo->domain_sid;
1695
1696
0
        if (rftr->flags & LSA_SID_DISABLED_MASK) {
1697
0
          sid_possible = false;
1698
0
        }
1699
1700
0
        if (rftr->flags & LSA_NB_DISABLED_MASK) {
1701
0
          nb_possible = false;
1702
0
        }
1703
0
        break;
1704
1705
0
      default:
1706
0
        break;
1707
0
      }
1708
1709
0
      if (rtln == NULL) {
1710
0
        continue;
1711
0
      }
1712
1713
0
      if (rtln->string == NULL) {
1714
0
        continue;
1715
0
      }
1716
1717
0
      cmp = dns_cmp(ntln->string, rtln->string);
1718
0
      if (DNS_CMP_IS_NO_MATCH(cmp)) {
1719
0
        nb_possible = false;
1720
0
        sid_possible = false;
1721
0
      }
1722
0
      if (cmp == DNS_CMP_MATCH) {
1723
        /* We need to normalize the string */
1724
0
        ntln->string = talloc_strdup(nftr,
1725
0
                   rtln->string);
1726
0
        if (ntln->string == NULL) {
1727
0
          return NT_STATUS_NO_MEMORY;
1728
0
        }
1729
0
      }
1730
1731
0
      if (rinfo == NULL) {
1732
0
        continue;
1733
0
      }
1734
1735
0
      if (rsid != NULL) {
1736
0
        cmp = dom_sid_compare(nsid, rsid);
1737
0
      } else {
1738
0
        cmp = -1;
1739
0
      }
1740
0
      if (cmp == 0) {
1741
0
        if (sid_possible) {
1742
0
          flags |= LSA_SID_DISABLED_CONFLICT;
1743
0
        }
1744
0
      }
1745
1746
0
      if (rnb->string != NULL) {
1747
0
        cmp = strcasecmp_m(nnb->string, rnb->string);
1748
0
      } else {
1749
0
        cmp = -1;
1750
0
      }
1751
0
      if (cmp == 0) {
1752
0
        nnb->string = talloc_strdup(nftr, rnb->string);
1753
0
        if (nnb->string == NULL) {
1754
0
          return NT_STATUS_NO_MEMORY;
1755
0
        }
1756
0
        if (nb_possible) {
1757
0
          flags |= LSA_NB_DISABLED_CONFLICT;
1758
0
        }
1759
0
      }
1760
0
    }
1761
1762
0
    if (flags == 0) {
1763
0
      continue;
1764
0
    }
1765
1766
0
    nftr->flags |= flags;
1767
1768
0
    status = dsdb_trust_add_collision(c_info,
1769
0
              collision_type,
1770
0
              n, nftr->flags,
1771
0
              ref_tdo->domain_name.string);
1772
0
    if (!NT_STATUS_IS_OK(status)) {
1773
0
      return status;
1774
0
    }
1775
0
  }
1776
1777
0
  return NT_STATUS_OK;
1778
0
}
1779
1780
NTSTATUS dsdb_trust_merge_forest_info(TALLOC_CTX *mem_ctx,
1781
        const struct lsa_TrustDomainInfoInfoEx *tdo,
1782
        const struct lsa_ForestTrustInformation2 *ofti,
1783
        const struct lsa_ForestTrustInformation2 *nfti,
1784
        struct lsa_ForestTrustInformation2 **_mfti)
1785
0
{
1786
0
  TALLOC_CTX *frame = talloc_stackframe();
1787
0
  struct lsa_ForestTrustInformation2 *mfti = NULL;
1788
0
  uint32_t ni;
1789
0
  uint32_t oi;
1790
0
  NTSTATUS status;
1791
0
  int cmp;
1792
1793
0
  *_mfti = NULL;
1794
0
  mfti = talloc_zero(mem_ctx, struct lsa_ForestTrustInformation2);
1795
0
  if (mfti == NULL) {
1796
0
    TALLOC_FREE(frame);
1797
0
    return NT_STATUS_NO_MEMORY;
1798
0
  }
1799
0
  talloc_steal(frame, mfti);
1800
1801
  /*
1802
   * First we add all top unique level names.
1803
   *
1804
   * The one matching the tdo dns name, will be
1805
   * added without further checking. All others
1806
   * may keep the flags and time values.
1807
   */
1808
0
  for (ni = 0; ni < nfti->count; ni++) {
1809
0
    const struct lsa_ForestTrustRecord2 *nftr = nfti->entries[ni];
1810
0
    struct lsa_ForestTrustRecord2 tftr = {
1811
0
      .flags = 0,
1812
0
    };
1813
0
    const char *ndns = NULL;
1814
0
    bool ignore_new = false;
1815
0
    bool found_old = false;
1816
0
    uint32_t mi;
1817
1818
0
    if (nftr == NULL) {
1819
0
      TALLOC_FREE(frame);
1820
0
      return NT_STATUS_INVALID_PARAMETER;
1821
0
    }
1822
1823
0
    if (nftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
1824
0
      continue;
1825
0
    }
1826
1827
0
    ndns = nftr->forest_trust_data.top_level_name.string;
1828
0
    if (ndns == NULL) {
1829
0
      TALLOC_FREE(frame);
1830
0
      return NT_STATUS_INVALID_PARAMETER;
1831
0
    }
1832
1833
0
    cmp = dns_cmp(tdo->domain_name.string, ndns);
1834
0
    if (cmp == DNS_CMP_MATCH) {
1835
0
      status = dsdb_trust_forest_info_add_record(mfti, nftr);
1836
0
      if (!NT_STATUS_IS_OK(status)) {
1837
0
        TALLOC_FREE(frame);
1838
0
        return status;
1839
0
      }
1840
0
    }
1841
1842
0
    for (mi = 0; mi < mfti->count; mi++) {
1843
0
      const struct lsa_ForestTrustRecord2 *mftr =
1844
0
        mfti->entries[mi];
1845
0
      const char *mdns = NULL;
1846
1847
      /*
1848
       * we just added this above, so we're sure to have a
1849
       * valid LSA_FOREST_TRUST_TOP_LEVEL_NAME record
1850
       */
1851
0
      mdns = mftr->forest_trust_data.top_level_name.string;
1852
1853
0
      cmp = dns_cmp(mdns, ndns);
1854
0
      switch (cmp) {
1855
0
      case DNS_CMP_MATCH:
1856
0
      case DNS_CMP_SECOND_IS_CHILD:
1857
0
        ignore_new = true;
1858
0
        break;
1859
0
      }
1860
1861
0
      if (ignore_new) {
1862
0
        break;
1863
0
      }
1864
0
    }
1865
1866
0
    if (ignore_new) {
1867
0
      continue;
1868
0
    }
1869
1870
    /*
1871
     * make a temporary copy where we can change time and flags
1872
     */
1873
0
    tftr = *nftr;
1874
1875
0
    for (oi = 0; oi < ofti->count; oi++) {
1876
0
      const struct lsa_ForestTrustRecord2 *oftr =
1877
0
        ofti->entries[oi];
1878
0
      const char *odns = NULL;
1879
1880
0
      if (oftr == NULL) {
1881
        /*
1882
         * broken record => ignore...
1883
         */
1884
0
        continue;
1885
0
      }
1886
1887
0
      if (oftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
1888
0
        continue;
1889
0
      }
1890
1891
0
      odns = oftr->forest_trust_data.top_level_name.string;
1892
0
      if (odns == NULL) {
1893
        /*
1894
         * broken record => ignore...
1895
         */
1896
0
        continue;
1897
0
      }
1898
1899
0
      cmp = dns_cmp(odns, ndns);
1900
0
      if (cmp != DNS_CMP_MATCH) {
1901
0
        continue;
1902
0
      }
1903
1904
0
      found_old = true;
1905
0
      tftr.flags = oftr->flags;
1906
0
      tftr.time = oftr->time;
1907
0
    }
1908
1909
0
    if (!found_old) {
1910
0
      tftr.flags = LSA_TLN_DISABLED_NEW;
1911
0
      tftr.time = 0;
1912
0
    }
1913
1914
0
    status = dsdb_trust_forest_info_add_record(mfti, &tftr);
1915
0
    if (!NT_STATUS_IS_OK(status)) {
1916
0
      TALLOC_FREE(frame);
1917
0
      return status;
1918
0
    }
1919
0
  }
1920
1921
  /*
1922
   * Now we add all unique (based on their SID) domains
1923
   * and may keep the flags and time values.
1924
   */
1925
0
  for (ni = 0; ni < nfti->count; ni++) {
1926
0
    const struct lsa_ForestTrustRecord2 *nftr = nfti->entries[ni];
1927
0
    struct lsa_ForestTrustRecord2 tftr = {
1928
0
      .flags = 0,
1929
0
    };
1930
0
    const struct lsa_ForestTrustDomainInfo *nd = NULL;
1931
0
    const char *ndns = NULL;
1932
0
    const char *nnbt = NULL;
1933
0
    bool ignore_new = false;
1934
0
    bool found_old = false;
1935
0
    uint32_t mi;
1936
1937
0
    if (nftr == NULL) {
1938
0
      TALLOC_FREE(frame);
1939
0
      return NT_STATUS_INVALID_PARAMETER;
1940
0
    }
1941
1942
0
    if (nftr->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
1943
0
      continue;
1944
0
    }
1945
1946
0
    nd = &nftr->forest_trust_data.domain_info;
1947
0
    if (nd->domain_sid == NULL) {
1948
0
      TALLOC_FREE(frame);
1949
0
      return NT_STATUS_INVALID_PARAMETER;
1950
0
    }
1951
0
    ndns = nd->dns_domain_name.string;
1952
0
    if (ndns == NULL) {
1953
0
      TALLOC_FREE(frame);
1954
0
      return NT_STATUS_INVALID_PARAMETER;
1955
0
    }
1956
0
    nnbt = nd->netbios_domain_name.string;
1957
0
    if (nnbt == NULL) {
1958
0
      TALLOC_FREE(frame);
1959
0
      return NT_STATUS_INVALID_PARAMETER;
1960
0
    }
1961
1962
0
    for (mi = 0; mi < mfti->count; mi++) {
1963
0
      const struct lsa_ForestTrustRecord2 *mftr =
1964
0
        mfti->entries[mi];
1965
0
      const struct lsa_ForestTrustDomainInfo *md = NULL;
1966
1967
0
      if (mftr->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
1968
0
        continue;
1969
0
      }
1970
1971
      /*
1972
       * we just added this above, so we're sure to have a
1973
       * valid LSA_FOREST_TRUST_DOMAIN_INFO record
1974
       */
1975
0
      md = &mftr->forest_trust_data.domain_info;
1976
1977
0
      cmp = dom_sid_compare(nd->domain_sid, md->domain_sid);
1978
0
      if (cmp == 0) {
1979
0
        ignore_new = true;
1980
0
        break;
1981
0
      }
1982
0
    }
1983
1984
0
    if (ignore_new) {
1985
0
      continue;
1986
0
    }
1987
1988
    /*
1989
     * make a temporary copy where we can change time and flags
1990
     */
1991
0
    tftr = *nftr;
1992
1993
0
    for (oi = 0; oi < ofti->count; oi++) {
1994
0
      const struct lsa_ForestTrustRecord2 *oftr =
1995
0
        ofti->entries[oi];
1996
0
      const struct lsa_ForestTrustDomainInfo *od = NULL;
1997
0
      const char *onbt = NULL;
1998
1999
0
      if (oftr == NULL) {
2000
        /*
2001
         * broken record => ignore...
2002
         */
2003
0
        continue;
2004
0
      }
2005
2006
0
      if (oftr->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
2007
0
        continue;
2008
0
      }
2009
2010
0
      od = &oftr->forest_trust_data.domain_info;
2011
0
      onbt = od->netbios_domain_name.string;
2012
0
      if (onbt == NULL) {
2013
        /*
2014
         * broken record => ignore...
2015
         */
2016
0
        continue;
2017
0
      }
2018
2019
0
      cmp = strcasecmp(onbt, nnbt);
2020
0
      if (cmp != 0) {
2021
0
        continue;
2022
0
      }
2023
2024
0
      found_old = true;
2025
0
      tftr.flags = oftr->flags;
2026
0
      tftr.time = oftr->time;
2027
0
    }
2028
2029
0
    if (!found_old) {
2030
0
      tftr.flags = 0;
2031
0
      tftr.time = 0;
2032
0
    }
2033
2034
0
    status = dsdb_trust_forest_info_add_record(mfti, &tftr);
2035
0
    if (!NT_STATUS_IS_OK(status)) {
2036
0
      TALLOC_FREE(frame);
2037
0
      return status;
2038
0
    }
2039
0
  }
2040
2041
  /*
2042
   * We keep old domain records disabled by the admin
2043
   * if not already in the list.
2044
   */
2045
0
  for (oi = 0; oi < ofti->count; oi++) {
2046
0
    const struct lsa_ForestTrustRecord2 *oftr =
2047
0
      ofti->entries[oi];
2048
0
    const struct lsa_ForestTrustDomainInfo *od = NULL;
2049
0
    const char *odns = NULL;
2050
0
    const char *onbt = NULL;
2051
0
    bool ignore_old = true;
2052
0
    uint32_t mi;
2053
2054
0
    if (oftr == NULL) {
2055
      /*
2056
       * broken record => ignore...
2057
       */
2058
0
      continue;
2059
0
    }
2060
2061
0
    if (oftr->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
2062
0
      continue;
2063
0
    }
2064
2065
0
    od = &oftr->forest_trust_data.domain_info;
2066
0
    odns = od->dns_domain_name.string;
2067
0
    if (odns == NULL) {
2068
      /*
2069
       * broken record => ignore...
2070
       */
2071
0
      continue;
2072
0
    }
2073
0
    onbt = od->netbios_domain_name.string;
2074
0
    if (onbt == NULL) {
2075
      /*
2076
       * broken record => ignore...
2077
       */
2078
0
      continue;
2079
0
    }
2080
0
    if (od->domain_sid == NULL) {
2081
      /*
2082
       * broken record => ignore...
2083
       */
2084
0
      continue;
2085
0
    }
2086
2087
0
    if (oftr->flags & LSA_NB_DISABLED_ADMIN) {
2088
0
      ignore_old = false;
2089
0
    } else if (oftr->flags & LSA_SID_DISABLED_ADMIN) {
2090
0
      ignore_old = false;
2091
0
    }
2092
2093
0
    for (mi = 0; mi < mfti->count; mi++) {
2094
0
      const struct lsa_ForestTrustRecord2 *mftr =
2095
0
        mfti->entries[mi];
2096
0
      const struct lsa_ForestTrustDomainInfo *md = NULL;
2097
2098
0
      if (mftr->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
2099
0
        continue;
2100
0
      }
2101
2102
      /*
2103
       * we just added this above, so we're sure to have a
2104
       * valid LSA_FOREST_TRUST_DOMAIN_INFO record
2105
       */
2106
0
      md = &mftr->forest_trust_data.domain_info;
2107
2108
0
      cmp = dom_sid_compare(od->domain_sid, md->domain_sid);
2109
0
      if (cmp == 0) {
2110
0
        ignore_old = true;
2111
0
        break;
2112
0
      }
2113
0
    }
2114
2115
0
    if (ignore_old) {
2116
0
      continue;
2117
0
    }
2118
2119
0
    status = dsdb_trust_forest_info_add_record(mfti, oftr);
2120
0
    if (!NT_STATUS_IS_OK(status)) {
2121
0
      TALLOC_FREE(frame);
2122
0
      return status;
2123
0
    }
2124
0
  }
2125
2126
  /*
2127
   * Finally we readd top level exclusions,
2128
   * if they still match a top level name.
2129
   */
2130
0
  for (oi = 0; oi < ofti->count; oi++) {
2131
0
    const struct lsa_ForestTrustRecord2 *oftr =
2132
0
      ofti->entries[oi];
2133
0
    const char *odns = NULL;
2134
0
    bool ignore_old = false;
2135
0
    uint32_t mi;
2136
2137
0
    if (oftr == NULL) {
2138
      /*
2139
       * broken record => ignore...
2140
       */
2141
0
      continue;
2142
0
    }
2143
2144
0
    if (oftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX) {
2145
0
      continue;
2146
0
    }
2147
2148
0
    odns = oftr->forest_trust_data.top_level_name_ex.string;
2149
0
    if (odns == NULL) {
2150
      /*
2151
       * broken record => ignore...
2152
       */
2153
0
      continue;
2154
0
    }
2155
2156
0
    for (mi = 0; mi < mfti->count; mi++) {
2157
0
      const struct lsa_ForestTrustRecord2 *mftr =
2158
0
        mfti->entries[mi];
2159
0
      const char *mdns = NULL;
2160
2161
0
      if (mftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
2162
0
        continue;
2163
0
      }
2164
2165
      /*
2166
       * we just added this above, so we're sure to have a
2167
       * valid LSA_FOREST_TRUST_TOP_LEVEL_NAME.
2168
       */
2169
0
      mdns = mftr->forest_trust_data.top_level_name.string;
2170
2171
0
      cmp = dns_cmp(mdns, odns);
2172
0
      switch (cmp) {
2173
0
      case DNS_CMP_MATCH:
2174
0
      case DNS_CMP_SECOND_IS_CHILD:
2175
0
        break;
2176
0
      default:
2177
0
        ignore_old = true;
2178
0
        break;
2179
0
      }
2180
2181
0
      if (ignore_old) {
2182
0
        break;
2183
0
      }
2184
0
    }
2185
2186
0
    if (ignore_old) {
2187
0
      continue;
2188
0
    }
2189
2190
0
    status = dsdb_trust_forest_info_add_record(mfti, oftr);
2191
0
    if (!NT_STATUS_IS_OK(status)) {
2192
0
      TALLOC_FREE(frame);
2193
0
      return status;
2194
0
    }
2195
0
  }
2196
2197
  /*
2198
   * Finally we readd scanner info records
2199
   */
2200
0
  for (oi = 0; oi < ofti->count; oi++) {
2201
0
    const struct lsa_ForestTrustRecord2 *oftr =
2202
0
      ofti->entries[oi];
2203
2204
0
    if (oftr == NULL) {
2205
      /*
2206
       * broken record => ignore...
2207
       */
2208
0
      continue;
2209
0
    }
2210
2211
0
    if (oftr->type != LSA_FOREST_TRUST_SCANNER_INFO) {
2212
0
      continue;
2213
0
    }
2214
2215
0
    status = dsdb_trust_forest_info_add_record(mfti, oftr);
2216
0
    if (!NT_STATUS_IS_OK(status)) {
2217
0
      TALLOC_FREE(frame);
2218
0
      return status;
2219
0
    }
2220
0
  }
2221
2222
  /*
2223
   * Finally we readd binary info records
2224
   */
2225
0
  for (oi = 0; oi < ofti->count; oi++) {
2226
0
    const struct lsa_ForestTrustRecord2 *oftr =
2227
0
      ofti->entries[oi];
2228
2229
0
    if (oftr == NULL) {
2230
      /*
2231
       * broken record => ignore...
2232
       */
2233
0
      continue;
2234
0
    }
2235
2236
0
    if (oftr->type != LSA_FOREST_TRUST_BINARY_DATA) {
2237
0
      continue;
2238
0
    }
2239
2240
0
    status = dsdb_trust_forest_info_add_record(mfti, oftr);
2241
0
    if (!NT_STATUS_IS_OK(status)) {
2242
0
      TALLOC_FREE(frame);
2243
0
      return status;
2244
0
    }
2245
0
  }
2246
2247
0
  *_mfti = talloc_move(mem_ctx, &mfti);
2248
0
  TALLOC_FREE(frame);
2249
0
  return NT_STATUS_OK;
2250
0
}
2251
2252
NTSTATUS dsdb_trust_search_tdo(struct ldb_context *sam_ctx,
2253
             const char *netbios, const char *dns,
2254
             const char * const *attrs,
2255
             TALLOC_CTX *mem_ctx,
2256
             struct ldb_message **msg)
2257
0
{
2258
0
  TALLOC_CTX *frame = talloc_stackframe();
2259
0
  int ret;
2260
0
  struct ldb_dn *system_dn = NULL;
2261
0
  char *netbios_encoded = NULL;
2262
0
  char *dns_encoded = NULL;
2263
0
  char *filter = NULL;
2264
2265
0
  *msg = NULL;
2266
2267
0
  if (netbios == NULL && dns == NULL) {
2268
0
    TALLOC_FREE(frame);
2269
0
    return NT_STATUS_INVALID_PARAMETER_MIX;
2270
0
  }
2271
2272
0
  system_dn = samdb_system_container_dn(sam_ctx, frame);
2273
0
  if (system_dn == NULL) {
2274
0
    TALLOC_FREE(frame);
2275
0
    return NT_STATUS_NO_MEMORY;
2276
0
  }
2277
2278
0
  if (netbios != NULL) {
2279
0
    netbios_encoded = ldb_binary_encode_string(frame, netbios);
2280
0
    if (netbios_encoded == NULL) {
2281
0
      TALLOC_FREE(frame);
2282
0
      return NT_STATUS_NO_MEMORY;
2283
0
    }
2284
0
  }
2285
2286
0
  if (dns != NULL) {
2287
0
    dns_encoded = ldb_binary_encode_string(frame, dns);
2288
0
    if (dns_encoded == NULL) {
2289
0
      TALLOC_FREE(frame);
2290
0
      return NT_STATUS_NO_MEMORY;
2291
0
    }
2292
0
  }
2293
2294
0
  if (netbios != NULL && dns != NULL) {
2295
0
    filter = talloc_asprintf(frame,
2296
0
        "(&(objectClass=trustedDomain)"
2297
0
          "(|(trustPartner=%s)(flatName=%s))"
2298
0
        ")",
2299
0
        dns_encoded, netbios_encoded);
2300
0
    if (filter == NULL) {
2301
0
      TALLOC_FREE(frame);
2302
0
      return NT_STATUS_NO_MEMORY;
2303
0
    }
2304
0
  } else if (netbios != NULL) {
2305
0
    filter = talloc_asprintf(frame,
2306
0
        "(&(objectClass=trustedDomain)(flatName=%s))",
2307
0
        netbios_encoded);
2308
0
    if (filter == NULL) {
2309
0
      TALLOC_FREE(frame);
2310
0
      return NT_STATUS_NO_MEMORY;
2311
0
    }
2312
0
  } else if (dns != NULL) {
2313
0
    filter = talloc_asprintf(frame,
2314
0
        "(&(objectClass=trustedDomain)(trustPartner=%s))",
2315
0
        dns_encoded);
2316
0
    if (filter == NULL) {
2317
0
      TALLOC_FREE(frame);
2318
0
      return NT_STATUS_NO_MEMORY;
2319
0
    }
2320
0
  }
2321
2322
0
  ret = dsdb_search_one(sam_ctx, mem_ctx, msg,
2323
0
            system_dn,
2324
0
            LDB_SCOPE_ONELEVEL, attrs,
2325
0
            DSDB_SEARCH_NO_GLOBAL_CATALOG,
2326
0
            "%s", filter);
2327
0
  if (ret != LDB_SUCCESS) {
2328
0
    NTSTATUS status = dsdb_ldb_err_to_ntstatus(ret);
2329
0
    DEBUG(3, ("Failed to search for %s: %s - %s\n",
2330
0
        filter, nt_errstr(status), ldb_errstring(sam_ctx)));
2331
0
    TALLOC_FREE(frame);
2332
0
    return status;
2333
0
  }
2334
2335
0
  TALLOC_FREE(frame);
2336
0
  return NT_STATUS_OK;
2337
0
}
2338
2339
NTSTATUS dsdb_trust_search_tdo_by_type(struct ldb_context *sam_ctx,
2340
               enum netr_SchannelType type,
2341
               const char *name,
2342
               const char * const *attrs,
2343
               TALLOC_CTX *mem_ctx,
2344
               struct ldb_message **msg)
2345
0
{
2346
0
  TALLOC_CTX *frame = talloc_stackframe();
2347
0
  NTSTATUS status;
2348
0
  size_t len;
2349
0
  char trailer = '$';
2350
0
  bool require_trailer = true;
2351
0
  char *encoded_name = NULL;
2352
0
  const char *netbios = NULL;
2353
0
  const char *dns = NULL;
2354
2355
0
  if (type != SEC_CHAN_DOMAIN && type != SEC_CHAN_DNS_DOMAIN) {
2356
0
    TALLOC_FREE(frame);
2357
0
    return NT_STATUS_INVALID_PARAMETER;
2358
0
  }
2359
2360
0
  if (type == SEC_CHAN_DNS_DOMAIN) {
2361
0
    trailer = '.';
2362
0
    require_trailer = false;
2363
0
  }
2364
2365
0
  encoded_name = ldb_binary_encode_string(frame, name);
2366
0
  if (encoded_name == NULL) {
2367
0
    TALLOC_FREE(frame);
2368
0
    return NT_STATUS_NO_MEMORY;
2369
0
  }
2370
2371
0
  len = strlen(encoded_name);
2372
0
  if (len < 2) {
2373
0
    TALLOC_FREE(frame);
2374
0
    return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2375
0
  }
2376
2377
0
  if (require_trailer && encoded_name[len - 1] != trailer) {
2378
0
    TALLOC_FREE(frame);
2379
0
    return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2380
0
  }
2381
0
  encoded_name[len - 1] = '\0';
2382
2383
0
  if (type == SEC_CHAN_DNS_DOMAIN) {
2384
0
    dns = encoded_name;
2385
0
  } else {
2386
0
    netbios = encoded_name;
2387
0
  }
2388
2389
0
  status = dsdb_trust_search_tdo(sam_ctx, netbios, dns,
2390
0
               attrs, mem_ctx, msg);
2391
0
  if (!NT_STATUS_IS_OK(status)) {
2392
0
    TALLOC_FREE(frame);
2393
0
    return status;
2394
0
  }
2395
2396
0
  TALLOC_FREE(frame);
2397
0
  return NT_STATUS_OK;
2398
0
}
2399
2400
NTSTATUS dsdb_trust_search_tdo_by_sid(struct ldb_context *sam_ctx,
2401
              const struct dom_sid *sid,
2402
              const char * const *attrs,
2403
              TALLOC_CTX *mem_ctx,
2404
              struct ldb_message **msg)
2405
0
{
2406
0
  TALLOC_CTX *frame = talloc_stackframe();
2407
0
  int ret;
2408
0
  struct ldb_dn *system_dn = NULL;
2409
0
  char *encoded_sid = NULL;
2410
0
  char *filter = NULL;
2411
2412
0
  *msg = NULL;
2413
2414
0
  if (sid == NULL) {
2415
0
    TALLOC_FREE(frame);
2416
0
    return NT_STATUS_INVALID_PARAMETER_MIX;
2417
0
  }
2418
2419
0
  encoded_sid = ldap_encode_ndr_dom_sid(frame, sid);
2420
0
  if (encoded_sid == NULL) {
2421
0
    TALLOC_FREE(frame);
2422
0
    return NT_STATUS_NO_MEMORY;
2423
0
  }
2424
2425
0
  system_dn = samdb_system_container_dn(sam_ctx, frame);
2426
0
  if (system_dn == NULL) {
2427
0
    TALLOC_FREE(frame);
2428
0
    return NT_STATUS_NO_MEMORY;
2429
0
  }
2430
2431
0
  filter = talloc_asprintf(frame,
2432
0
        "(&"
2433
0
          "(objectClass=trustedDomain)"
2434
0
          "(securityIdentifier=%s)"
2435
0
        ")",
2436
0
        encoded_sid);
2437
0
  if (filter == NULL) {
2438
0
    TALLOC_FREE(frame);
2439
0
    return NT_STATUS_NO_MEMORY;
2440
0
  }
2441
2442
0
  ret = dsdb_search_one(sam_ctx, mem_ctx, msg,
2443
0
            system_dn,
2444
0
            LDB_SCOPE_ONELEVEL, attrs,
2445
0
            DSDB_SEARCH_NO_GLOBAL_CATALOG,
2446
0
            "%s", filter);
2447
0
  if (ret != LDB_SUCCESS) {
2448
0
    NTSTATUS status = dsdb_ldb_err_to_ntstatus(ret);
2449
0
    DEBUG(3, ("Failed to search for %s: %s - %s\n",
2450
0
        filter, nt_errstr(status), ldb_errstring(sam_ctx)));
2451
0
    TALLOC_FREE(frame);
2452
0
    return status;
2453
0
  }
2454
2455
0
  TALLOC_FREE(frame);
2456
0
  return NT_STATUS_OK;
2457
0
}
2458
2459
NTSTATUS dsdb_trust_get_incoming_passwords(const struct ldb_message *msg,
2460
             TALLOC_CTX *mem_ctx,
2461
             struct samr_Password **_current,
2462
             struct samr_Password **_previous)
2463
0
{
2464
0
  TALLOC_CTX *frame = talloc_stackframe();
2465
0
  struct samr_Password __current = {
2466
0
    .hash = {0},
2467
0
  };
2468
0
  struct samr_Password __previous = {
2469
0
    .hash = {0},
2470
0
  };
2471
0
  struct samr_Password *current = NULL;
2472
0
  struct samr_Password *previous = NULL;
2473
0
  const struct ldb_val *blob = NULL;
2474
0
  enum ndr_err_code ndr_err;
2475
0
  struct trustAuthInOutBlob incoming = {
2476
0
    .count = 0,
2477
0
  };
2478
0
  uint32_t i;
2479
2480
0
  if (_current != NULL) {
2481
0
    *_current = NULL;
2482
0
  }
2483
0
  if (_previous != NULL) {
2484
0
    *_previous = NULL;
2485
0
  }
2486
2487
0
  blob = ldb_msg_find_ldb_val(msg, "trustAuthIncoming");
2488
0
  if (blob == NULL) {
2489
0
    TALLOC_FREE(frame);
2490
0
    return NT_STATUS_ACCOUNT_DISABLED;
2491
0
  }
2492
2493
  /* ldb_val is equivalent to DATA_BLOB */
2494
0
  ndr_err = ndr_pull_struct_blob_all(blob, frame, &incoming,
2495
0
        (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2496
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2497
0
    TALLOC_FREE(frame);
2498
0
    return NT_STATUS_INTERNAL_DB_CORRUPTION;
2499
0
  }
2500
2501
0
  for (i = 0; i < incoming.current.count; i++) {
2502
0
    struct AuthenticationInformation *a =
2503
0
      &incoming.current.array[i];
2504
2505
0
    if (current != NULL) {
2506
0
      break;
2507
0
    }
2508
2509
0
    switch (a->AuthType) {
2510
0
    case TRUST_AUTH_TYPE_NONE:
2511
0
    case TRUST_AUTH_TYPE_VERSION:
2512
0
      break;
2513
0
    case TRUST_AUTH_TYPE_NT4OWF:
2514
0
      current = &a->AuthInfo.nt4owf.password;
2515
0
      break;
2516
0
    case TRUST_AUTH_TYPE_CLEAR:
2517
0
      mdfour(__current.hash,
2518
0
             a->AuthInfo.clear.password,
2519
0
             a->AuthInfo.clear.size);
2520
0
      current = &__current;
2521
0
      break;
2522
0
    }
2523
0
  }
2524
2525
0
  if (current == NULL) {
2526
0
    TALLOC_FREE(frame);
2527
0
    return NT_STATUS_INTERNAL_DB_CORRUPTION;
2528
0
  }
2529
2530
0
  for (i = 0; i < incoming.previous.count; i++) {
2531
0
    struct AuthenticationInformation *a =
2532
0
      &incoming.previous.array[i];
2533
2534
0
    if (previous != NULL) {
2535
0
      break;
2536
0
    }
2537
2538
0
    switch (a->AuthType) {
2539
0
    case TRUST_AUTH_TYPE_NONE:
2540
0
    case TRUST_AUTH_TYPE_VERSION:
2541
0
      break;
2542
0
    case TRUST_AUTH_TYPE_NT4OWF:
2543
0
      previous = &a->AuthInfo.nt4owf.password;
2544
0
      break;
2545
0
    case TRUST_AUTH_TYPE_CLEAR:
2546
0
      mdfour(__previous.hash,
2547
0
             a->AuthInfo.clear.password,
2548
0
             a->AuthInfo.clear.size);
2549
0
      previous = &__previous;
2550
0
      break;
2551
0
    }
2552
0
  }
2553
2554
0
  if (previous == NULL) {
2555
0
    previous = current;
2556
0
  }
2557
2558
0
  if (_current != NULL) {
2559
0
    *_current = talloc_memdup(mem_ctx, current, sizeof(*current));
2560
0
    if (*_current == NULL) {
2561
0
      TALLOC_FREE(frame);
2562
0
      return NT_STATUS_NO_MEMORY;
2563
0
    }
2564
0
  }
2565
0
  if (_previous != NULL) {
2566
0
    *_previous =
2567
0
      talloc_memdup(mem_ctx, previous, sizeof(*previous));
2568
0
    if (*_previous == NULL) {
2569
0
      if (_current != NULL) {
2570
0
        TALLOC_FREE(*_current);
2571
0
      }
2572
0
      TALLOC_FREE(frame);
2573
0
      return NT_STATUS_NO_MEMORY;
2574
0
    }
2575
0
  }
2576
0
  ZERO_STRUCTP(current);
2577
0
  ZERO_STRUCTP(previous);
2578
0
  TALLOC_FREE(frame);
2579
0
  return NT_STATUS_OK;
2580
0
}
2581
2582
NTSTATUS dsdb_trust_search_tdos(struct ldb_context *sam_ctx,
2583
        const char *exclude,
2584
        const char * const *attrs,
2585
        TALLOC_CTX *mem_ctx,
2586
        struct ldb_result **res)
2587
0
{
2588
0
  TALLOC_CTX *frame = talloc_stackframe();
2589
0
  int ret;
2590
0
  struct ldb_dn *system_dn = NULL;
2591
0
  const char *filter = NULL;
2592
0
  char *exclude_encoded = NULL;
2593
2594
0
  *res = NULL;
2595
2596
0
  system_dn = samdb_system_container_dn(sam_ctx, frame);
2597
0
  if (system_dn == NULL) {
2598
0
    TALLOC_FREE(frame);
2599
0
    return NT_STATUS_NO_MEMORY;
2600
0
  }
2601
2602
0
  if (exclude != NULL) {
2603
0
    exclude_encoded = ldb_binary_encode_string(frame, exclude);
2604
0
    if (exclude_encoded == NULL) {
2605
0
      TALLOC_FREE(frame);
2606
0
      return NT_STATUS_NO_MEMORY;
2607
0
    }
2608
2609
0
    filter = talloc_asprintf(frame,
2610
0
        "(&(objectClass=trustedDomain)"
2611
0
          "(!(|(trustPartner=%s)(flatName=%s)))"
2612
0
        ")",
2613
0
        exclude_encoded, exclude_encoded);
2614
0
    if (filter == NULL) {
2615
0
      TALLOC_FREE(frame);
2616
0
      return NT_STATUS_NO_MEMORY;
2617
0
    }
2618
0
  } else {
2619
0
    filter = "(objectClass=trustedDomain)";
2620
0
  }
2621
2622
0
  ret = dsdb_search(sam_ctx, mem_ctx, res,
2623
0
        system_dn,
2624
0
        LDB_SCOPE_ONELEVEL, attrs,
2625
0
        DSDB_SEARCH_NO_GLOBAL_CATALOG,
2626
0
        "%s", filter);
2627
0
  if (ret != LDB_SUCCESS) {
2628
0
    NTSTATUS status = dsdb_ldb_err_to_ntstatus(ret);
2629
0
    DEBUG(3, ("Failed to search for %s: %s - %s\n",
2630
0
        filter, nt_errstr(status), ldb_errstring(sam_ctx)));
2631
0
    TALLOC_FREE(frame);
2632
0
    return status;
2633
0
  }
2634
2635
0
  TALLOC_FREE(frame);
2636
0
  return NT_STATUS_OK;
2637
0
}
2638
2639
struct dsdb_trust_routing_domain;
2640
2641
struct dsdb_trust_routing_table {
2642
  struct dsdb_trust_routing_domain *domains;
2643
};
2644
2645
struct dsdb_trust_routing_domain {
2646
  struct dsdb_trust_routing_domain *prev, *next;
2647
2648
  struct lsa_TrustDomainInfoInfoEx *tdo;
2649
2650
  struct lsa_ForestTrustDomainInfo di;
2651
2652
  struct lsa_ForestTrustInformation2 *fti;
2653
};
2654
2655
NTSTATUS dsdb_trust_routing_table_load(struct ldb_context *sam_ctx,
2656
               TALLOC_CTX *mem_ctx,
2657
               struct dsdb_trust_routing_table **_table)
2658
0
{
2659
0
  TALLOC_CTX *frame = talloc_stackframe();
2660
0
  struct dsdb_trust_routing_table *table;
2661
0
  struct dsdb_trust_routing_domain *d = NULL;
2662
0
  struct ldb_dn *domain_dn = NULL;
2663
0
  struct lsa_TrustDomainInfoInfoEx *root_trust_tdo = NULL;
2664
0
  struct lsa_TrustDomainInfoInfoEx *trust_parent_tdo = NULL;
2665
0
  struct lsa_TrustDomainInfoInfoEx *root_direction_tdo = NULL;
2666
0
  const char * const trusts_attrs[] = {
2667
0
    "securityIdentifier",
2668
0
    "flatName",
2669
0
    "trustPartner",
2670
0
    "trustAttributes",
2671
0
    "trustDirection",
2672
0
    "trustType",
2673
0
    "msDS-TrustForestTrustInfo",
2674
0
    NULL
2675
0
  };
2676
0
  struct ldb_result *trusts_res = NULL;
2677
0
  unsigned int i;
2678
0
  NTSTATUS status;
2679
2680
0
  *_table = NULL;
2681
2682
0
  domain_dn = ldb_get_default_basedn(sam_ctx);
2683
0
  if (domain_dn == NULL) {
2684
0
    TALLOC_FREE(frame);
2685
0
    return NT_STATUS_INTERNAL_ERROR;
2686
0
  }
2687
2688
0
  table = talloc_zero(mem_ctx, struct dsdb_trust_routing_table);
2689
0
  if (table == NULL) {
2690
0
    TALLOC_FREE(frame);
2691
0
    return NT_STATUS_NO_MEMORY;
2692
0
  }
2693
0
  talloc_steal(frame, table);
2694
2695
0
  d = talloc_zero(table, struct dsdb_trust_routing_domain);
2696
0
  if (d == NULL) {
2697
0
    TALLOC_FREE(frame);
2698
0
    return NT_STATUS_NO_MEMORY;
2699
0
  }
2700
2701
0
  status = dsdb_trust_crossref_tdo_info(d, sam_ctx,
2702
0
                domain_dn, NULL,
2703
0
                &d->tdo,
2704
0
                &root_trust_tdo,
2705
0
                &trust_parent_tdo);
2706
0
  if (!NT_STATUS_IS_OK(status)) {
2707
0
    TALLOC_FREE(frame);
2708
0
    return status;
2709
0
  }
2710
2711
  /*
2712
   * d->tdo should not be NULL of status above is 'NT_STATUS_OK'
2713
   * check is needed to satisfy clang static checker
2714
  */
2715
0
  if (d->tdo == NULL) {
2716
0
    TALLOC_FREE(frame);
2717
0
    return NT_STATUS_NO_MEMORY;
2718
0
  }
2719
0
  d->di.domain_sid = d->tdo->sid;
2720
0
  d->di.netbios_domain_name.string = d->tdo->netbios_name.string;
2721
0
  d->di.dns_domain_name.string = d->tdo->domain_name.string;
2722
2723
0
  if (root_trust_tdo != NULL) {
2724
0
    root_direction_tdo = root_trust_tdo;
2725
0
  } else if (trust_parent_tdo != NULL) {
2726
0
    root_direction_tdo = trust_parent_tdo;
2727
0
  }
2728
2729
0
  if (root_direction_tdo == NULL) {
2730
    /* we're the forest root */
2731
0
    status = dsdb_trust_xref_forest_info(d, sam_ctx, &d->fti);
2732
0
    if (!NT_STATUS_IS_OK(status)) {
2733
0
      TALLOC_FREE(frame);
2734
0
      return status;
2735
0
    }
2736
0
  }
2737
2738
0
  DLIST_ADD(table->domains, d);
2739
2740
0
  status = dsdb_trust_search_tdos(sam_ctx, NULL, trusts_attrs,
2741
0
          frame, &trusts_res);
2742
0
  if (!NT_STATUS_IS_OK(status)) {
2743
0
    TALLOC_FREE(frame);
2744
0
    return status;
2745
0
  }
2746
2747
0
  for (i = 0; i < trusts_res->count; i++) {
2748
0
    bool ok;
2749
0
    int cmp;
2750
2751
0
    d = talloc_zero(table, struct dsdb_trust_routing_domain);
2752
0
    if (d == NULL) {
2753
0
      TALLOC_FREE(frame);
2754
0
      return NT_STATUS_NO_MEMORY;
2755
0
    }
2756
2757
0
    status = dsdb_trust_parse_tdo_info(d,
2758
0
               trusts_res->msgs[i],
2759
0
               &d->tdo);
2760
0
    if (!NT_STATUS_IS_OK(status)) {
2761
0
      TALLOC_FREE(frame);
2762
0
      return status;
2763
0
    }
2764
2765
0
    d->di.domain_sid = d->tdo->sid;
2766
0
    d->di.netbios_domain_name.string = d->tdo->netbios_name.string;
2767
0
    d->di.dns_domain_name.string = d->tdo->domain_name.string;
2768
2769
0
    DLIST_ADD_END(table->domains, d);
2770
2771
0
    if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
2772
0
      struct ForestTrustInfo *fti = NULL;
2773
2774
0
      status = dsdb_trust_parse_forest_info(frame,
2775
0
                    trusts_res->msgs[i],
2776
0
                    &fti);
2777
0
      if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
2778
0
        fti = NULL;
2779
0
        status = NT_STATUS_OK;
2780
0
      }
2781
0
      if (!NT_STATUS_IS_OK(status)) {
2782
0
        TALLOC_FREE(frame);
2783
0
        return status;
2784
0
      }
2785
2786
0
      if (fti == NULL) {
2787
0
        continue;
2788
0
      }
2789
2790
0
      status = trust_forest_info_to_lsa2(d, fti, &d->fti);
2791
0
      if (!NT_STATUS_IS_OK(status)) {
2792
0
        TALLOC_FREE(frame);
2793
0
        return status;
2794
0
      }
2795
2796
0
      continue;
2797
0
    }
2798
2799
0
    if (!(d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST)) {
2800
0
      continue;
2801
0
    }
2802
2803
0
    if (root_direction_tdo == NULL) {
2804
0
      continue;
2805
0
    }
2806
2807
0
    ok = dom_sid_equal(root_direction_tdo->sid, d->tdo->sid);
2808
0
    if (!ok) {
2809
0
      continue;
2810
0
    }
2811
2812
0
    cmp = strcasecmp_m(root_direction_tdo->netbios_name.string,
2813
0
           d->tdo->netbios_name.string);
2814
0
    if (cmp != 0) {
2815
0
      continue;
2816
0
    }
2817
2818
0
    cmp = strcasecmp_m(root_direction_tdo->domain_name.string,
2819
0
           d->tdo->domain_name.string);
2820
0
    if (cmp != 0) {
2821
0
      continue;
2822
0
    }
2823
2824
    /* this our route to the forest root */
2825
0
    status = dsdb_trust_xref_forest_info(d, sam_ctx, &d->fti);
2826
0
    if (!NT_STATUS_IS_OK(status)) {
2827
0
      TALLOC_FREE(frame);
2828
0
      return status;
2829
0
    }
2830
0
  }
2831
2832
0
  *_table = talloc_move(mem_ctx, &table);
2833
0
  TALLOC_FREE(frame);
2834
0
  return NT_STATUS_OK;
2835
0
}
2836
2837
static void dsdb_trust_update_best_tln(
2838
  const struct dsdb_trust_routing_domain **best_d,
2839
  const char **best_tln,
2840
  const struct dsdb_trust_routing_domain *d,
2841
  const char *tln)
2842
0
{
2843
0
  int cmp;
2844
2845
0
  if (*best_tln == NULL) {
2846
0
    *best_tln = tln;
2847
0
    *best_d = d;
2848
0
    return;
2849
0
  }
2850
2851
0
  cmp = dns_cmp(tln, *best_tln);
2852
0
  if (cmp != DNS_CMP_FIRST_IS_CHILD) {
2853
0
    return;
2854
0
  }
2855
2856
0
  *best_tln = tln;
2857
0
  *best_d = d;
2858
0
}
2859
2860
const struct lsa_TrustDomainInfoInfoEx *dsdb_trust_routing_by_name(
2861
    const struct dsdb_trust_routing_table *table,
2862
    const char *name)
2863
0
{
2864
0
  const struct dsdb_trust_routing_domain *best_d = NULL;
2865
0
  const char *best_tln = NULL;
2866
0
  const struct dsdb_trust_routing_domain *d = NULL;
2867
2868
0
  if (name == NULL) {
2869
0
    return NULL;
2870
0
  }
2871
2872
0
  for (d = table->domains; d != NULL; d = d->next) {
2873
0
    bool transitive = false;
2874
0
    bool allow_netbios = false;
2875
0
    bool exclude = false;
2876
0
    uint32_t i;
2877
2878
0
    if (d->tdo->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
2879
      /*
2880
       * Only uplevel trusts have top level names
2881
       */
2882
0
      continue;
2883
0
    }
2884
2885
0
    if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
2886
0
      transitive = true;
2887
0
    }
2888
2889
0
    if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
2890
0
      transitive = true;
2891
0
    }
2892
2893
0
    if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE) {
2894
0
      transitive = false;
2895
0
    }
2896
2897
0
    if (d->tdo->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
2898
0
      transitive = false;
2899
0
    }
2900
2901
0
    switch (d->tdo->trust_type) {
2902
0
    case LSA_TRUST_TYPE_UPLEVEL:
2903
0
      if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_UPLEVEL_ONLY) {
2904
0
        break;
2905
0
      }
2906
0
      allow_netbios = true;
2907
0
      break;
2908
0
    case LSA_TRUST_TYPE_DOWNLEVEL:
2909
0
      allow_netbios = true;
2910
0
      break;
2911
0
    default:
2912
0
      allow_netbios = false;
2913
0
      break;
2914
0
    }
2915
2916
0
    if (!transitive || d->fti == NULL) {
2917
0
      int cmp;
2918
2919
0
      if (allow_netbios) {
2920
0
        cmp = dns_cmp(name, d->tdo->netbios_name.string);
2921
0
        if (cmp == DNS_CMP_MATCH) {
2922
          /*
2923
           * exact match
2924
           */
2925
0
          return d->tdo;
2926
0
        }
2927
0
      }
2928
2929
0
      cmp = dns_cmp(name, d->tdo->domain_name.string);
2930
0
      if (cmp == DNS_CMP_MATCH) {
2931
        /*
2932
         * exact match
2933
         */
2934
0
        return d->tdo;
2935
0
      }
2936
0
      if (cmp != DNS_CMP_FIRST_IS_CHILD) {
2937
0
        continue;
2938
0
      }
2939
2940
0
      dsdb_trust_update_best_tln(&best_d, &best_tln, d,
2941
0
               d->tdo->domain_name.string);
2942
0
      continue;
2943
0
    }
2944
2945
0
    exclude = trust_forest_info_tln_ex_match(d->fti, name);
2946
0
    if (exclude) {
2947
0
      continue;
2948
0
    }
2949
2950
0
    for (i = 0; i < d->fti->count; i++ ) {
2951
0
      const struct lsa_ForestTrustRecord2 *f = d->fti->entries[i];
2952
0
      const struct lsa_ForestTrustDomainInfo *di = NULL;
2953
0
      const char *fti_nbt = NULL;
2954
0
      int cmp;
2955
2956
0
      if (!allow_netbios) {
2957
0
        break;
2958
0
      }
2959
2960
0
      if (f == NULL) {
2961
        /* broken record */
2962
0
        continue;
2963
0
      }
2964
2965
0
      if (f->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
2966
0
        continue;
2967
0
      }
2968
2969
0
      if (f->flags & LSA_NB_DISABLED_MASK) {
2970
        /*
2971
         * any flag disables the entry.
2972
         */
2973
0
        continue;
2974
0
      }
2975
2976
0
      di = &f->forest_trust_data.domain_info;
2977
0
      fti_nbt = di->netbios_domain_name.string;
2978
0
      if (fti_nbt == NULL) {
2979
        /* broken record */
2980
0
        continue;
2981
0
      }
2982
2983
0
      cmp = dns_cmp(name, fti_nbt);
2984
0
      if (cmp == DNS_CMP_MATCH) {
2985
        /*
2986
         * exact match
2987
         */
2988
0
        return d->tdo;
2989
0
      }
2990
0
    }
2991
2992
0
    for (i = 0; i < d->fti->count; i++ ) {
2993
0
      const struct lsa_ForestTrustRecord2 *f = d->fti->entries[i];
2994
0
      const union lsa_ForestTrustData2 *u = NULL;
2995
0
      const char *fti_tln = NULL;
2996
0
      int cmp;
2997
2998
0
      if (f == NULL) {
2999
        /* broken record */
3000
0
        continue;
3001
0
      }
3002
3003
0
      if (f->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
3004
0
        continue;
3005
0
      }
3006
3007
0
      if (f->flags & LSA_TLN_DISABLED_MASK) {
3008
        /*
3009
         * any flag disables the entry.
3010
         */
3011
0
        continue;
3012
0
      }
3013
3014
0
      u = &f->forest_trust_data;
3015
0
      fti_tln = u->top_level_name.string;
3016
0
      if (fti_tln == NULL) {
3017
0
        continue;
3018
0
      }
3019
3020
0
      cmp = dns_cmp(name, fti_tln);
3021
0
      if (cmp == DNS_CMP_MATCH) {
3022
        /*
3023
         * exact match
3024
         */
3025
0
        return d->tdo;
3026
0
      }
3027
0
      if (cmp != DNS_CMP_FIRST_IS_CHILD) {
3028
0
        continue;
3029
0
      }
3030
3031
0
      dsdb_trust_update_best_tln(&best_d, &best_tln,
3032
0
               d, fti_tln);
3033
0
      continue;
3034
0
    }
3035
0
  }
3036
3037
0
  if (best_d != NULL) {
3038
0
    return best_d->tdo;
3039
0
  }
3040
3041
0
  return NULL;
3042
0
}
3043
3044
const struct lsa_TrustDomainInfoInfoEx *dsdb_trust_domain_by_sid(
3045
    const struct dsdb_trust_routing_table *table,
3046
    const struct dom_sid *sid,
3047
    const struct lsa_ForestTrustDomainInfo **pdi)
3048
0
{
3049
0
  const struct dsdb_trust_routing_domain *d = NULL;
3050
3051
0
  if (pdi != NULL) {
3052
0
    *pdi = NULL;
3053
0
  }
3054
3055
0
  if (sid == NULL) {
3056
0
    return NULL;
3057
0
  }
3058
3059
0
  for (d = table->domains; d != NULL; d = d->next) {
3060
0
    bool transitive = false;
3061
0
    uint32_t i;
3062
3063
0
    if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
3064
0
      transitive = true;
3065
0
    }
3066
3067
0
    if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
3068
0
      transitive = true;
3069
0
    }
3070
3071
0
    if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE) {
3072
0
      transitive = false;
3073
0
    }
3074
3075
0
    if (d->tdo->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
3076
0
      transitive = false;
3077
0
    }
3078
3079
0
    if (!transitive || d->fti == NULL) {
3080
0
      bool match = false;
3081
3082
0
      match = dom_sid_equal(d->di.domain_sid, sid);
3083
0
      if (match) {
3084
        /*
3085
         * exact match, it's the domain itself.
3086
         */
3087
0
        if (pdi != NULL) {
3088
0
          *pdi = &d->di;
3089
0
        }
3090
0
        return d->tdo;
3091
0
      }
3092
0
      continue;
3093
0
    }
3094
3095
0
    for (i = 0; i < d->fti->count; i++ ) {
3096
0
      const struct lsa_ForestTrustRecord2 *f = d->fti->entries[i];
3097
0
      const struct lsa_ForestTrustDomainInfo *di = NULL;
3098
0
      const struct dom_sid *fti_sid = NULL;
3099
0
      bool match = false;
3100
3101
0
      if (f == NULL) {
3102
        /* broken record */
3103
0
        continue;
3104
0
      }
3105
3106
0
      if (f->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
3107
0
        continue;
3108
0
      }
3109
3110
0
      if (f->flags & LSA_SID_DISABLED_MASK) {
3111
        /*
3112
         * any flag disables the entry.
3113
         */
3114
0
        continue;
3115
0
      }
3116
3117
0
      di = &f->forest_trust_data.domain_info;
3118
0
      fti_sid = di->domain_sid;
3119
0
      if (fti_sid == NULL) {
3120
        /* broken record */
3121
0
        continue;
3122
0
      }
3123
3124
0
      match = dom_sid_equal(fti_sid, sid);
3125
0
      if (match) {
3126
        /*
3127
         * exact match, it's a domain in the forest.
3128
         */
3129
0
        if (pdi != NULL) {
3130
0
          *pdi = di;
3131
0
        }
3132
0
        return d->tdo;
3133
0
      }
3134
0
    }
3135
0
  }
3136
3137
0
  return NULL;
3138
0
}
3139
3140
const struct lsa_TrustDomainInfoInfoEx *dsdb_trust_domain_by_name(
3141
    const struct dsdb_trust_routing_table *table,
3142
    const char *name,
3143
    const struct lsa_ForestTrustDomainInfo **pdi)
3144
0
{
3145
0
  const struct dsdb_trust_routing_domain *d = NULL;
3146
3147
0
  if (pdi != NULL) {
3148
0
    *pdi = NULL;
3149
0
  }
3150
3151
0
  if (name == NULL) {
3152
0
    return NULL;
3153
0
  }
3154
3155
0
  for (d = table->domains; d != NULL; d = d->next) {
3156
0
    bool transitive = false;
3157
0
    uint32_t i;
3158
3159
0
    if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
3160
0
      transitive = true;
3161
0
    }
3162
3163
0
    if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
3164
0
      transitive = true;
3165
0
    }
3166
3167
0
    if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE) {
3168
0
      transitive = false;
3169
0
    }
3170
3171
0
    if (d->tdo->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
3172
0
      transitive = false;
3173
0
    }
3174
3175
0
    if (!transitive || d->fti == NULL) {
3176
0
      bool match = false;
3177
3178
0
      match = strequal_m(d->di.netbios_domain_name.string,
3179
0
             name);
3180
0
      if (match) {
3181
        /*
3182
         * exact match for netbios name,
3183
         * it's the domain itself.
3184
         */
3185
0
        if (pdi != NULL) {
3186
0
          *pdi = &d->di;
3187
0
        }
3188
0
        return d->tdo;
3189
0
      }
3190
0
      match = strequal_m(d->di.dns_domain_name.string,
3191
0
             name);
3192
0
      if (match) {
3193
        /*
3194
         * exact match for dns name,
3195
         * it's the domain itself.
3196
         */
3197
0
        if (pdi != NULL) {
3198
0
          *pdi = &d->di;
3199
0
        }
3200
0
        return d->tdo;
3201
0
      }
3202
0
      continue;
3203
0
    }
3204
3205
0
    for (i = 0; i < d->fti->count; i++ ) {
3206
0
      const struct lsa_ForestTrustRecord2 *f = d->fti->entries[i];
3207
0
      const struct lsa_ForestTrustDomainInfo *di = NULL;
3208
0
      bool match = false;
3209
3210
0
      if (f == NULL) {
3211
        /* broken record */
3212
0
        continue;
3213
0
      }
3214
3215
0
      if (f->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
3216
0
        continue;
3217
0
      }
3218
0
      di = &f->forest_trust_data.domain_info;
3219
3220
0
      if (!(f->flags & LSA_NB_DISABLED_MASK)) {
3221
0
        match = strequal_m(di->netbios_domain_name.string,
3222
0
               name);
3223
0
        if (match) {
3224
          /*
3225
           * exact match for netbios name,
3226
           * it's a domain in the forest.
3227
           */
3228
0
          if (pdi != NULL) {
3229
0
            *pdi = di;
3230
0
          }
3231
0
          return d->tdo;
3232
0
        }
3233
0
      }
3234
3235
0
      if (!(f->flags & LSA_TLN_DISABLED_MASK)) {
3236
0
        match = strequal_m(di->dns_domain_name.string,
3237
0
               name);
3238
0
        if (match) {
3239
          /*
3240
           * exact match for dns name,
3241
           * it's a domain in the forest.
3242
           */
3243
0
          if (pdi != NULL) {
3244
0
            *pdi = di;
3245
0
          }
3246
0
          return d->tdo;
3247
0
        }
3248
0
      }
3249
0
    }
3250
0
  }
3251
3252
0
  return NULL;
3253
0
}
3254
3255
NTSTATUS dsdb_trust_get_claims_tf_policy(struct ldb_context *samldb,
3256
           const struct ldb_message *tdo_msg,
3257
           const char *tdo_attr,
3258
           TALLOC_CTX *mem_ctx,
3259
           struct claims_tf_rule_set **_rule_set)
3260
0
{
3261
0
  TALLOC_CTX *frame = talloc_stackframe();
3262
0
  const struct ldb_val *tdo_link_val = NULL;
3263
0
  struct ldb_dn *config_dn = NULL;
3264
0
  struct ldb_dn *claims_tf_dn = NULL;
3265
0
  struct ldb_dn *policy_dn = NULL;
3266
0
  struct ldb_message *policy_msg = NULL;
3267
0
  static const char * const policy_attrs[] = {
3268
0
    "msDS-TransformationRules",
3269
0
    NULL
3270
0
  };
3271
0
  const struct ldb_val *xml_blob = NULL;
3272
0
  DATA_BLOB rules_blob = { .length = 0, };
3273
0
  struct claims_tf_rule_set *rule_set = NULL;
3274
0
  int cmp;
3275
0
  bool ok;
3276
0
  int ret;
3277
3278
0
  *_rule_set = NULL;
3279
3280
0
  tdo_link_val = ldb_msg_find_ldb_val(tdo_msg, tdo_attr);
3281
0
  if (tdo_link_val == NULL) {
3282
0
    TALLOC_FREE(frame);
3283
0
    return NT_STATUS_DS_NO_ATTRIBUTE_OR_VALUE;
3284
0
  }
3285
3286
0
  config_dn = ldb_get_config_basedn(samldb);
3287
0
  if (config_dn == NULL) {
3288
0
    TALLOC_FREE(frame);
3289
0
    return NT_STATUS_DS_INIT_FAILURE;
3290
0
  }
3291
3292
0
  claims_tf_dn = ldb_dn_copy(frame, config_dn);
3293
0
  if (claims_tf_dn == NULL) {
3294
0
    TALLOC_FREE(frame);
3295
0
    return NT_STATUS_NO_MEMORY;
3296
0
  }
3297
3298
0
  ok = ldb_dn_add_child_fmt(claims_tf_dn,
3299
0
          "%s,%s,%s",
3300
0
          "CN=Claims Transformation Policies",
3301
0
          "CN=Claims Configuration",
3302
0
          "CN=Services");
3303
0
  if (!ok) {
3304
0
    TALLOC_FREE(frame);
3305
0
    return NT_STATUS_NO_MEMORY;
3306
0
  }
3307
3308
0
  policy_dn = ldb_msg_find_attr_as_dn(samldb, frame, tdo_msg, tdo_attr);
3309
0
  if (policy_dn == NULL) {
3310
0
    TALLOC_FREE(frame);
3311
0
    return NT_STATUS_NO_MEMORY;
3312
0
  }
3313
3314
  /*
3315
   * The policy dn needs to be a child of
3316
   * the CN=Claims Transformation Policies container
3317
   */
3318
0
  cmp = ldb_dn_compare_base(claims_tf_dn, policy_dn);
3319
0
  if (cmp != 0) {
3320
0
    TALLOC_FREE(frame);
3321
0
    return NT_STATUS_DS_OBJ_CLASS_VIOLATION;
3322
0
  }
3323
3324
0
  ret = dsdb_search_one(samldb,
3325
0
            frame,
3326
0
            &policy_msg,
3327
0
            policy_dn,
3328
0
            LDB_SCOPE_BASE,
3329
0
            policy_attrs,
3330
0
            DSDB_SEARCH_ONE_ONLY,
3331
0
            "(objectClass=msDS-ClaimsTransformationPolicyType)");
3332
0
  if (ret != LDB_SUCCESS) {
3333
0
    TALLOC_FREE(frame);
3334
0
    return NT_STATUS_POLICY_OBJECT_NOT_FOUND;
3335
0
  }
3336
3337
0
  xml_blob = ldb_msg_find_ldb_val(policy_msg, "msDS-TransformationRules");
3338
0
  if (xml_blob == NULL) {
3339
0
    TALLOC_FREE(frame);
3340
0
    return NT_STATUS_DS_NO_ATTRIBUTE_OR_VALUE;
3341
0
  }
3342
3343
0
  ok = claims_tf_policy_unwrap_xml(xml_blob,
3344
0
           &rules_blob);
3345
0
  if (!ok) {
3346
0
    TALLOC_FREE(frame);
3347
0
    return NT_STATUS_DS_INVALID_ATTRIBUTE_SYNTAX;
3348
0
  }
3349
3350
0
  ok = claims_tf_rule_set_parse_blob(&rules_blob,
3351
0
             frame,
3352
0
             &rule_set,
3353
0
             NULL); /* _error_string */
3354
0
  if (!ok) {
3355
0
    TALLOC_FREE(frame);
3356
0
    return NT_STATUS_DS_INVALID_ATTRIBUTE_SYNTAX;
3357
0
  }
3358
3359
0
  *_rule_set = talloc_move(mem_ctx, &rule_set);
3360
0
  TALLOC_FREE(frame);
3361
0
  return NT_STATUS_OK;
3362
0
}