Coverage Report

Created: 2026-04-01 06:26

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
    p = strstr_m(ntln->string, "..");
1004
0
    if (p != NULL) {
1005
0
      TALLOC_FREE(frame);
1006
0
      return NT_STATUS_INVALID_PARAMETER;
1007
0
    }
1008
1009
0
    if (nnb != NULL &&
1010
0
       (nnb->string == NULL ||
1011
0
        strlen(nnb->string) > 15))
1012
0
    {
1013
0
      TALLOC_FREE(frame);
1014
0
      return NT_STATUS_INVALID_PARAMETER;
1015
0
    }
1016
1017
0
    for (c = 0; c < n; c++) {
1018
0
      const struct lsa_ForestTrustRecord2 *cftr = nfti->entries[c];
1019
0
      const struct lsa_ForestTrustDomainInfo *cinfo = NULL;
1020
0
      const struct lsa_StringLarge *ctln = NULL;
1021
0
      const struct lsa_StringLarge *cnb = NULL;
1022
0
      const struct dom_sid *csid = NULL;
1023
0
      int cmp;
1024
1025
0
      if (cftr == NULL) {
1026
0
        continue;
1027
0
      }
1028
1029
0
      if (cftr->type != nftr->type) {
1030
0
        continue;
1031
0
      }
1032
1033
0
      switch (cftr->type) {
1034
0
      case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
1035
0
        ctln = &cftr->forest_trust_data.top_level_name;
1036
0
        break;
1037
1038
0
      case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
1039
0
        ctln = &cftr->forest_trust_data.top_level_name_ex;
1040
0
        break;
1041
1042
0
      case LSA_FOREST_TRUST_DOMAIN_INFO:
1043
0
        cinfo = &cftr->forest_trust_data.domain_info;
1044
0
        ctln = &cinfo->dns_domain_name;
1045
0
        cnb = &cinfo->netbios_domain_name;
1046
0
        csid = cinfo->domain_sid;
1047
0
        break;
1048
1049
0
      case LSA_FOREST_TRUST_SCANNER_INFO:
1050
0
        cinfo = &cftr->forest_trust_data.scanner_info;
1051
0
        ctln = &cinfo->dns_domain_name;
1052
0
        cnb = &cinfo->netbios_domain_name;
1053
0
        csid = cinfo->domain_sid;
1054
0
        break;
1055
1056
0
      default:
1057
0
        TALLOC_FREE(frame);
1058
0
        return NT_STATUS_INVALID_PARAMETER;
1059
0
      }
1060
1061
0
      cmp = dns_cmp(ntln->string, ctln->string);
1062
0
      if (cmp == DNS_CMP_MATCH) {
1063
0
        nftr = NULL;
1064
0
        TALLOC_FREE(nfti->entries[n]);
1065
0
        break;
1066
0
      }
1067
1068
0
      if (cinfo == NULL) {
1069
0
        continue;
1070
0
      }
1071
1072
0
      cmp = strcasecmp_m(nnb->string, cnb->string);
1073
0
      if (cmp == 0) {
1074
0
        nftr = NULL;
1075
0
        TALLOC_FREE(nfti->entries[n]);
1076
0
        break;
1077
0
      }
1078
1079
0
      if (cftr->type == LSA_FOREST_TRUST_SCANNER_INFO) {
1080
        /*
1081
         * ignore the sid
1082
         */
1083
0
        continue;
1084
0
      }
1085
1086
0
      cmp = dom_sid_compare(nsid, csid);
1087
0
      if (cmp == 0) {
1088
0
        nftr = NULL;
1089
0
        TALLOC_FREE(nfti->entries[n]);
1090
0
        break;
1091
0
      }
1092
0
    }
1093
0
  }
1094
1095
  /*
1096
   * Now we check that only true top level names are provided
1097
   */
1098
0
  for (n = 0; n < nfti->count; n++) {
1099
0
    const struct lsa_ForestTrustRecord2 *nftr = nfti->entries[n];
1100
0
    const struct lsa_StringLarge *ntln = NULL;
1101
0
    uint32_t c;
1102
1103
0
    if (nftr == NULL) {
1104
0
      continue;
1105
0
    }
1106
1107
0
    if (nftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
1108
0
      continue;
1109
0
    }
1110
1111
0
    ntln = &nftr->forest_trust_data.top_level_name;
1112
1113
0
    for (c = 0; c < nfti->count; c++) {
1114
0
      const struct lsa_ForestTrustRecord2 *cftr = nfti->entries[c];
1115
0
      const struct lsa_StringLarge *ctln = NULL;
1116
0
      int cmp;
1117
1118
0
      if (cftr == NULL) {
1119
0
        continue;
1120
0
      }
1121
1122
0
      if (cftr == nftr) {
1123
0
        continue;
1124
0
      }
1125
1126
0
      if (cftr->type != nftr->type) {
1127
0
        continue;
1128
0
      }
1129
1130
0
      ctln = &cftr->forest_trust_data.top_level_name;
1131
1132
0
      cmp = dns_cmp(ntln->string, ctln->string);
1133
0
      if (DNS_CMP_IS_NO_MATCH(cmp)) {
1134
0
        continue;
1135
0
      }
1136
1137
0
      TALLOC_FREE(frame);
1138
0
      return NT_STATUS_INVALID_PARAMETER;
1139
0
    }
1140
0
  }
1141
1142
  /*
1143
   * Now we check that only true sub level excludes are provided
1144
   */
1145
0
  for (n = 0; n < nfti->count; n++) {
1146
0
    const struct lsa_ForestTrustRecord2 *nftr = nfti->entries[n];
1147
0
    const struct lsa_StringLarge *ntln = NULL;
1148
0
    uint32_t c;
1149
0
    bool found_tln = false;
1150
1151
0
    if (nftr == NULL) {
1152
0
      continue;
1153
0
    }
1154
1155
0
    if (nftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX) {
1156
0
      continue;
1157
0
    }
1158
1159
0
    ntln = &nftr->forest_trust_data.top_level_name;
1160
1161
0
    for (c = 0; c < nfti->count; c++) {
1162
0
      const struct lsa_ForestTrustRecord2 *cftr = nfti->entries[c];
1163
0
      const struct lsa_StringLarge *ctln = NULL;
1164
0
      int cmp;
1165
1166
0
      if (cftr == NULL) {
1167
0
        continue;
1168
0
      }
1169
1170
0
      if (cftr == nftr) {
1171
0
        continue;
1172
0
      }
1173
1174
0
      if (cftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
1175
0
        continue;
1176
0
      }
1177
1178
0
      ctln = &cftr->forest_trust_data.top_level_name;
1179
1180
0
      cmp = dns_cmp(ntln->string, ctln->string);
1181
0
      if (cmp == DNS_CMP_FIRST_IS_CHILD) {
1182
0
        found_tln = true;
1183
0
        break;
1184
0
      }
1185
0
    }
1186
1187
0
    if (found_tln) {
1188
0
      continue;
1189
0
    }
1190
1191
0
    TALLOC_FREE(frame);
1192
0
    return NT_STATUS_INVALID_PARAMETER;
1193
0
  }
1194
1195
  /*
1196
   * Now we check that there's a top level name for each domain
1197
   */
1198
0
  for (n = 0; n < nfti->count; n++) {
1199
0
    const struct lsa_ForestTrustRecord2 *nftr = nfti->entries[n];
1200
0
    const struct lsa_ForestTrustDomainInfo *ninfo = NULL;
1201
0
    const struct lsa_StringLarge *ntln = NULL;
1202
0
    uint32_t c;
1203
0
    bool found_tln = false;
1204
1205
0
    if (nftr == NULL) {
1206
0
      continue;
1207
0
    }
1208
1209
0
    if (nftr->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
1210
0
      continue;
1211
0
    }
1212
1213
0
    ninfo = &nftr->forest_trust_data.domain_info;
1214
0
    ntln = &ninfo->dns_domain_name;
1215
1216
0
    for (c = 0; c < nfti->count; c++) {
1217
0
      const struct lsa_ForestTrustRecord2 *cftr = nfti->entries[c];
1218
0
      const struct lsa_StringLarge *ctln = NULL;
1219
0
      int cmp;
1220
1221
0
      if (cftr == NULL) {
1222
0
        continue;
1223
0
      }
1224
1225
0
      if (cftr == nftr) {
1226
0
        continue;
1227
0
      }
1228
1229
0
      if (cftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
1230
0
        continue;
1231
0
      }
1232
1233
0
      ctln = &cftr->forest_trust_data.top_level_name;
1234
1235
0
      cmp = dns_cmp(ntln->string, ctln->string);
1236
0
      if (cmp == DNS_CMP_MATCH) {
1237
0
        found_tln = true;
1238
0
        break;
1239
0
      }
1240
0
      if (cmp == DNS_CMP_FIRST_IS_CHILD) {
1241
0
        found_tln = true;
1242
0
        break;
1243
0
      }
1244
0
    }
1245
1246
0
    if (found_tln) {
1247
0
      continue;
1248
0
    }
1249
1250
0
    TALLOC_FREE(frame);
1251
0
    return NT_STATUS_INVALID_PARAMETER;
1252
0
  }
1253
1254
0
  *_nfti = talloc_move(mem_ctx, &nfti);
1255
0
  TALLOC_FREE(frame);
1256
0
  return NT_STATUS_OK;
1257
0
}
1258
1259
NTSTATUS dsdb_trust_normalize_forest_info_step2(TALLOC_CTX *mem_ctx,
1260
        const struct lsa_ForestTrustInformation2 *gfti,
1261
        struct lsa_ForestTrustInformation2 **_nfti)
1262
0
{
1263
0
  TALLOC_CTX *frame = talloc_stackframe();
1264
0
  struct timeval tv = timeval_current();
1265
0
  NTTIME now = timeval_to_nttime(&tv);
1266
0
  struct lsa_ForestTrustInformation2 *nfti;
1267
0
  uint32_t g;
1268
1269
0
  *_nfti = NULL;
1270
1271
0
  nfti = talloc_zero(mem_ctx, struct lsa_ForestTrustInformation2);
1272
0
  if (nfti == NULL) {
1273
0
    TALLOC_FREE(frame);
1274
0
    return NT_STATUS_NO_MEMORY;
1275
0
  }
1276
0
  talloc_steal(frame, nfti);
1277
1278
  /*
1279
   * Now we add TOP_LEVEL_NAME[_EX] in reverse order
1280
   * followed by LSA_FOREST_TRUST_DOMAIN_INFO in reverse order.
1281
   *
1282
   * LSA_FOREST_TRUST_SCANNER_INFO and LSA_FOREST_TRUST_BINARY_DATA
1283
   * are added last.
1284
   *
1285
   * This also removes the possible NULL entries generated in step1.
1286
   */
1287
1288
0
  for (g = 0; g < gfti->count; g++) {
1289
0
    const struct lsa_ForestTrustRecord2 *gftr = gfti->entries[gfti->count - (g+1)];
1290
0
    struct lsa_ForestTrustRecord2 tftr;
1291
0
    bool skip = false;
1292
0
    NTSTATUS status;
1293
1294
0
    if (gftr == NULL) {
1295
0
      continue;
1296
0
    }
1297
1298
0
    switch (gftr->type) {
1299
0
    case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
1300
0
    case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
1301
0
      break;
1302
1303
0
    case LSA_FOREST_TRUST_DOMAIN_INFO:
1304
0
    case LSA_FOREST_TRUST_BINARY_DATA:
1305
0
    case LSA_FOREST_TRUST_SCANNER_INFO:
1306
0
      skip = true;
1307
0
      break;
1308
1309
0
    default:
1310
0
      TALLOC_FREE(frame);
1311
0
      return NT_STATUS_INVALID_PARAMETER;
1312
0
    }
1313
1314
0
    if (skip) {
1315
0
      continue;
1316
0
    }
1317
1318
    /* make a copy in order to update the time. */
1319
0
    tftr = *gftr;
1320
0
    if (tftr.time == 0) {
1321
0
      tftr.time = now;
1322
0
    }
1323
1324
0
    status = dsdb_trust_forest_info_add_record(nfti, &tftr);
1325
0
    if (!NT_STATUS_IS_OK(status)) {
1326
0
      TALLOC_FREE(frame);
1327
0
      return status;
1328
0
    }
1329
0
  }
1330
1331
0
  for (g = 0; g < gfti->count; g++) {
1332
0
    const struct lsa_ForestTrustRecord2 *gftr = gfti->entries[gfti->count - (g+1)];
1333
0
    struct lsa_ForestTrustRecord2 tftr;
1334
0
    bool skip = false;
1335
0
    NTSTATUS status;
1336
1337
0
    if (gftr == NULL) {
1338
0
      continue;
1339
0
    }
1340
1341
0
    switch (gftr->type) {
1342
0
    case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
1343
0
    case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
1344
0
    case LSA_FOREST_TRUST_BINARY_DATA:
1345
0
    case LSA_FOREST_TRUST_SCANNER_INFO:
1346
0
      skip = true;
1347
0
      break;
1348
1349
0
    case LSA_FOREST_TRUST_DOMAIN_INFO:
1350
0
      break;
1351
1352
0
    default:
1353
0
      TALLOC_FREE(frame);
1354
0
      return NT_STATUS_INVALID_PARAMETER;
1355
0
    }
1356
1357
0
    if (skip) {
1358
0
      continue;
1359
0
    }
1360
1361
    /* make a copy in order to update the time. */
1362
0
    tftr = *gftr;
1363
0
    if (tftr.time == 0) {
1364
0
      tftr.time = now;
1365
0
    }
1366
1367
0
    status = dsdb_trust_forest_info_add_record(nfti, &tftr);
1368
0
    if (!NT_STATUS_IS_OK(status)) {
1369
0
      TALLOC_FREE(frame);
1370
0
      return status;
1371
0
    }
1372
0
  }
1373
1374
0
  for (g = 0; g < gfti->count; g++) {
1375
0
    const struct lsa_ForestTrustRecord2 *gftr = gfti->entries[gfti->count - (g+1)];
1376
0
    struct lsa_ForestTrustRecord2 tftr;
1377
0
    bool skip = false;
1378
0
    NTSTATUS status;
1379
1380
0
    if (gftr == NULL) {
1381
0
      continue;
1382
0
    }
1383
1384
0
    switch (gftr->type) {
1385
0
    case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
1386
0
    case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
1387
0
    case LSA_FOREST_TRUST_DOMAIN_INFO:
1388
0
    case LSA_FOREST_TRUST_BINARY_DATA:
1389
0
      skip = true;
1390
0
      break;
1391
1392
0
    case LSA_FOREST_TRUST_SCANNER_INFO:
1393
0
      break;
1394
1395
0
    default:
1396
0
      TALLOC_FREE(frame);
1397
0
      return NT_STATUS_INVALID_PARAMETER;
1398
0
    }
1399
1400
0
    if (skip) {
1401
0
      continue;
1402
0
    }
1403
1404
    /* make a copy in order to update the time. */
1405
0
    tftr = *gftr;
1406
0
    if (tftr.time == 0) {
1407
0
      tftr.time = now;
1408
0
    }
1409
1410
0
    status = dsdb_trust_forest_info_add_record(nfti, &tftr);
1411
0
    if (!NT_STATUS_IS_OK(status)) {
1412
0
      TALLOC_FREE(frame);
1413
0
      return status;
1414
0
    }
1415
0
  }
1416
1417
0
  for (g = 0; g < gfti->count; g++) {
1418
0
    const struct lsa_ForestTrustRecord2 *gftr = gfti->entries[gfti->count - (g+1)];
1419
0
    struct lsa_ForestTrustRecord2 tftr;
1420
0
    bool skip = false;
1421
0
    NTSTATUS status;
1422
1423
0
    if (gftr == NULL) {
1424
0
      continue;
1425
0
    }
1426
1427
0
    switch (gftr->type) {
1428
0
    case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
1429
0
    case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
1430
0
    case LSA_FOREST_TRUST_DOMAIN_INFO:
1431
0
    case LSA_FOREST_TRUST_SCANNER_INFO:
1432
0
      skip = true;
1433
0
      break;
1434
1435
0
    case LSA_FOREST_TRUST_BINARY_DATA:
1436
0
      break;
1437
1438
0
    default:
1439
0
      TALLOC_FREE(frame);
1440
0
      return NT_STATUS_INVALID_PARAMETER;
1441
0
    }
1442
1443
0
    if (skip) {
1444
0
      continue;
1445
0
    }
1446
1447
    /* make a copy in order to update the time. */
1448
0
    tftr = *gftr;
1449
0
    if (tftr.time == 0) {
1450
0
      tftr.time = now;
1451
0
    }
1452
1453
0
    status = dsdb_trust_forest_info_add_record(nfti, &tftr);
1454
0
    if (!NT_STATUS_IS_OK(status)) {
1455
0
      TALLOC_FREE(frame);
1456
0
      return status;
1457
0
    }
1458
0
  }
1459
1460
0
  *_nfti = talloc_move(mem_ctx, &nfti);
1461
0
  TALLOC_FREE(frame);
1462
0
  return NT_STATUS_OK;
1463
0
}
1464
1465
static NTSTATUS dsdb_trust_add_collision(
1466
      struct lsa_ForestTrustCollisionInfo *c_info,
1467
      enum lsa_ForestTrustCollisionRecordType type,
1468
      uint32_t idx, uint32_t flags,
1469
      const char *tdo_name)
1470
0
{
1471
0
  struct lsa_ForestTrustCollisionRecord **es;
1472
0
  uint32_t i = c_info->count;
1473
1474
0
  es = talloc_realloc(c_info, c_info->entries,
1475
0
          struct lsa_ForestTrustCollisionRecord *, i + 1);
1476
0
  if (es == NULL) {
1477
0
    return NT_STATUS_NO_MEMORY;
1478
0
  }
1479
0
  c_info->entries = es;
1480
0
  c_info->count = i + 1;
1481
1482
0
  es[i] = talloc_zero(es, struct lsa_ForestTrustCollisionRecord);
1483
0
  if (es[i] == NULL) {
1484
0
    return NT_STATUS_NO_MEMORY;
1485
0
  }
1486
1487
0
  es[i]->index = idx;
1488
0
  es[i]->type = type;
1489
0
  es[i]->flags = flags;
1490
0
  es[i]->name.string = talloc_strdup(es[i], tdo_name);
1491
0
  if (es[i]->name.string == NULL) {
1492
0
    return NT_STATUS_NO_MEMORY;
1493
0
  }
1494
1495
0
  return NT_STATUS_OK;
1496
0
}
1497
1498
NTSTATUS dsdb_trust_verify_forest_info(const struct lsa_TrustDomainInfoInfoEx *ref_tdo,
1499
        const struct lsa_ForestTrustInformation2 *ref_fti,
1500
        enum lsa_ForestTrustCollisionRecordType collision_type,
1501
        struct lsa_ForestTrustCollisionInfo *c_info,
1502
        struct lsa_ForestTrustInformation2 *new_fti)
1503
0
{
1504
0
  uint32_t n;
1505
1506
0
  for (n = 0; n < new_fti->count; n++) {
1507
0
    struct lsa_ForestTrustRecord2 *nftr = new_fti->entries[n];
1508
0
    struct lsa_StringLarge *ntln = NULL;
1509
0
    bool ntln_excluded = false;
1510
0
    uint32_t flags = 0;
1511
0
    uint32_t r;
1512
0
    NTSTATUS status;
1513
1514
0
    if (nftr == NULL) {
1515
0
      continue;
1516
0
    }
1517
1518
0
    if (nftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
1519
0
      continue;
1520
0
    }
1521
1522
0
    ntln = &nftr->forest_trust_data.top_level_name;
1523
0
    if (ntln->string == NULL) {
1524
0
      return NT_STATUS_INVALID_PARAMETER;
1525
0
    }
1526
1527
0
    ntln_excluded = trust_forest_info_tln_ex_match(ref_fti,
1528
0
                     ntln->string);
1529
1530
    /* check if this is already taken and not excluded */
1531
0
    for (r = 0; r < ref_fti->count; r++) {
1532
0
      const struct lsa_ForestTrustRecord2 *rftr =
1533
0
        ref_fti->entries[r];
1534
0
      const struct lsa_StringLarge *rtln = NULL;
1535
0
      int cmp;
1536
1537
0
      if (rftr == NULL) {
1538
0
        continue;
1539
0
      }
1540
1541
0
      if (rftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
1542
0
        continue;
1543
0
      }
1544
1545
0
      rtln = &rftr->forest_trust_data.top_level_name;
1546
0
      if (rtln->string == NULL) {
1547
0
        continue;
1548
0
      }
1549
1550
0
      cmp = dns_cmp(ntln->string, rtln->string);
1551
0
      if (DNS_CMP_IS_NO_MATCH(cmp)) {
1552
0
        continue;
1553
0
      }
1554
0
      if (cmp == DNS_CMP_MATCH) {
1555
        /* We need to normalize the string */
1556
0
        ntln->string = talloc_strdup(nftr,
1557
0
                   rtln->string);
1558
0
        if (ntln->string == NULL) {
1559
0
          return NT_STATUS_NO_MEMORY;
1560
0
        }
1561
0
      }
1562
1563
0
      if (ntln_excluded) {
1564
0
        continue;
1565
0
      }
1566
1567
0
      if (rftr->flags & LSA_TLN_DISABLED_MASK) {
1568
0
        continue;
1569
0
      }
1570
1571
0
      if (nftr->flags & LSA_TLN_DISABLED_MASK) {
1572
0
        continue;
1573
0
      }
1574
1575
0
      if (cmp == DNS_CMP_SECOND_IS_CHILD) {
1576
0
        bool m;
1577
1578
        /*
1579
         * If the conflicting tln is a child, check if
1580
         * we have an exclusion record for it.
1581
         */
1582
0
        m = trust_forest_info_tln_ex_match(new_fti,
1583
0
                   rtln->string);
1584
0
        if (m) {
1585
0
          continue;
1586
0
        }
1587
0
      }
1588
1589
0
      flags |= LSA_TLN_DISABLED_CONFLICT;
1590
0
    }
1591
1592
0
    if (flags == 0) {
1593
0
      continue;
1594
0
    }
1595
1596
0
    nftr->flags |= flags;
1597
1598
0
    status = dsdb_trust_add_collision(c_info,
1599
0
              collision_type,
1600
0
              n, nftr->flags,
1601
0
              ref_tdo->domain_name.string);
1602
0
    if (!NT_STATUS_IS_OK(status)) {
1603
0
      return status;
1604
0
    }
1605
0
  }
1606
1607
0
  for (n = 0; n < new_fti->count; n++) {
1608
0
    struct lsa_ForestTrustRecord2 *nftr = new_fti->entries[n];
1609
0
    struct lsa_ForestTrustDomainInfo *ninfo = NULL;
1610
0
    struct lsa_StringLarge *ntln = NULL;
1611
0
    struct lsa_StringLarge *nnb = NULL;
1612
0
    struct dom_sid *nsid = NULL;
1613
0
    bool ntln_found = false;
1614
0
    uint32_t flags = 0;
1615
0
    uint32_t r;
1616
0
    NTSTATUS status;
1617
1618
0
    if (nftr == NULL) {
1619
0
      continue;
1620
0
    }
1621
1622
0
    if (nftr->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
1623
0
      continue;
1624
0
    }
1625
1626
0
    ninfo = &nftr->forest_trust_data.domain_info;
1627
0
    ntln = &ninfo->dns_domain_name;
1628
0
    if (ntln->string == NULL) {
1629
0
      return NT_STATUS_INVALID_PARAMETER;
1630
0
    }
1631
0
    nnb = &ninfo->netbios_domain_name;
1632
0
    if (nnb->string == NULL) {
1633
0
      return NT_STATUS_INVALID_PARAMETER;
1634
0
    }
1635
0
    nsid = ninfo->domain_sid;
1636
0
    if (nsid == NULL) {
1637
0
      return NT_STATUS_INVALID_PARAMETER;
1638
0
    }
1639
1640
0
    ntln_found = trust_forest_info_tln_match(ref_fti, ntln->string);
1641
1642
    /* check if this is already taken and not excluded */
1643
0
    for (r = 0; r < ref_fti->count; r++) {
1644
0
      const struct lsa_ForestTrustRecord2 *rftr =
1645
0
        ref_fti->entries[r];
1646
0
      const struct lsa_ForestTrustDomainInfo *rinfo = NULL;
1647
0
      const struct lsa_StringLarge *rtln = NULL;
1648
0
      const struct lsa_StringLarge *rnb = NULL;
1649
0
      const struct dom_sid *rsid = NULL;
1650
0
      bool nb_possible = true;
1651
0
      bool sid_possible = true;
1652
0
      int cmp;
1653
1654
0
      if (rftr == NULL) {
1655
0
        continue;
1656
0
      }
1657
1658
0
      if (!ntln_found) {
1659
        /*
1660
         * If the dns name doesn't match any existing
1661
         * tln any conflict is ignored, but name
1662
         * normalization still happens.
1663
         *
1664
         * I guess that's a bug in Windows
1665
         * (tested with Windows 2012r2).
1666
         */
1667
0
        nb_possible = false;
1668
0
        sid_possible = false;
1669
0
      }
1670
1671
0
      if (nftr->flags & LSA_SID_DISABLED_MASK) {
1672
0
        sid_possible = false;
1673
0
      }
1674
1675
0
      if (nftr->flags & LSA_NB_DISABLED_MASK) {
1676
0
        nb_possible = false;
1677
0
      }
1678
1679
0
      switch (rftr->type) {
1680
0
      case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
1681
0
        rtln = &rftr->forest_trust_data.top_level_name;
1682
0
        nb_possible = false;
1683
0
        sid_possible = false;
1684
0
        break;
1685
1686
0
      case LSA_FOREST_TRUST_DOMAIN_INFO:
1687
0
        rinfo = &rftr->forest_trust_data.domain_info;
1688
0
        rtln = &rinfo->dns_domain_name;
1689
0
        rnb = &rinfo->netbios_domain_name;
1690
0
        rsid = rinfo->domain_sid;
1691
1692
0
        if (rftr->flags & LSA_SID_DISABLED_MASK) {
1693
0
          sid_possible = false;
1694
0
        }
1695
1696
0
        if (rftr->flags & LSA_NB_DISABLED_MASK) {
1697
0
          nb_possible = false;
1698
0
        }
1699
0
        break;
1700
1701
0
      default:
1702
0
        break;
1703
0
      }
1704
1705
0
      if (rtln == NULL) {
1706
0
        continue;
1707
0
      }
1708
1709
0
      if (rtln->string == NULL) {
1710
0
        continue;
1711
0
      }
1712
1713
0
      cmp = dns_cmp(ntln->string, rtln->string);
1714
0
      if (DNS_CMP_IS_NO_MATCH(cmp)) {
1715
0
        nb_possible = false;
1716
0
        sid_possible = false;
1717
0
      }
1718
0
      if (cmp == DNS_CMP_MATCH) {
1719
        /* We need to normalize the string */
1720
0
        ntln->string = talloc_strdup(nftr,
1721
0
                   rtln->string);
1722
0
        if (ntln->string == NULL) {
1723
0
          return NT_STATUS_NO_MEMORY;
1724
0
        }
1725
0
      }
1726
1727
0
      if (rinfo == NULL) {
1728
0
        continue;
1729
0
      }
1730
1731
0
      if (rsid != NULL) {
1732
0
        cmp = dom_sid_compare(nsid, rsid);
1733
0
      } else {
1734
0
        cmp = -1;
1735
0
      }
1736
0
      if (cmp == 0) {
1737
0
        if (sid_possible) {
1738
0
          flags |= LSA_SID_DISABLED_CONFLICT;
1739
0
        }
1740
0
      }
1741
1742
0
      if (rnb->string != NULL) {
1743
0
        cmp = strcasecmp_m(nnb->string, rnb->string);
1744
0
      } else {
1745
0
        cmp = -1;
1746
0
      }
1747
0
      if (cmp == 0) {
1748
0
        nnb->string = talloc_strdup(nftr, rnb->string);
1749
0
        if (nnb->string == NULL) {
1750
0
          return NT_STATUS_NO_MEMORY;
1751
0
        }
1752
0
        if (nb_possible) {
1753
0
          flags |= LSA_NB_DISABLED_CONFLICT;
1754
0
        }
1755
0
      }
1756
0
    }
1757
1758
0
    if (flags == 0) {
1759
0
      continue;
1760
0
    }
1761
1762
0
    nftr->flags |= flags;
1763
1764
0
    status = dsdb_trust_add_collision(c_info,
1765
0
              collision_type,
1766
0
              n, nftr->flags,
1767
0
              ref_tdo->domain_name.string);
1768
0
    if (!NT_STATUS_IS_OK(status)) {
1769
0
      return status;
1770
0
    }
1771
0
  }
1772
1773
0
  return NT_STATUS_OK;
1774
0
}
1775
1776
NTSTATUS dsdb_trust_merge_forest_info(TALLOC_CTX *mem_ctx,
1777
        const struct lsa_TrustDomainInfoInfoEx *tdo,
1778
        const struct lsa_ForestTrustInformation2 *ofti,
1779
        const struct lsa_ForestTrustInformation2 *nfti,
1780
        struct lsa_ForestTrustInformation2 **_mfti)
1781
0
{
1782
0
  TALLOC_CTX *frame = talloc_stackframe();
1783
0
  struct lsa_ForestTrustInformation2 *mfti = NULL;
1784
0
  uint32_t ni;
1785
0
  uint32_t oi;
1786
0
  NTSTATUS status;
1787
0
  int cmp;
1788
1789
0
  *_mfti = NULL;
1790
0
  mfti = talloc_zero(mem_ctx, struct lsa_ForestTrustInformation2);
1791
0
  if (mfti == NULL) {
1792
0
    TALLOC_FREE(frame);
1793
0
    return NT_STATUS_NO_MEMORY;
1794
0
  }
1795
0
  talloc_steal(frame, mfti);
1796
1797
  /*
1798
   * First we add all top unique level names.
1799
   *
1800
   * The one matching the tdo dns name, will be
1801
   * added without further checking. All others
1802
   * may keep the flags and time values.
1803
   */
1804
0
  for (ni = 0; ni < nfti->count; ni++) {
1805
0
    const struct lsa_ForestTrustRecord2 *nftr = nfti->entries[ni];
1806
0
    struct lsa_ForestTrustRecord2 tftr = {
1807
0
      .flags = 0,
1808
0
    };
1809
0
    const char *ndns = NULL;
1810
0
    bool ignore_new = false;
1811
0
    bool found_old = false;
1812
0
    uint32_t mi;
1813
1814
0
    if (nftr == NULL) {
1815
0
      TALLOC_FREE(frame);
1816
0
      return NT_STATUS_INVALID_PARAMETER;
1817
0
    }
1818
1819
0
    if (nftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
1820
0
      continue;
1821
0
    }
1822
1823
0
    ndns = nftr->forest_trust_data.top_level_name.string;
1824
0
    if (ndns == NULL) {
1825
0
      TALLOC_FREE(frame);
1826
0
      return NT_STATUS_INVALID_PARAMETER;
1827
0
    }
1828
1829
0
    cmp = dns_cmp(tdo->domain_name.string, ndns);
1830
0
    if (cmp == DNS_CMP_MATCH) {
1831
0
      status = dsdb_trust_forest_info_add_record(mfti, nftr);
1832
0
      if (!NT_STATUS_IS_OK(status)) {
1833
0
        TALLOC_FREE(frame);
1834
0
        return status;
1835
0
      }
1836
0
    }
1837
1838
0
    for (mi = 0; mi < mfti->count; mi++) {
1839
0
      const struct lsa_ForestTrustRecord2 *mftr =
1840
0
        mfti->entries[mi];
1841
0
      const char *mdns = NULL;
1842
1843
      /*
1844
       * we just added this above, so we're sure to have a
1845
       * valid LSA_FOREST_TRUST_TOP_LEVEL_NAME record
1846
       */
1847
0
      mdns = mftr->forest_trust_data.top_level_name.string;
1848
1849
0
      cmp = dns_cmp(mdns, ndns);
1850
0
      switch (cmp) {
1851
0
      case DNS_CMP_MATCH:
1852
0
      case DNS_CMP_SECOND_IS_CHILD:
1853
0
        ignore_new = true;
1854
0
        break;
1855
0
      }
1856
1857
0
      if (ignore_new) {
1858
0
        break;
1859
0
      }
1860
0
    }
1861
1862
0
    if (ignore_new) {
1863
0
      continue;
1864
0
    }
1865
1866
    /*
1867
     * make a temporary copy where we can change time and flags
1868
     */
1869
0
    tftr = *nftr;
1870
1871
0
    for (oi = 0; oi < ofti->count; oi++) {
1872
0
      const struct lsa_ForestTrustRecord2 *oftr =
1873
0
        ofti->entries[oi];
1874
0
      const char *odns = NULL;
1875
1876
0
      if (oftr == NULL) {
1877
        /*
1878
         * broken record => ignore...
1879
         */
1880
0
        continue;
1881
0
      }
1882
1883
0
      if (oftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
1884
0
        continue;
1885
0
      }
1886
1887
0
      odns = oftr->forest_trust_data.top_level_name.string;
1888
0
      if (odns == NULL) {
1889
        /*
1890
         * broken record => ignore...
1891
         */
1892
0
        continue;
1893
0
      }
1894
1895
0
      cmp = dns_cmp(odns, ndns);
1896
0
      if (cmp != DNS_CMP_MATCH) {
1897
0
        continue;
1898
0
      }
1899
1900
0
      found_old = true;
1901
0
      tftr.flags = oftr->flags;
1902
0
      tftr.time = oftr->time;
1903
0
    }
1904
1905
0
    if (!found_old) {
1906
0
      tftr.flags = LSA_TLN_DISABLED_NEW;
1907
0
      tftr.time = 0;
1908
0
    }
1909
1910
0
    status = dsdb_trust_forest_info_add_record(mfti, &tftr);
1911
0
    if (!NT_STATUS_IS_OK(status)) {
1912
0
      TALLOC_FREE(frame);
1913
0
      return status;
1914
0
    }
1915
0
  }
1916
1917
  /*
1918
   * Now we add all unique (based on their SID) domains
1919
   * and may keep the flags and time values.
1920
   */
1921
0
  for (ni = 0; ni < nfti->count; ni++) {
1922
0
    const struct lsa_ForestTrustRecord2 *nftr = nfti->entries[ni];
1923
0
    struct lsa_ForestTrustRecord2 tftr = {
1924
0
      .flags = 0,
1925
0
    };
1926
0
    const struct lsa_ForestTrustDomainInfo *nd = NULL;
1927
0
    const char *ndns = NULL;
1928
0
    const char *nnbt = NULL;
1929
0
    bool ignore_new = false;
1930
0
    bool found_old = false;
1931
0
    uint32_t mi;
1932
1933
0
    if (nftr == NULL) {
1934
0
      TALLOC_FREE(frame);
1935
0
      return NT_STATUS_INVALID_PARAMETER;
1936
0
    }
1937
1938
0
    if (nftr->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
1939
0
      continue;
1940
0
    }
1941
1942
0
    nd = &nftr->forest_trust_data.domain_info;
1943
0
    if (nd->domain_sid == NULL) {
1944
0
      TALLOC_FREE(frame);
1945
0
      return NT_STATUS_INVALID_PARAMETER;
1946
0
    }
1947
0
    ndns = nd->dns_domain_name.string;
1948
0
    if (ndns == NULL) {
1949
0
      TALLOC_FREE(frame);
1950
0
      return NT_STATUS_INVALID_PARAMETER;
1951
0
    }
1952
0
    nnbt = nd->netbios_domain_name.string;
1953
0
    if (nnbt == NULL) {
1954
0
      TALLOC_FREE(frame);
1955
0
      return NT_STATUS_INVALID_PARAMETER;
1956
0
    }
1957
1958
0
    for (mi = 0; mi < mfti->count; mi++) {
1959
0
      const struct lsa_ForestTrustRecord2 *mftr =
1960
0
        mfti->entries[mi];
1961
0
      const struct lsa_ForestTrustDomainInfo *md = NULL;
1962
1963
0
      if (mftr->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
1964
0
        continue;
1965
0
      }
1966
1967
      /*
1968
       * we just added this above, so we're sure to have a
1969
       * valid LSA_FOREST_TRUST_DOMAIN_INFO record
1970
       */
1971
0
      md = &mftr->forest_trust_data.domain_info;
1972
1973
0
      cmp = dom_sid_compare(nd->domain_sid, md->domain_sid);
1974
0
      if (cmp == 0) {
1975
0
        ignore_new = true;
1976
0
        break;
1977
0
      }
1978
0
    }
1979
1980
0
    if (ignore_new) {
1981
0
      continue;
1982
0
    }
1983
1984
    /*
1985
     * make a temporary copy where we can change time and flags
1986
     */
1987
0
    tftr = *nftr;
1988
1989
0
    for (oi = 0; oi < ofti->count; oi++) {
1990
0
      const struct lsa_ForestTrustRecord2 *oftr =
1991
0
        ofti->entries[oi];
1992
0
      const struct lsa_ForestTrustDomainInfo *od = NULL;
1993
0
      const char *onbt = NULL;
1994
1995
0
      if (oftr == NULL) {
1996
        /*
1997
         * broken record => ignore...
1998
         */
1999
0
        continue;
2000
0
      }
2001
2002
0
      if (oftr->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
2003
0
        continue;
2004
0
      }
2005
2006
0
      od = &oftr->forest_trust_data.domain_info;
2007
0
      onbt = od->netbios_domain_name.string;
2008
0
      if (onbt == NULL) {
2009
        /*
2010
         * broken record => ignore...
2011
         */
2012
0
        continue;
2013
0
      }
2014
2015
0
      cmp = strcasecmp(onbt, nnbt);
2016
0
      if (cmp != 0) {
2017
0
        continue;
2018
0
      }
2019
2020
0
      found_old = true;
2021
0
      tftr.flags = oftr->flags;
2022
0
      tftr.time = oftr->time;
2023
0
    }
2024
2025
0
    if (!found_old) {
2026
0
      tftr.flags = 0;
2027
0
      tftr.time = 0;
2028
0
    }
2029
2030
0
    status = dsdb_trust_forest_info_add_record(mfti, &tftr);
2031
0
    if (!NT_STATUS_IS_OK(status)) {
2032
0
      TALLOC_FREE(frame);
2033
0
      return status;
2034
0
    }
2035
0
  }
2036
2037
  /*
2038
   * We keep old domain records disabled by the admin
2039
   * if not already in the list.
2040
   */
2041
0
  for (oi = 0; oi < ofti->count; oi++) {
2042
0
    const struct lsa_ForestTrustRecord2 *oftr =
2043
0
      ofti->entries[oi];
2044
0
    const struct lsa_ForestTrustDomainInfo *od = NULL;
2045
0
    const char *odns = NULL;
2046
0
    const char *onbt = NULL;
2047
0
    bool ignore_old = true;
2048
0
    uint32_t mi;
2049
2050
0
    if (oftr == NULL) {
2051
      /*
2052
       * broken record => ignore...
2053
       */
2054
0
      continue;
2055
0
    }
2056
2057
0
    if (oftr->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
2058
0
      continue;
2059
0
    }
2060
2061
0
    od = &oftr->forest_trust_data.domain_info;
2062
0
    odns = od->dns_domain_name.string;
2063
0
    if (odns == NULL) {
2064
      /*
2065
       * broken record => ignore...
2066
       */
2067
0
      continue;
2068
0
    }
2069
0
    onbt = od->netbios_domain_name.string;
2070
0
    if (onbt == NULL) {
2071
      /*
2072
       * broken record => ignore...
2073
       */
2074
0
      continue;
2075
0
    }
2076
0
    if (od->domain_sid == NULL) {
2077
      /*
2078
       * broken record => ignore...
2079
       */
2080
0
      continue;
2081
0
    }
2082
2083
0
    if (oftr->flags & LSA_NB_DISABLED_ADMIN) {
2084
0
      ignore_old = false;
2085
0
    } else if (oftr->flags & LSA_SID_DISABLED_ADMIN) {
2086
0
      ignore_old = false;
2087
0
    }
2088
2089
0
    for (mi = 0; mi < mfti->count; mi++) {
2090
0
      const struct lsa_ForestTrustRecord2 *mftr =
2091
0
        mfti->entries[mi];
2092
0
      const struct lsa_ForestTrustDomainInfo *md = NULL;
2093
2094
0
      if (mftr->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
2095
0
        continue;
2096
0
      }
2097
2098
      /*
2099
       * we just added this above, so we're sure to have a
2100
       * valid LSA_FOREST_TRUST_DOMAIN_INFO record
2101
       */
2102
0
      md = &mftr->forest_trust_data.domain_info;
2103
2104
0
      cmp = dom_sid_compare(od->domain_sid, md->domain_sid);
2105
0
      if (cmp == 0) {
2106
0
        ignore_old = true;
2107
0
        break;
2108
0
      }
2109
0
    }
2110
2111
0
    if (ignore_old) {
2112
0
      continue;
2113
0
    }
2114
2115
0
    status = dsdb_trust_forest_info_add_record(mfti, oftr);
2116
0
    if (!NT_STATUS_IS_OK(status)) {
2117
0
      TALLOC_FREE(frame);
2118
0
      return status;
2119
0
    }
2120
0
  }
2121
2122
  /*
2123
   * Finally we readd top level exclusions,
2124
   * if they still match a top level name.
2125
   */
2126
0
  for (oi = 0; oi < ofti->count; oi++) {
2127
0
    const struct lsa_ForestTrustRecord2 *oftr =
2128
0
      ofti->entries[oi];
2129
0
    const char *odns = NULL;
2130
0
    bool ignore_old = false;
2131
0
    uint32_t mi;
2132
2133
0
    if (oftr == NULL) {
2134
      /*
2135
       * broken record => ignore...
2136
       */
2137
0
      continue;
2138
0
    }
2139
2140
0
    if (oftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX) {
2141
0
      continue;
2142
0
    }
2143
2144
0
    odns = oftr->forest_trust_data.top_level_name_ex.string;
2145
0
    if (odns == NULL) {
2146
      /*
2147
       * broken record => ignore...
2148
       */
2149
0
      continue;
2150
0
    }
2151
2152
0
    for (mi = 0; mi < mfti->count; mi++) {
2153
0
      const struct lsa_ForestTrustRecord2 *mftr =
2154
0
        mfti->entries[mi];
2155
0
      const char *mdns = NULL;
2156
2157
0
      if (mftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
2158
0
        continue;
2159
0
      }
2160
2161
      /*
2162
       * we just added this above, so we're sure to have a
2163
       * valid LSA_FOREST_TRUST_TOP_LEVEL_NAME.
2164
       */
2165
0
      mdns = mftr->forest_trust_data.top_level_name.string;
2166
2167
0
      cmp = dns_cmp(mdns, odns);
2168
0
      switch (cmp) {
2169
0
      case DNS_CMP_MATCH:
2170
0
      case DNS_CMP_SECOND_IS_CHILD:
2171
0
        break;
2172
0
      default:
2173
0
        ignore_old = true;
2174
0
        break;
2175
0
      }
2176
2177
0
      if (ignore_old) {
2178
0
        break;
2179
0
      }
2180
0
    }
2181
2182
0
    if (ignore_old) {
2183
0
      continue;
2184
0
    }
2185
2186
0
    status = dsdb_trust_forest_info_add_record(mfti, oftr);
2187
0
    if (!NT_STATUS_IS_OK(status)) {
2188
0
      TALLOC_FREE(frame);
2189
0
      return status;
2190
0
    }
2191
0
  }
2192
2193
  /*
2194
   * Finally we readd scanner info records
2195
   */
2196
0
  for (oi = 0; oi < ofti->count; oi++) {
2197
0
    const struct lsa_ForestTrustRecord2 *oftr =
2198
0
      ofti->entries[oi];
2199
2200
0
    if (oftr == NULL) {
2201
      /*
2202
       * broken record => ignore...
2203
       */
2204
0
      continue;
2205
0
    }
2206
2207
0
    if (oftr->type != LSA_FOREST_TRUST_SCANNER_INFO) {
2208
0
      continue;
2209
0
    }
2210
2211
0
    status = dsdb_trust_forest_info_add_record(mfti, oftr);
2212
0
    if (!NT_STATUS_IS_OK(status)) {
2213
0
      TALLOC_FREE(frame);
2214
0
      return status;
2215
0
    }
2216
0
  }
2217
2218
  /*
2219
   * Finally we readd binary info records
2220
   */
2221
0
  for (oi = 0; oi < ofti->count; oi++) {
2222
0
    const struct lsa_ForestTrustRecord2 *oftr =
2223
0
      ofti->entries[oi];
2224
2225
0
    if (oftr == NULL) {
2226
      /*
2227
       * broken record => ignore...
2228
       */
2229
0
      continue;
2230
0
    }
2231
2232
0
    if (oftr->type != LSA_FOREST_TRUST_BINARY_DATA) {
2233
0
      continue;
2234
0
    }
2235
2236
0
    status = dsdb_trust_forest_info_add_record(mfti, oftr);
2237
0
    if (!NT_STATUS_IS_OK(status)) {
2238
0
      TALLOC_FREE(frame);
2239
0
      return status;
2240
0
    }
2241
0
  }
2242
2243
0
  *_mfti = talloc_move(mem_ctx, &mfti);
2244
0
  TALLOC_FREE(frame);
2245
0
  return NT_STATUS_OK;
2246
0
}
2247
2248
NTSTATUS dsdb_trust_search_tdo(struct ldb_context *sam_ctx,
2249
             const char *netbios, const char *dns,
2250
             const char * const *attrs,
2251
             TALLOC_CTX *mem_ctx,
2252
             struct ldb_message **msg)
2253
0
{
2254
0
  TALLOC_CTX *frame = talloc_stackframe();
2255
0
  int ret;
2256
0
  struct ldb_dn *system_dn = NULL;
2257
0
  char *netbios_encoded = NULL;
2258
0
  char *dns_encoded = NULL;
2259
0
  char *filter = NULL;
2260
2261
0
  *msg = NULL;
2262
2263
0
  if (netbios == NULL && dns == NULL) {
2264
0
    TALLOC_FREE(frame);
2265
0
    return NT_STATUS_INVALID_PARAMETER_MIX;
2266
0
  }
2267
2268
0
  system_dn = samdb_system_container_dn(sam_ctx, frame);
2269
0
  if (system_dn == NULL) {
2270
0
    TALLOC_FREE(frame);
2271
0
    return NT_STATUS_NO_MEMORY;
2272
0
  }
2273
2274
0
  if (netbios != NULL) {
2275
0
    netbios_encoded = ldb_binary_encode_string(frame, netbios);
2276
0
    if (netbios_encoded == NULL) {
2277
0
      TALLOC_FREE(frame);
2278
0
      return NT_STATUS_NO_MEMORY;
2279
0
    }
2280
0
  }
2281
2282
0
  if (dns != NULL) {
2283
0
    dns_encoded = ldb_binary_encode_string(frame, dns);
2284
0
    if (dns_encoded == NULL) {
2285
0
      TALLOC_FREE(frame);
2286
0
      return NT_STATUS_NO_MEMORY;
2287
0
    }
2288
0
  }
2289
2290
0
  if (netbios != NULL && dns != NULL) {
2291
0
    filter = talloc_asprintf(frame,
2292
0
        "(&(objectClass=trustedDomain)"
2293
0
          "(|(trustPartner=%s)(flatName=%s))"
2294
0
        ")",
2295
0
        dns_encoded, netbios_encoded);
2296
0
    if (filter == NULL) {
2297
0
      TALLOC_FREE(frame);
2298
0
      return NT_STATUS_NO_MEMORY;
2299
0
    }
2300
0
  } else if (netbios != NULL) {
2301
0
    filter = talloc_asprintf(frame,
2302
0
        "(&(objectClass=trustedDomain)(flatName=%s))",
2303
0
        netbios_encoded);
2304
0
    if (filter == NULL) {
2305
0
      TALLOC_FREE(frame);
2306
0
      return NT_STATUS_NO_MEMORY;
2307
0
    }
2308
0
  } else if (dns != NULL) {
2309
0
    filter = talloc_asprintf(frame,
2310
0
        "(&(objectClass=trustedDomain)(trustPartner=%s))",
2311
0
        dns_encoded);
2312
0
    if (filter == NULL) {
2313
0
      TALLOC_FREE(frame);
2314
0
      return NT_STATUS_NO_MEMORY;
2315
0
    }
2316
0
  }
2317
2318
0
  ret = dsdb_search_one(sam_ctx, mem_ctx, msg,
2319
0
            system_dn,
2320
0
            LDB_SCOPE_ONELEVEL, attrs,
2321
0
            DSDB_SEARCH_NO_GLOBAL_CATALOG,
2322
0
            "%s", filter);
2323
0
  if (ret != LDB_SUCCESS) {
2324
0
    NTSTATUS status = dsdb_ldb_err_to_ntstatus(ret);
2325
0
    DEBUG(3, ("Failed to search for %s: %s - %s\n",
2326
0
        filter, nt_errstr(status), ldb_errstring(sam_ctx)));
2327
0
    TALLOC_FREE(frame);
2328
0
    return status;
2329
0
  }
2330
2331
0
  TALLOC_FREE(frame);
2332
0
  return NT_STATUS_OK;
2333
0
}
2334
2335
NTSTATUS dsdb_trust_search_tdo_by_type(struct ldb_context *sam_ctx,
2336
               enum netr_SchannelType type,
2337
               const char *name,
2338
               const char * const *attrs,
2339
               TALLOC_CTX *mem_ctx,
2340
               struct ldb_message **msg)
2341
0
{
2342
0
  TALLOC_CTX *frame = talloc_stackframe();
2343
0
  NTSTATUS status;
2344
0
  size_t len;
2345
0
  char trailer = '$';
2346
0
  bool require_trailer = true;
2347
0
  char *encoded_name = NULL;
2348
0
  const char *netbios = NULL;
2349
0
  const char *dns = NULL;
2350
2351
0
  if (type != SEC_CHAN_DOMAIN && type != SEC_CHAN_DNS_DOMAIN) {
2352
0
    TALLOC_FREE(frame);
2353
0
    return NT_STATUS_INVALID_PARAMETER;
2354
0
  }
2355
2356
0
  if (type == SEC_CHAN_DNS_DOMAIN) {
2357
0
    trailer = '.';
2358
0
    require_trailer = false;
2359
0
  }
2360
2361
0
  encoded_name = ldb_binary_encode_string(frame, name);
2362
0
  if (encoded_name == NULL) {
2363
0
    TALLOC_FREE(frame);
2364
0
    return NT_STATUS_NO_MEMORY;
2365
0
  }
2366
2367
0
  len = strlen(encoded_name);
2368
0
  if (len < 2) {
2369
0
    TALLOC_FREE(frame);
2370
0
    return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2371
0
  }
2372
2373
0
  if (require_trailer && encoded_name[len - 1] != trailer) {
2374
0
    TALLOC_FREE(frame);
2375
0
    return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2376
0
  }
2377
0
  encoded_name[len - 1] = '\0';
2378
2379
0
  if (type == SEC_CHAN_DNS_DOMAIN) {
2380
0
    dns = encoded_name;
2381
0
  } else {
2382
0
    netbios = encoded_name;
2383
0
  }
2384
2385
0
  status = dsdb_trust_search_tdo(sam_ctx, netbios, dns,
2386
0
               attrs, mem_ctx, msg);
2387
0
  if (!NT_STATUS_IS_OK(status)) {
2388
0
    TALLOC_FREE(frame);
2389
0
    return status;
2390
0
  }
2391
2392
0
  TALLOC_FREE(frame);
2393
0
  return NT_STATUS_OK;
2394
0
}
2395
2396
NTSTATUS dsdb_trust_search_tdo_by_sid(struct ldb_context *sam_ctx,
2397
              const struct dom_sid *sid,
2398
              const char * const *attrs,
2399
              TALLOC_CTX *mem_ctx,
2400
              struct ldb_message **msg)
2401
0
{
2402
0
  TALLOC_CTX *frame = talloc_stackframe();
2403
0
  int ret;
2404
0
  struct ldb_dn *system_dn = NULL;
2405
0
  char *encoded_sid = NULL;
2406
0
  char *filter = NULL;
2407
2408
0
  *msg = NULL;
2409
2410
0
  if (sid == NULL) {
2411
0
    TALLOC_FREE(frame);
2412
0
    return NT_STATUS_INVALID_PARAMETER_MIX;
2413
0
  }
2414
2415
0
  encoded_sid = ldap_encode_ndr_dom_sid(frame, sid);
2416
0
  if (encoded_sid == NULL) {
2417
0
    TALLOC_FREE(frame);
2418
0
    return NT_STATUS_NO_MEMORY;
2419
0
  }
2420
2421
0
  system_dn = samdb_system_container_dn(sam_ctx, frame);
2422
0
  if (system_dn == NULL) {
2423
0
    TALLOC_FREE(frame);
2424
0
    return NT_STATUS_NO_MEMORY;
2425
0
  }
2426
2427
0
  filter = talloc_asprintf(frame,
2428
0
        "(&"
2429
0
          "(objectClass=trustedDomain)"
2430
0
          "(securityIdentifier=%s)"
2431
0
        ")",
2432
0
        encoded_sid);
2433
0
  if (filter == NULL) {
2434
0
    TALLOC_FREE(frame);
2435
0
    return NT_STATUS_NO_MEMORY;
2436
0
  }
2437
2438
0
  ret = dsdb_search_one(sam_ctx, mem_ctx, msg,
2439
0
            system_dn,
2440
0
            LDB_SCOPE_ONELEVEL, attrs,
2441
0
            DSDB_SEARCH_NO_GLOBAL_CATALOG,
2442
0
            "%s", filter);
2443
0
  if (ret != LDB_SUCCESS) {
2444
0
    NTSTATUS status = dsdb_ldb_err_to_ntstatus(ret);
2445
0
    DEBUG(3, ("Failed to search for %s: %s - %s\n",
2446
0
        filter, nt_errstr(status), ldb_errstring(sam_ctx)));
2447
0
    TALLOC_FREE(frame);
2448
0
    return status;
2449
0
  }
2450
2451
0
  TALLOC_FREE(frame);
2452
0
  return NT_STATUS_OK;
2453
0
}
2454
2455
NTSTATUS dsdb_trust_get_incoming_passwords(const struct ldb_message *msg,
2456
             TALLOC_CTX *mem_ctx,
2457
             struct samr_Password **_current,
2458
             struct samr_Password **_previous)
2459
0
{
2460
0
  TALLOC_CTX *frame = talloc_stackframe();
2461
0
  struct samr_Password __current = {
2462
0
    .hash = {0},
2463
0
  };
2464
0
  struct samr_Password __previous = {
2465
0
    .hash = {0},
2466
0
  };
2467
0
  struct samr_Password *current = NULL;
2468
0
  struct samr_Password *previous = NULL;
2469
0
  const struct ldb_val *blob = NULL;
2470
0
  enum ndr_err_code ndr_err;
2471
0
  struct trustAuthInOutBlob incoming = {
2472
0
    .count = 0,
2473
0
  };
2474
0
  uint32_t i;
2475
2476
0
  if (_current != NULL) {
2477
0
    *_current = NULL;
2478
0
  }
2479
0
  if (_previous != NULL) {
2480
0
    *_previous = NULL;
2481
0
  }
2482
2483
0
  blob = ldb_msg_find_ldb_val(msg, "trustAuthIncoming");
2484
0
  if (blob == NULL) {
2485
0
    TALLOC_FREE(frame);
2486
0
    return NT_STATUS_ACCOUNT_DISABLED;
2487
0
  }
2488
2489
  /* ldb_val is equivalent to DATA_BLOB */
2490
0
  ndr_err = ndr_pull_struct_blob_all(blob, frame, &incoming,
2491
0
        (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2492
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2493
0
    TALLOC_FREE(frame);
2494
0
    return NT_STATUS_INTERNAL_DB_CORRUPTION;
2495
0
  }
2496
2497
0
  for (i = 0; i < incoming.current.count; i++) {
2498
0
    struct AuthenticationInformation *a =
2499
0
      &incoming.current.array[i];
2500
2501
0
    if (current != NULL) {
2502
0
      break;
2503
0
    }
2504
2505
0
    switch (a->AuthType) {
2506
0
    case TRUST_AUTH_TYPE_NONE:
2507
0
    case TRUST_AUTH_TYPE_VERSION:
2508
0
      break;
2509
0
    case TRUST_AUTH_TYPE_NT4OWF:
2510
0
      current = &a->AuthInfo.nt4owf.password;
2511
0
      break;
2512
0
    case TRUST_AUTH_TYPE_CLEAR:
2513
0
      mdfour(__current.hash,
2514
0
             a->AuthInfo.clear.password,
2515
0
             a->AuthInfo.clear.size);
2516
0
      current = &__current;
2517
0
      break;
2518
0
    }
2519
0
  }
2520
2521
0
  if (current == NULL) {
2522
0
    TALLOC_FREE(frame);
2523
0
    return NT_STATUS_INTERNAL_DB_CORRUPTION;
2524
0
  }
2525
2526
0
  for (i = 0; i < incoming.previous.count; i++) {
2527
0
    struct AuthenticationInformation *a =
2528
0
      &incoming.previous.array[i];
2529
2530
0
    if (previous != NULL) {
2531
0
      break;
2532
0
    }
2533
2534
0
    switch (a->AuthType) {
2535
0
    case TRUST_AUTH_TYPE_NONE:
2536
0
    case TRUST_AUTH_TYPE_VERSION:
2537
0
      break;
2538
0
    case TRUST_AUTH_TYPE_NT4OWF:
2539
0
      previous = &a->AuthInfo.nt4owf.password;
2540
0
      break;
2541
0
    case TRUST_AUTH_TYPE_CLEAR:
2542
0
      mdfour(__previous.hash,
2543
0
             a->AuthInfo.clear.password,
2544
0
             a->AuthInfo.clear.size);
2545
0
      previous = &__previous;
2546
0
      break;
2547
0
    }
2548
0
  }
2549
2550
0
  if (previous == NULL) {
2551
0
    previous = current;
2552
0
  }
2553
2554
0
  if (_current != NULL) {
2555
0
    *_current = talloc_memdup(mem_ctx, current, sizeof(*current));
2556
0
    if (*_current == NULL) {
2557
0
      TALLOC_FREE(frame);
2558
0
      return NT_STATUS_NO_MEMORY;
2559
0
    }
2560
0
  }
2561
0
  if (_previous != NULL) {
2562
0
    *_previous =
2563
0
      talloc_memdup(mem_ctx, previous, sizeof(*previous));
2564
0
    if (*_previous == NULL) {
2565
0
      if (_current != NULL) {
2566
0
        TALLOC_FREE(*_current);
2567
0
      }
2568
0
      TALLOC_FREE(frame);
2569
0
      return NT_STATUS_NO_MEMORY;
2570
0
    }
2571
0
  }
2572
0
  ZERO_STRUCTP(current);
2573
0
  ZERO_STRUCTP(previous);
2574
0
  TALLOC_FREE(frame);
2575
0
  return NT_STATUS_OK;
2576
0
}
2577
2578
NTSTATUS dsdb_trust_search_tdos(struct ldb_context *sam_ctx,
2579
        const char *exclude,
2580
        const char * const *attrs,
2581
        TALLOC_CTX *mem_ctx,
2582
        struct ldb_result **res)
2583
0
{
2584
0
  TALLOC_CTX *frame = talloc_stackframe();
2585
0
  int ret;
2586
0
  struct ldb_dn *system_dn = NULL;
2587
0
  const char *filter = NULL;
2588
0
  char *exclude_encoded = NULL;
2589
2590
0
  *res = NULL;
2591
2592
0
  system_dn = samdb_system_container_dn(sam_ctx, frame);
2593
0
  if (system_dn == NULL) {
2594
0
    TALLOC_FREE(frame);
2595
0
    return NT_STATUS_NO_MEMORY;
2596
0
  }
2597
2598
0
  if (exclude != NULL) {
2599
0
    exclude_encoded = ldb_binary_encode_string(frame, exclude);
2600
0
    if (exclude_encoded == NULL) {
2601
0
      TALLOC_FREE(frame);
2602
0
      return NT_STATUS_NO_MEMORY;
2603
0
    }
2604
2605
0
    filter = talloc_asprintf(frame,
2606
0
        "(&(objectClass=trustedDomain)"
2607
0
          "(!(|(trustPartner=%s)(flatName=%s)))"
2608
0
        ")",
2609
0
        exclude_encoded, exclude_encoded);
2610
0
    if (filter == NULL) {
2611
0
      TALLOC_FREE(frame);
2612
0
      return NT_STATUS_NO_MEMORY;
2613
0
    }
2614
0
  } else {
2615
0
    filter = "(objectClass=trustedDomain)";
2616
0
  }
2617
2618
0
  ret = dsdb_search(sam_ctx, mem_ctx, res,
2619
0
        system_dn,
2620
0
        LDB_SCOPE_ONELEVEL, attrs,
2621
0
        DSDB_SEARCH_NO_GLOBAL_CATALOG,
2622
0
        "%s", filter);
2623
0
  if (ret != LDB_SUCCESS) {
2624
0
    NTSTATUS status = dsdb_ldb_err_to_ntstatus(ret);
2625
0
    DEBUG(3, ("Failed to search for %s: %s - %s\n",
2626
0
        filter, nt_errstr(status), ldb_errstring(sam_ctx)));
2627
0
    TALLOC_FREE(frame);
2628
0
    return status;
2629
0
  }
2630
2631
0
  TALLOC_FREE(frame);
2632
0
  return NT_STATUS_OK;
2633
0
}
2634
2635
struct dsdb_trust_routing_domain;
2636
2637
struct dsdb_trust_routing_table {
2638
  struct dsdb_trust_routing_domain *domains;
2639
};
2640
2641
struct dsdb_trust_routing_domain {
2642
  struct dsdb_trust_routing_domain *prev, *next;
2643
2644
  struct lsa_TrustDomainInfoInfoEx *tdo;
2645
2646
  struct lsa_ForestTrustDomainInfo di;
2647
2648
  struct lsa_ForestTrustInformation2 *fti;
2649
};
2650
2651
NTSTATUS dsdb_trust_routing_table_load(struct ldb_context *sam_ctx,
2652
               TALLOC_CTX *mem_ctx,
2653
               struct dsdb_trust_routing_table **_table)
2654
0
{
2655
0
  TALLOC_CTX *frame = talloc_stackframe();
2656
0
  struct dsdb_trust_routing_table *table;
2657
0
  struct dsdb_trust_routing_domain *d = NULL;
2658
0
  struct ldb_dn *domain_dn = NULL;
2659
0
  struct lsa_TrustDomainInfoInfoEx *root_trust_tdo = NULL;
2660
0
  struct lsa_TrustDomainInfoInfoEx *trust_parent_tdo = NULL;
2661
0
  struct lsa_TrustDomainInfoInfoEx *root_direction_tdo = NULL;
2662
0
  const char * const trusts_attrs[] = {
2663
0
    "securityIdentifier",
2664
0
    "flatName",
2665
0
    "trustPartner",
2666
0
    "trustAttributes",
2667
0
    "trustDirection",
2668
0
    "trustType",
2669
0
    "msDS-TrustForestTrustInfo",
2670
0
    NULL
2671
0
  };
2672
0
  struct ldb_result *trusts_res = NULL;
2673
0
  unsigned int i;
2674
0
  NTSTATUS status;
2675
2676
0
  *_table = NULL;
2677
2678
0
  domain_dn = ldb_get_default_basedn(sam_ctx);
2679
0
  if (domain_dn == NULL) {
2680
0
    TALLOC_FREE(frame);
2681
0
    return NT_STATUS_INTERNAL_ERROR;
2682
0
  }
2683
2684
0
  table = talloc_zero(mem_ctx, struct dsdb_trust_routing_table);
2685
0
  if (table == NULL) {
2686
0
    TALLOC_FREE(frame);
2687
0
    return NT_STATUS_NO_MEMORY;
2688
0
  }
2689
0
  talloc_steal(frame, table);
2690
2691
0
  d = talloc_zero(table, struct dsdb_trust_routing_domain);
2692
0
  if (d == NULL) {
2693
0
    TALLOC_FREE(frame);
2694
0
    return NT_STATUS_NO_MEMORY;
2695
0
  }
2696
2697
0
  status = dsdb_trust_crossref_tdo_info(d, sam_ctx,
2698
0
                domain_dn, NULL,
2699
0
                &d->tdo,
2700
0
                &root_trust_tdo,
2701
0
                &trust_parent_tdo);
2702
0
  if (!NT_STATUS_IS_OK(status)) {
2703
0
    TALLOC_FREE(frame);
2704
0
    return status;
2705
0
  }
2706
2707
  /*
2708
   * d->tdo should not be NULL of status above is 'NT_STATUS_OK'
2709
   * check is needed to satisfy clang static checker
2710
  */
2711
0
  if (d->tdo == NULL) {
2712
0
    TALLOC_FREE(frame);
2713
0
    return NT_STATUS_NO_MEMORY;
2714
0
  }
2715
0
  d->di.domain_sid = d->tdo->sid;
2716
0
  d->di.netbios_domain_name.string = d->tdo->netbios_name.string;
2717
0
  d->di.dns_domain_name.string = d->tdo->domain_name.string;
2718
2719
0
  if (root_trust_tdo != NULL) {
2720
0
    root_direction_tdo = root_trust_tdo;
2721
0
  } else if (trust_parent_tdo != NULL) {
2722
0
    root_direction_tdo = trust_parent_tdo;
2723
0
  }
2724
2725
0
  if (root_direction_tdo == NULL) {
2726
    /* we're the forest root */
2727
0
    status = dsdb_trust_xref_forest_info(d, sam_ctx, &d->fti);
2728
0
    if (!NT_STATUS_IS_OK(status)) {
2729
0
      TALLOC_FREE(frame);
2730
0
      return status;
2731
0
    }
2732
0
  }
2733
2734
0
  DLIST_ADD(table->domains, d);
2735
2736
0
  status = dsdb_trust_search_tdos(sam_ctx, NULL, trusts_attrs,
2737
0
          frame, &trusts_res);
2738
0
  if (!NT_STATUS_IS_OK(status)) {
2739
0
    TALLOC_FREE(frame);
2740
0
    return status;
2741
0
  }
2742
2743
0
  for (i = 0; i < trusts_res->count; i++) {
2744
0
    bool ok;
2745
0
    int cmp;
2746
2747
0
    d = talloc_zero(table, struct dsdb_trust_routing_domain);
2748
0
    if (d == NULL) {
2749
0
      TALLOC_FREE(frame);
2750
0
      return NT_STATUS_NO_MEMORY;
2751
0
    }
2752
2753
0
    status = dsdb_trust_parse_tdo_info(d,
2754
0
               trusts_res->msgs[i],
2755
0
               &d->tdo);
2756
0
    if (!NT_STATUS_IS_OK(status)) {
2757
0
      TALLOC_FREE(frame);
2758
0
      return status;
2759
0
    }
2760
2761
0
    d->di.domain_sid = d->tdo->sid;
2762
0
    d->di.netbios_domain_name.string = d->tdo->netbios_name.string;
2763
0
    d->di.dns_domain_name.string = d->tdo->domain_name.string;
2764
2765
0
    DLIST_ADD_END(table->domains, d);
2766
2767
0
    if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
2768
0
      struct ForestTrustInfo *fti = NULL;
2769
2770
0
      status = dsdb_trust_parse_forest_info(frame,
2771
0
                    trusts_res->msgs[i],
2772
0
                    &fti);
2773
0
      if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
2774
0
        fti = NULL;
2775
0
        status = NT_STATUS_OK;
2776
0
      }
2777
0
      if (!NT_STATUS_IS_OK(status)) {
2778
0
        TALLOC_FREE(frame);
2779
0
        return status;
2780
0
      }
2781
2782
0
      if (fti == NULL) {
2783
0
        continue;
2784
0
      }
2785
2786
0
      status = trust_forest_info_to_lsa2(d, fti, &d->fti);
2787
0
      if (!NT_STATUS_IS_OK(status)) {
2788
0
        TALLOC_FREE(frame);
2789
0
        return status;
2790
0
      }
2791
2792
0
      continue;
2793
0
    }
2794
2795
0
    if (!(d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST)) {
2796
0
      continue;
2797
0
    }
2798
2799
0
    if (root_direction_tdo == NULL) {
2800
0
      continue;
2801
0
    }
2802
2803
0
    ok = dom_sid_equal(root_direction_tdo->sid, d->tdo->sid);
2804
0
    if (!ok) {
2805
0
      continue;
2806
0
    }
2807
2808
0
    cmp = strcasecmp_m(root_direction_tdo->netbios_name.string,
2809
0
           d->tdo->netbios_name.string);
2810
0
    if (cmp != 0) {
2811
0
      continue;
2812
0
    }
2813
2814
0
    cmp = strcasecmp_m(root_direction_tdo->domain_name.string,
2815
0
           d->tdo->domain_name.string);
2816
0
    if (cmp != 0) {
2817
0
      continue;
2818
0
    }
2819
2820
    /* this our route to the forest root */
2821
0
    status = dsdb_trust_xref_forest_info(d, sam_ctx, &d->fti);
2822
0
    if (!NT_STATUS_IS_OK(status)) {
2823
0
      TALLOC_FREE(frame);
2824
0
      return status;
2825
0
    }
2826
0
  }
2827
2828
0
  *_table = talloc_move(mem_ctx, &table);
2829
0
  TALLOC_FREE(frame);
2830
0
  return NT_STATUS_OK;
2831
0
}
2832
2833
static void dsdb_trust_update_best_tln(
2834
  const struct dsdb_trust_routing_domain **best_d,
2835
  const char **best_tln,
2836
  const struct dsdb_trust_routing_domain *d,
2837
  const char *tln)
2838
0
{
2839
0
  int cmp;
2840
2841
0
  if (*best_tln == NULL) {
2842
0
    *best_tln = tln;
2843
0
    *best_d = d;
2844
0
    return;
2845
0
  }
2846
2847
0
  cmp = dns_cmp(tln, *best_tln);
2848
0
  if (cmp != DNS_CMP_FIRST_IS_CHILD) {
2849
0
    return;
2850
0
  }
2851
2852
0
  *best_tln = tln;
2853
0
  *best_d = d;
2854
0
}
2855
2856
const struct lsa_TrustDomainInfoInfoEx *dsdb_trust_routing_by_name(
2857
    const struct dsdb_trust_routing_table *table,
2858
    const char *name)
2859
0
{
2860
0
  const struct dsdb_trust_routing_domain *best_d = NULL;
2861
0
  const char *best_tln = NULL;
2862
0
  const struct dsdb_trust_routing_domain *d = NULL;
2863
2864
0
  if (name == NULL) {
2865
0
    return NULL;
2866
0
  }
2867
2868
0
  for (d = table->domains; d != NULL; d = d->next) {
2869
0
    bool transitive = false;
2870
0
    bool allow_netbios = false;
2871
0
    bool exclude = false;
2872
0
    uint32_t i;
2873
2874
0
    if (d->tdo->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
2875
      /*
2876
       * Only uplevel trusts have top level names
2877
       */
2878
0
      continue;
2879
0
    }
2880
2881
0
    if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
2882
0
      transitive = true;
2883
0
    }
2884
2885
0
    if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
2886
0
      transitive = true;
2887
0
    }
2888
2889
0
    if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE) {
2890
0
      transitive = false;
2891
0
    }
2892
2893
0
    if (d->tdo->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
2894
0
      transitive = false;
2895
0
    }
2896
2897
0
    switch (d->tdo->trust_type) {
2898
0
    case LSA_TRUST_TYPE_UPLEVEL:
2899
0
      if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_UPLEVEL_ONLY) {
2900
0
        break;
2901
0
      }
2902
0
      allow_netbios = true;
2903
0
      break;
2904
0
    case LSA_TRUST_TYPE_DOWNLEVEL:
2905
0
      allow_netbios = true;
2906
0
      break;
2907
0
    default:
2908
0
      allow_netbios = false;
2909
0
      break;
2910
0
    }
2911
2912
0
    if (!transitive || d->fti == NULL) {
2913
0
      int cmp;
2914
2915
0
      if (allow_netbios) {
2916
0
        cmp = dns_cmp(name, d->tdo->netbios_name.string);
2917
0
        if (cmp == DNS_CMP_MATCH) {
2918
          /*
2919
           * exact match
2920
           */
2921
0
          return d->tdo;
2922
0
        }
2923
0
      }
2924
2925
0
      cmp = dns_cmp(name, d->tdo->domain_name.string);
2926
0
      if (cmp == DNS_CMP_MATCH) {
2927
        /*
2928
         * exact match
2929
         */
2930
0
        return d->tdo;
2931
0
      }
2932
0
      if (cmp != DNS_CMP_FIRST_IS_CHILD) {
2933
0
        continue;
2934
0
      }
2935
2936
0
      dsdb_trust_update_best_tln(&best_d, &best_tln, d,
2937
0
               d->tdo->domain_name.string);
2938
0
      continue;
2939
0
    }
2940
2941
0
    exclude = trust_forest_info_tln_ex_match(d->fti, name);
2942
0
    if (exclude) {
2943
0
      continue;
2944
0
    }
2945
2946
0
    for (i = 0; i < d->fti->count; i++ ) {
2947
0
      const struct lsa_ForestTrustRecord2 *f = d->fti->entries[i];
2948
0
      const struct lsa_ForestTrustDomainInfo *di = NULL;
2949
0
      const char *fti_nbt = NULL;
2950
0
      int cmp;
2951
2952
0
      if (!allow_netbios) {
2953
0
        break;
2954
0
      }
2955
2956
0
      if (f == NULL) {
2957
        /* broken record */
2958
0
        continue;
2959
0
      }
2960
2961
0
      if (f->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
2962
0
        continue;
2963
0
      }
2964
2965
0
      if (f->flags & LSA_NB_DISABLED_MASK) {
2966
        /*
2967
         * any flag disables the entry.
2968
         */
2969
0
        continue;
2970
0
      }
2971
2972
0
      di = &f->forest_trust_data.domain_info;
2973
0
      fti_nbt = di->netbios_domain_name.string;
2974
0
      if (fti_nbt == NULL) {
2975
        /* broken record */
2976
0
        continue;
2977
0
      }
2978
2979
0
      cmp = dns_cmp(name, fti_nbt);
2980
0
      if (cmp == DNS_CMP_MATCH) {
2981
        /*
2982
         * exact match
2983
         */
2984
0
        return d->tdo;
2985
0
      }
2986
0
    }
2987
2988
0
    for (i = 0; i < d->fti->count; i++ ) {
2989
0
      const struct lsa_ForestTrustRecord2 *f = d->fti->entries[i];
2990
0
      const union lsa_ForestTrustData2 *u = NULL;
2991
0
      const char *fti_tln = NULL;
2992
0
      int cmp;
2993
2994
0
      if (f == NULL) {
2995
        /* broken record */
2996
0
        continue;
2997
0
      }
2998
2999
0
      if (f->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
3000
0
        continue;
3001
0
      }
3002
3003
0
      if (f->flags & LSA_TLN_DISABLED_MASK) {
3004
        /*
3005
         * any flag disables the entry.
3006
         */
3007
0
        continue;
3008
0
      }
3009
3010
0
      u = &f->forest_trust_data;
3011
0
      fti_tln = u->top_level_name.string;
3012
0
      if (fti_tln == NULL) {
3013
0
        continue;
3014
0
      }
3015
3016
0
      cmp = dns_cmp(name, fti_tln);
3017
0
      if (cmp == DNS_CMP_MATCH) {
3018
        /*
3019
         * exact match
3020
         */
3021
0
        return d->tdo;
3022
0
      }
3023
0
      if (cmp != DNS_CMP_FIRST_IS_CHILD) {
3024
0
        continue;
3025
0
      }
3026
3027
0
      dsdb_trust_update_best_tln(&best_d, &best_tln,
3028
0
               d, fti_tln);
3029
0
      continue;
3030
0
    }
3031
0
  }
3032
3033
0
  if (best_d != NULL) {
3034
0
    return best_d->tdo;
3035
0
  }
3036
3037
0
  return NULL;
3038
0
}
3039
3040
const struct lsa_TrustDomainInfoInfoEx *dsdb_trust_domain_by_sid(
3041
    const struct dsdb_trust_routing_table *table,
3042
    const struct dom_sid *sid,
3043
    const struct lsa_ForestTrustDomainInfo **pdi)
3044
0
{
3045
0
  const struct dsdb_trust_routing_domain *d = NULL;
3046
3047
0
  if (pdi != NULL) {
3048
0
    *pdi = NULL;
3049
0
  }
3050
3051
0
  if (sid == NULL) {
3052
0
    return NULL;
3053
0
  }
3054
3055
0
  for (d = table->domains; d != NULL; d = d->next) {
3056
0
    bool transitive = false;
3057
0
    uint32_t i;
3058
3059
0
    if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
3060
0
      transitive = true;
3061
0
    }
3062
3063
0
    if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
3064
0
      transitive = true;
3065
0
    }
3066
3067
0
    if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE) {
3068
0
      transitive = false;
3069
0
    }
3070
3071
0
    if (d->tdo->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
3072
0
      transitive = false;
3073
0
    }
3074
3075
0
    if (!transitive || d->fti == NULL) {
3076
0
      bool match = false;
3077
3078
0
      match = dom_sid_equal(d->di.domain_sid, sid);
3079
0
      if (match) {
3080
        /*
3081
         * exact match, it's the domain itself.
3082
         */
3083
0
        if (pdi != NULL) {
3084
0
          *pdi = &d->di;
3085
0
        }
3086
0
        return d->tdo;
3087
0
      }
3088
0
      continue;
3089
0
    }
3090
3091
0
    for (i = 0; i < d->fti->count; i++ ) {
3092
0
      const struct lsa_ForestTrustRecord2 *f = d->fti->entries[i];
3093
0
      const struct lsa_ForestTrustDomainInfo *di = NULL;
3094
0
      const struct dom_sid *fti_sid = NULL;
3095
0
      bool match = false;
3096
3097
0
      if (f == NULL) {
3098
        /* broken record */
3099
0
        continue;
3100
0
      }
3101
3102
0
      if (f->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
3103
0
        continue;
3104
0
      }
3105
3106
0
      if (f->flags & LSA_SID_DISABLED_MASK) {
3107
        /*
3108
         * any flag disables the entry.
3109
         */
3110
0
        continue;
3111
0
      }
3112
3113
0
      di = &f->forest_trust_data.domain_info;
3114
0
      fti_sid = di->domain_sid;
3115
0
      if (fti_sid == NULL) {
3116
        /* broken record */
3117
0
        continue;
3118
0
      }
3119
3120
0
      match = dom_sid_equal(fti_sid, sid);
3121
0
      if (match) {
3122
        /*
3123
         * exact match, it's a domain in the forest.
3124
         */
3125
0
        if (pdi != NULL) {
3126
0
          *pdi = di;
3127
0
        }
3128
0
        return d->tdo;
3129
0
      }
3130
0
    }
3131
0
  }
3132
3133
0
  return NULL;
3134
0
}
3135
3136
const struct lsa_TrustDomainInfoInfoEx *dsdb_trust_domain_by_name(
3137
    const struct dsdb_trust_routing_table *table,
3138
    const char *name,
3139
    const struct lsa_ForestTrustDomainInfo **pdi)
3140
0
{
3141
0
  const struct dsdb_trust_routing_domain *d = NULL;
3142
3143
0
  if (pdi != NULL) {
3144
0
    *pdi = NULL;
3145
0
  }
3146
3147
0
  if (name == NULL) {
3148
0
    return NULL;
3149
0
  }
3150
3151
0
  for (d = table->domains; d != NULL; d = d->next) {
3152
0
    bool transitive = false;
3153
0
    uint32_t i;
3154
3155
0
    if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
3156
0
      transitive = true;
3157
0
    }
3158
3159
0
    if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
3160
0
      transitive = true;
3161
0
    }
3162
3163
0
    if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE) {
3164
0
      transitive = false;
3165
0
    }
3166
3167
0
    if (d->tdo->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
3168
0
      transitive = false;
3169
0
    }
3170
3171
0
    if (!transitive || d->fti == NULL) {
3172
0
      bool match = false;
3173
3174
0
      match = strequal_m(d->di.netbios_domain_name.string,
3175
0
             name);
3176
0
      if (match) {
3177
        /*
3178
         * exact match for netbios name,
3179
         * it's the domain itself.
3180
         */
3181
0
        if (pdi != NULL) {
3182
0
          *pdi = &d->di;
3183
0
        }
3184
0
        return d->tdo;
3185
0
      }
3186
0
      match = strequal_m(d->di.dns_domain_name.string,
3187
0
             name);
3188
0
      if (match) {
3189
        /*
3190
         * exact match for dns name,
3191
         * it's the domain itself.
3192
         */
3193
0
        if (pdi != NULL) {
3194
0
          *pdi = &d->di;
3195
0
        }
3196
0
        return d->tdo;
3197
0
      }
3198
0
      continue;
3199
0
    }
3200
3201
0
    for (i = 0; i < d->fti->count; i++ ) {
3202
0
      const struct lsa_ForestTrustRecord2 *f = d->fti->entries[i];
3203
0
      const struct lsa_ForestTrustDomainInfo *di = NULL;
3204
0
      bool match = false;
3205
3206
0
      if (f == NULL) {
3207
        /* broken record */
3208
0
        continue;
3209
0
      }
3210
3211
0
      if (f->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
3212
0
        continue;
3213
0
      }
3214
0
      di = &f->forest_trust_data.domain_info;
3215
3216
0
      if (!(f->flags & LSA_NB_DISABLED_MASK)) {
3217
0
        match = strequal_m(di->netbios_domain_name.string,
3218
0
               name);
3219
0
        if (match) {
3220
          /*
3221
           * exact match for netbios name,
3222
           * it's a domain in the forest.
3223
           */
3224
0
          if (pdi != NULL) {
3225
0
            *pdi = di;
3226
0
          }
3227
0
          return d->tdo;
3228
0
        }
3229
0
      }
3230
3231
0
      if (!(f->flags & LSA_TLN_DISABLED_MASK)) {
3232
0
        match = strequal_m(di->dns_domain_name.string,
3233
0
               name);
3234
0
        if (match) {
3235
          /*
3236
           * exact match for dns name,
3237
           * it's a domain in the forest.
3238
           */
3239
0
          if (pdi != NULL) {
3240
0
            *pdi = di;
3241
0
          }
3242
0
          return d->tdo;
3243
0
        }
3244
0
      }
3245
0
    }
3246
0
  }
3247
3248
0
  return NULL;
3249
0
}
3250
3251
NTSTATUS dsdb_trust_get_claims_tf_policy(struct ldb_context *samldb,
3252
           const struct ldb_message *tdo_msg,
3253
           const char *tdo_attr,
3254
           TALLOC_CTX *mem_ctx,
3255
           struct claims_tf_rule_set **_rule_set)
3256
0
{
3257
0
  TALLOC_CTX *frame = talloc_stackframe();
3258
0
  const struct ldb_val *tdo_link_val = NULL;
3259
0
  struct ldb_dn *config_dn = NULL;
3260
0
  struct ldb_dn *claims_tf_dn = NULL;
3261
0
  struct ldb_dn *policy_dn = NULL;
3262
0
  struct ldb_message *policy_msg = NULL;
3263
0
  static const char * const policy_attrs[] = {
3264
0
    "msDS-TransformationRules",
3265
0
    NULL
3266
0
  };
3267
0
  const struct ldb_val *xml_blob = NULL;
3268
0
  DATA_BLOB rules_blob = { .length = 0, };
3269
0
  struct claims_tf_rule_set *rule_set = NULL;
3270
0
  int cmp;
3271
0
  bool ok;
3272
0
  int ret;
3273
3274
0
  *_rule_set = NULL;
3275
3276
0
  tdo_link_val = ldb_msg_find_ldb_val(tdo_msg, tdo_attr);
3277
0
  if (tdo_link_val == NULL) {
3278
0
    TALLOC_FREE(frame);
3279
0
    return NT_STATUS_DS_NO_ATTRIBUTE_OR_VALUE;
3280
0
  }
3281
3282
0
  config_dn = ldb_get_config_basedn(samldb);
3283
0
  if (config_dn == NULL) {
3284
0
    TALLOC_FREE(frame);
3285
0
    return NT_STATUS_DS_INIT_FAILURE;
3286
0
  }
3287
3288
0
  claims_tf_dn = ldb_dn_copy(frame, config_dn);
3289
0
  if (claims_tf_dn == NULL) {
3290
0
    TALLOC_FREE(frame);
3291
0
    return NT_STATUS_NO_MEMORY;
3292
0
  }
3293
3294
0
  ok = ldb_dn_add_child_fmt(claims_tf_dn,
3295
0
          "%s,%s,%s",
3296
0
          "CN=Claims Transformation Policies",
3297
0
          "CN=Claims Configuration",
3298
0
          "CN=Services");
3299
0
  if (!ok) {
3300
0
    TALLOC_FREE(frame);
3301
0
    return NT_STATUS_NO_MEMORY;
3302
0
  }
3303
3304
0
  policy_dn = ldb_msg_find_attr_as_dn(samldb, frame, tdo_msg, tdo_attr);
3305
0
  if (policy_dn == NULL) {
3306
0
    TALLOC_FREE(frame);
3307
0
    return NT_STATUS_NO_MEMORY;
3308
0
  }
3309
3310
  /*
3311
   * The policy dn needs to be a child of
3312
   * the CN=Claims Transformation Policies container
3313
   */
3314
0
  cmp = ldb_dn_compare_base(claims_tf_dn, policy_dn);
3315
0
  if (cmp != 0) {
3316
0
    TALLOC_FREE(frame);
3317
0
    return NT_STATUS_DS_OBJ_CLASS_VIOLATION;
3318
0
  }
3319
3320
0
  ret = dsdb_search_one(samldb,
3321
0
            frame,
3322
0
            &policy_msg,
3323
0
            policy_dn,
3324
0
            LDB_SCOPE_BASE,
3325
0
            policy_attrs,
3326
0
            DSDB_SEARCH_ONE_ONLY,
3327
0
            "(objectClass=msDS-ClaimsTransformationPolicyType)");
3328
0
  if (ret != LDB_SUCCESS) {
3329
0
    TALLOC_FREE(frame);
3330
0
    return NT_STATUS_POLICY_OBJECT_NOT_FOUND;
3331
0
  }
3332
3333
0
  xml_blob = ldb_msg_find_ldb_val(policy_msg, "msDS-TransformationRules");
3334
0
  if (xml_blob == NULL) {
3335
0
    TALLOC_FREE(frame);
3336
0
    return NT_STATUS_DS_NO_ATTRIBUTE_OR_VALUE;
3337
0
  }
3338
3339
0
  ok = claims_tf_policy_unwrap_xml(xml_blob,
3340
0
           &rules_blob);
3341
0
  if (!ok) {
3342
0
    TALLOC_FREE(frame);
3343
0
    return NT_STATUS_DS_INVALID_ATTRIBUTE_SYNTAX;
3344
0
  }
3345
3346
0
  ok = claims_tf_rule_set_parse_blob(&rules_blob,
3347
0
             frame,
3348
0
             &rule_set,
3349
0
             NULL); /* _error_string */
3350
0
  if (!ok) {
3351
0
    TALLOC_FREE(frame);
3352
0
    return NT_STATUS_DS_INVALID_ATTRIBUTE_SYNTAX;
3353
0
  }
3354
3355
0
  *_rule_set = talloc_move(mem_ctx, &rule_set);
3356
0
  TALLOC_FREE(frame);
3357
0
  return NT_STATUS_OK;
3358
0
}