LCOV - code coverage report
Current view: top level - source4/dsdb/common - util_trusts.c (source / functions) Hit Total Coverage
Test: coverage report for master 6248eab5 Lines: 1112 1797 61.9 %
Date: 2021-08-25 13:27:56 Functions: 29 32 90.6 %

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

Generated by: LCOV version 1.13