LCOV - code coverage report
Current view: top level - source4/dsdb/common - util_trusts.c (source / functions) Hit Total Coverage
Test: coverage report for vadcx-master-patch-75612 fe003de8 Lines: 1142 1870 61.1 %
Date: 2024-02-29 22:57:05 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          79 : NTSTATUS dsdb_trust_forest_info_from_lsa(TALLOC_CTX *mem_ctx,
      41             :                                 const struct lsa_ForestTrustInformation *lfti,
      42             :                                 struct ForestTrustInfo **_fti)
      43             : {
      44           0 :         struct ForestTrustInfo *fti;
      45           0 :         uint32_t i;
      46             : 
      47          79 :         *_fti = NULL;
      48             : 
      49          79 :         fti = talloc_zero(mem_ctx, struct ForestTrustInfo);
      50          79 :         if (fti == NULL) {
      51           0 :                 return NT_STATUS_NO_MEMORY;
      52             :         }
      53             : 
      54          79 :         fti->version = 1;
      55          79 :         fti->count = lfti->count;
      56          79 :         fti->records = talloc_zero_array(mem_ctx,
      57             :                                          struct ForestTrustInfoRecordArmor,
      58             :                                          fti->count);
      59          79 :         if (fti->records == NULL) {
      60           0 :                 TALLOC_FREE(fti);
      61           0 :                 return NT_STATUS_NO_MEMORY;
      62             :         }
      63             : 
      64         561 :         for (i = 0; i < fti->count; i++) {
      65         482 :                 const struct lsa_ForestTrustRecord *lftr = lfti->entries[i];
      66         482 :                 struct ForestTrustInfoRecord *ftr = &fti->records[i].record;
      67         482 :                 struct ForestTrustString *str = NULL;
      68         482 :                 const struct lsa_StringLarge *lstr = NULL;
      69         482 :                 const struct lsa_ForestTrustDomainInfo *linfo = NULL;
      70         482 :                 struct ForestTrustDataDomainInfo *info = NULL;
      71             : 
      72         482 :                 if (lftr == NULL) {
      73           0 :                         TALLOC_FREE(fti);
      74           0 :                         return NT_STATUS_INVALID_PARAMETER;
      75             :                 }
      76             : 
      77         482 :                 ftr->flags = lftr->flags;
      78         482 :                 ftr->timestamp = lftr->time;
      79         482 :                 ftr->type = (enum ForestTrustInfoRecordType)lftr->type;
      80             : 
      81         482 :                 switch (lftr->type) {
      82         387 :                 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
      83         387 :                         lstr = &lftr->forest_trust_data.top_level_name;
      84         387 :                         str = &ftr->data.name;
      85             : 
      86         387 :                         str->string = talloc_strdup(mem_ctx, lstr->string);
      87         387 :                         if (str->string == NULL) {
      88           0 :                                 TALLOC_FREE(fti);
      89           0 :                                 return NT_STATUS_NO_MEMORY;
      90             :                         }
      91             : 
      92         482 :                         break;
      93             : 
      94          16 :                 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
      95          16 :                         lstr = &lftr->forest_trust_data.top_level_name_ex;
      96          16 :                         str = &ftr->data.name;
      97             : 
      98          16 :                         str->string = talloc_strdup(mem_ctx, lstr->string);
      99          16 :                         if (str->string == NULL) {
     100           0 :                                 TALLOC_FREE(fti);
     101           0 :                                 return NT_STATUS_NO_MEMORY;
     102             :                         }
     103             : 
     104          16 :                         break;
     105             : 
     106          79 :                 case LSA_FOREST_TRUST_DOMAIN_INFO:
     107          79 :                         linfo = &lftr->forest_trust_data.domain_info;
     108          79 :                         info = &ftr->data.info;
     109             : 
     110          79 :                         if (linfo->domain_sid == NULL) {
     111           0 :                                 TALLOC_FREE(fti);
     112           0 :                                 return NT_STATUS_INVALID_PARAMETER;
     113             :                         }
     114          79 :                         info->sid = *linfo->domain_sid;
     115             : 
     116          79 :                         lstr = &linfo->dns_domain_name;
     117          79 :                         str = &info->dns_name;
     118          79 :                         str->string = talloc_strdup(mem_ctx, lstr->string);
     119          79 :                         if (str->string == NULL) {
     120           0 :                                 TALLOC_FREE(fti);
     121           0 :                                 return NT_STATUS_NO_MEMORY;
     122             :                         }
     123             : 
     124          79 :                         lstr = &linfo->netbios_domain_name;
     125          79 :                         str = &info->netbios_name;
     126          79 :                         str->string = talloc_strdup(mem_ctx, lstr->string);
     127          79 :                         if (str->string == NULL) {
     128           0 :                                 TALLOC_FREE(fti);
     129           0 :                                 return NT_STATUS_NO_MEMORY;
     130             :                         }
     131             : 
     132          79 :                         break;
     133             : 
     134           0 :                 default:
     135           0 :                         return NT_STATUS_NOT_SUPPORTED;
     136             :                 }
     137             :         }
     138             : 
     139          79 :         *_fti = fti;
     140          79 :         return NT_STATUS_OK;
     141             : }
     142             : 
     143        8022 : static NTSTATUS dsdb_trust_forest_record_to_lsa(TALLOC_CTX *mem_ctx,
     144             :                                          const struct ForestTrustInfoRecord *ftr,
     145             :                                          struct lsa_ForestTrustRecord **_lftr)
     146             : {
     147        8022 :         struct lsa_ForestTrustRecord *lftr = NULL;
     148        8022 :         const struct ForestTrustString *str = NULL;
     149        8022 :         struct lsa_StringLarge *lstr = NULL;
     150        8022 :         const struct ForestTrustDataDomainInfo *info = NULL;
     151        8022 :         struct lsa_ForestTrustDomainInfo *linfo = NULL;
     152             : 
     153        8022 :         *_lftr = NULL;
     154             : 
     155        8022 :         lftr = talloc_zero(mem_ctx, struct lsa_ForestTrustRecord);
     156        8022 :         if (lftr == NULL) {
     157           0 :                 return NT_STATUS_NO_MEMORY;
     158             :         }
     159             : 
     160        8022 :         lftr->flags = ftr->flags;
     161        8022 :         lftr->time = ftr->timestamp;
     162        8022 :         lftr->type = (enum lsa_ForestTrustRecordType)ftr->type;
     163             : 
     164        8022 :         switch (lftr->type) {
     165        6087 :         case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
     166        6087 :                 lstr = &lftr->forest_trust_data.top_level_name;
     167        6087 :                 str = &ftr->data.name;
     168             : 
     169        6087 :                 lstr->string = talloc_strdup(mem_ctx, str->string);
     170        6087 :                 if (lstr->string == NULL) {
     171           0 :                         TALLOC_FREE(lftr);
     172           0 :                         return NT_STATUS_NO_MEMORY;
     173             :                 }
     174             : 
     175        6087 :                 break;
     176             : 
     177          52 :         case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
     178          52 :                 lstr = &lftr->forest_trust_data.top_level_name_ex;
     179          52 :                 str = &ftr->data.name;
     180             : 
     181          52 :                 lstr->string = talloc_strdup(mem_ctx, str->string);
     182          52 :                 if (lstr->string == NULL) {
     183           0 :                         TALLOC_FREE(lftr);
     184           0 :                         return NT_STATUS_NO_MEMORY;
     185             :                 }
     186             : 
     187          52 :                 break;
     188             : 
     189        1883 :         case LSA_FOREST_TRUST_DOMAIN_INFO:
     190        1883 :                 linfo = &lftr->forest_trust_data.domain_info;
     191        1883 :                 info = &ftr->data.info;
     192             : 
     193        1883 :                 linfo->domain_sid = dom_sid_dup(lftr, &info->sid);
     194        1883 :                 if (linfo->domain_sid == NULL) {
     195           0 :                         TALLOC_FREE(lftr);
     196           0 :                         return NT_STATUS_NO_MEMORY;
     197             :                 }
     198             : 
     199        1883 :                 lstr = &linfo->dns_domain_name;
     200        1883 :                 str = &info->dns_name;
     201        1883 :                 lstr->string = talloc_strdup(mem_ctx, str->string);
     202        1883 :                 if (lstr->string == NULL) {
     203           0 :                         TALLOC_FREE(lftr);
     204           0 :                         return NT_STATUS_NO_MEMORY;
     205             :                 }
     206             : 
     207        1883 :                 lstr = &linfo->netbios_domain_name;
     208        1883 :                 str = &info->netbios_name;
     209        1883 :                 lstr->string = talloc_strdup(mem_ctx, str->string);
     210        1883 :                 if (lstr->string == NULL) {
     211           0 :                         TALLOC_FREE(lftr);
     212           0 :                         return NT_STATUS_NO_MEMORY;
     213             :                 }
     214             : 
     215        1883 :                 break;
     216             : 
     217           0 :         default:
     218           0 :                 return NT_STATUS_NOT_SUPPORTED;
     219             :         }
     220             : 
     221        8022 :         *_lftr = lftr;
     222        8022 :         return NT_STATUS_OK;
     223             : }
     224             : 
     225        1883 : NTSTATUS dsdb_trust_forest_info_to_lsa(TALLOC_CTX *mem_ctx,
     226             :                                        const struct ForestTrustInfo *fti,
     227             :                                        struct lsa_ForestTrustInformation **_lfti)
     228             : {
     229           0 :         struct lsa_ForestTrustInformation *lfti;
     230           0 :         uint32_t i;
     231             : 
     232        1883 :         *_lfti = NULL;
     233             : 
     234        1883 :         if (fti->version != 1) {
     235           0 :                 return NT_STATUS_INVALID_PARAMETER;
     236             :         }
     237             : 
     238        1883 :         lfti = talloc_zero(mem_ctx, struct lsa_ForestTrustInformation);
     239        1883 :         if (lfti == NULL) {
     240           0 :                 return NT_STATUS_NO_MEMORY;
     241             :         }
     242             : 
     243        1883 :         lfti->count = fti->count;
     244        1883 :         lfti->entries = talloc_zero_array(mem_ctx,
     245             :                                           struct lsa_ForestTrustRecord *,
     246             :                                           lfti->count);
     247        1883 :         if (lfti->entries == NULL) {
     248           0 :                 TALLOC_FREE(lfti);
     249           0 :                 return NT_STATUS_NO_MEMORY;
     250             :         }
     251             : 
     252        9905 :         for (i = 0; i < fti->count; i++) {
     253        8022 :                 struct ForestTrustInfoRecord *ftr = &fti->records[i].record;
     254        8022 :                 struct lsa_ForestTrustRecord *lftr = NULL;
     255           0 :                 NTSTATUS status;
     256             : 
     257        8022 :                 status = dsdb_trust_forest_record_to_lsa(lfti->entries, ftr,
     258             :                                                          &lftr);
     259        8022 :                 if (!NT_STATUS_IS_OK(status)) {
     260           0 :                         TALLOC_FREE(lfti);
     261           0 :                         return NT_STATUS_NO_MEMORY;
     262             :                 }
     263        8022 :                 lfti->entries[i] = lftr;
     264             :         }
     265             : 
     266        1883 :         *_lfti = lfti;
     267        1883 :         return NT_STATUS_OK;
     268             : }
     269             : 
     270       71426 : static NTSTATUS dsdb_trust_forest_info_add_record(struct lsa_ForestTrustInformation *fti,
     271             :                                                   const struct lsa_ForestTrustRecord *ftr)
     272             : {
     273       71426 :         struct lsa_ForestTrustRecord **es = NULL;
     274       71426 :         struct lsa_ForestTrustRecord *e = NULL;
     275       71426 :         const struct lsa_StringLarge *dns1 = NULL;
     276       71426 :         struct lsa_StringLarge *dns2 = NULL;
     277       71426 :         const struct lsa_ForestTrustDomainInfo *d1 = NULL;
     278       71426 :         struct lsa_ForestTrustDomainInfo *d2 = NULL;
     279       71426 :         size_t len = 0;
     280             : 
     281       71426 :         es = talloc_realloc(fti, fti->entries,
     282             :                             struct lsa_ForestTrustRecord *,
     283             :                             fti->count + 1);
     284       71426 :         if (!es) {
     285           0 :                 return NT_STATUS_NO_MEMORY;
     286             :         }
     287       71426 :         fti->entries = es;
     288             : 
     289       71426 :         e = talloc_zero(es, struct lsa_ForestTrustRecord);
     290       71426 :         if (e == NULL) {
     291           0 :                 return NT_STATUS_NO_MEMORY;
     292             :         }
     293             : 
     294       71426 :         e->type = ftr->type;
     295       71426 :         e->flags = ftr->flags;
     296       71426 :         e->time = ftr->time;
     297             : 
     298       71426 :         switch (ftr->type) {
     299       48798 :         case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
     300       48798 :                 dns1 = &ftr->forest_trust_data.top_level_name;
     301       48798 :                 dns2 = &e->forest_trust_data.top_level_name;
     302       48798 :                 break;
     303             : 
     304          32 :         case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
     305          32 :                 dns1 = &ftr->forest_trust_data.top_level_name_ex;
     306          32 :                 dns2 = &e->forest_trust_data.top_level_name_ex;
     307          32 :                 break;
     308             : 
     309       22596 :         case LSA_FOREST_TRUST_DOMAIN_INFO:
     310       22596 :                 dns1 = &ftr->forest_trust_data.domain_info.dns_domain_name;
     311       22596 :                 dns2 = &e->forest_trust_data.domain_info.dns_domain_name;
     312       22596 :                 d1 = &ftr->forest_trust_data.domain_info;
     313       22596 :                 d2 = &e->forest_trust_data.domain_info;
     314       22596 :                 break;
     315           0 :         default:
     316           0 :                 return NT_STATUS_INVALID_PARAMETER;
     317             :         }
     318             : 
     319       71426 :         if (dns1->string == NULL) {
     320           0 :                 TALLOC_FREE(e);
     321           0 :                 return NT_STATUS_INVALID_PARAMETER;
     322             :         }
     323             : 
     324       71426 :         len = strlen(dns1->string);
     325       71426 :         if (len == 0) {
     326           0 :                 TALLOC_FREE(e);
     327           0 :                 return NT_STATUS_INVALID_PARAMETER;
     328             :         }
     329             : 
     330       71426 :         dns2->string = talloc_strdup(e, dns1->string);
     331       71426 :         if (dns2->string == NULL) {
     332           0 :                 TALLOC_FREE(e);
     333           0 :                 return NT_STATUS_NO_MEMORY;
     334             :         }
     335             : 
     336       71426 :         if (d1 != NULL) {
     337       22596 :                 const struct lsa_StringLarge *nb1 = &d1->netbios_domain_name;
     338       22596 :                 struct lsa_StringLarge *nb2 = &d2->netbios_domain_name;
     339             : 
     340       22596 :                 if (nb1->string == NULL) {
     341           0 :                         TALLOC_FREE(e);
     342           0 :                         return NT_STATUS_INVALID_PARAMETER;
     343             :                 }
     344             : 
     345       22596 :                 len = strlen(nb1->string);
     346       22596 :                 if (len == 0) {
     347           0 :                         TALLOC_FREE(e);
     348           0 :                         return NT_STATUS_INVALID_PARAMETER;
     349             :                 }
     350       22596 :                 if (len > 15) {
     351           0 :                         TALLOC_FREE(e);
     352           0 :                         return NT_STATUS_INVALID_PARAMETER;
     353             :                 }
     354             : 
     355       22596 :                 nb2->string = talloc_strdup(e, nb1->string);
     356       22596 :                 if (nb2->string == NULL) {
     357           0 :                         TALLOC_FREE(e);
     358           0 :                         return NT_STATUS_NO_MEMORY;
     359             :                 }
     360             : 
     361       22596 :                 if (d1->domain_sid == NULL) {
     362           0 :                         TALLOC_FREE(e);
     363           0 :                         return NT_STATUS_INVALID_PARAMETER;
     364             :                 }
     365             : 
     366       22596 :                 d2->domain_sid = dom_sid_dup(e, d1->domain_sid);
     367       22596 :                 if (d2->domain_sid == NULL) {
     368           0 :                         TALLOC_FREE(e);
     369           0 :                         return NT_STATUS_NO_MEMORY;
     370             :                 }
     371             :         }
     372             : 
     373       71426 :         fti->entries[fti->count++] = e;
     374       71426 :         return NT_STATUS_OK;
     375             : }
     376             : 
     377       22402 : 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       22402 :         TALLOC_CTX *frame = talloc_stackframe();
     383       22402 :         struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
     384       22402 :         const char *dns = NULL;
     385       22402 :         const char *netbios = NULL;
     386       22402 :         struct ldb_dn *nc_dn = NULL;
     387       22402 :         struct dom_sid sid = {
     388             :                 .num_auths = 0,
     389             :         };
     390         644 :         NTSTATUS status;
     391             : 
     392       22402 :         *_tdo = NULL;
     393       22402 :         tdo = talloc_zero(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
     394       22402 :         if (tdo == NULL) {
     395           0 :                 TALLOC_FREE(frame);
     396           0 :                 return NT_STATUS_NO_MEMORY;
     397             :         }
     398       22402 :         talloc_steal(frame, tdo);
     399             : 
     400       22402 :         dns = ldb_msg_find_attr_as_string(msg, "dnsRoot", NULL);
     401       22402 :         if (dns == NULL) {
     402           0 :                 TALLOC_FREE(frame);
     403           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
     404             :         }
     405       22402 :         tdo->domain_name.string = talloc_strdup(tdo, dns);
     406       22402 :         if (tdo->domain_name.string == NULL) {
     407           0 :                 TALLOC_FREE(frame);
     408           0 :                 return NT_STATUS_NO_MEMORY;
     409             :         }
     410             : 
     411       22402 :         netbios = ldb_msg_find_attr_as_string(msg, "nETBIOSName", NULL);
     412       22402 :         if (netbios == NULL) {
     413           0 :                 TALLOC_FREE(frame);
     414           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
     415             :         }
     416       22402 :         tdo->netbios_name.string = talloc_strdup(tdo, netbios);
     417       22402 :         if (tdo->netbios_name.string == NULL) {
     418           0 :                 TALLOC_FREE(frame);
     419           0 :                 return NT_STATUS_NO_MEMORY;
     420             :         }
     421             : 
     422       22402 :         nc_dn = samdb_result_dn(sam_ctx, frame, msg, "ncName", NULL);
     423       22402 :         if (nc_dn == NULL) {
     424           0 :                 TALLOC_FREE(frame);
     425           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
     426             :         }
     427             : 
     428       22402 :         status = dsdb_get_extended_dn_sid(nc_dn, &sid, "SID");
     429       22402 :         if (!NT_STATUS_IS_OK(status)) {
     430           0 :                 TALLOC_FREE(frame);
     431           0 :                 return status;
     432             :         }
     433       22402 :         tdo->sid = dom_sid_dup(tdo, &sid);
     434       22402 :         if (tdo->sid == NULL) {
     435           0 :                 TALLOC_FREE(frame);
     436           0 :                 return NT_STATUS_NO_MEMORY;
     437             :         }
     438             : 
     439       22402 :         tdo->trust_type = LSA_TRUST_TYPE_UPLEVEL;
     440       22402 :         tdo->trust_direction = LSA_TRUST_DIRECTION_INBOUND |
     441             :                                LSA_TRUST_DIRECTION_OUTBOUND;
     442       22402 :         tdo->trust_attributes = LSA_TRUST_ATTRIBUTE_WITHIN_FOREST;
     443             : 
     444       22402 :         *_tdo = talloc_move(mem_ctx, &tdo);
     445       22402 :         TALLOC_FREE(frame);
     446       22402 :         return NT_STATUS_OK;
     447             : }
     448             : 
     449       22402 : 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       22402 :         TALLOC_CTX *frame = talloc_stackframe();
     458       22402 :         struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
     459       22402 :         struct lsa_TrustDomainInfoInfoEx *root_trust_tdo = NULL;
     460       22402 :         struct lsa_TrustDomainInfoInfoEx *trust_parent_tdo = NULL;
     461       22402 :         struct ldb_dn *partitions_dn = NULL;
     462       22402 :         const char * const cross_attrs[] = {
     463             :                 "dnsRoot",
     464             :                 "nETBIOSName",
     465             :                 "nCName",
     466             :                 "rootTrust",
     467             :                 "trustParent",
     468             :                 NULL,
     469             :         };
     470       22402 :         struct ldb_result *cross_res = NULL;
     471       22402 :         struct ldb_message *msg = NULL;
     472       22402 :         struct ldb_dn *root_trust_dn = NULL;
     473       22402 :         struct ldb_dn *trust_parent_dn = NULL;
     474         644 :         NTSTATUS status;
     475         644 :         int ret;
     476             : 
     477       22402 :         if (extra_filter == NULL) {
     478       22315 :                 extra_filter = "";
     479             :         }
     480             : 
     481       22402 :         *_tdo = NULL;
     482       22402 :         if (_root_trust_tdo != NULL) {
     483       22168 :                 *_root_trust_tdo = NULL;
     484             :         }
     485       22402 :         if (_trust_parent_tdo != NULL) {
     486       22168 :                 *_trust_parent_tdo = NULL;
     487             :         }
     488             : 
     489       22402 :         partitions_dn = samdb_partitions_dn(sam_ctx, frame);
     490       22402 :         if (partitions_dn == NULL) {
     491           0 :                 TALLOC_FREE(frame);
     492           0 :                 return NT_STATUS_NO_MEMORY;
     493             :         }
     494             : 
     495       22402 :         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       22402 :         if (ret != LDB_SUCCESS) {
     511           0 :                 TALLOC_FREE(frame);
     512           0 :                 return dsdb_ldb_err_to_ntstatus(ret);
     513             :         }
     514       22402 :         msg = cross_res->msgs[0];
     515             : 
     516       22402 :         status = dsdb_trust_parse_crossref_info(mem_ctx, sam_ctx, msg, &tdo);
     517       22402 :         if (!NT_STATUS_IS_OK(status)) {
     518           0 :                 TALLOC_FREE(frame);
     519           0 :                 return status;
     520             :         }
     521       22402 :         talloc_steal(frame, tdo);
     522             : 
     523       22402 :         if (_root_trust_tdo != NULL) {
     524       22168 :                 root_trust_dn = samdb_result_dn(sam_ctx, frame, msg,
     525             :                                                 "rootTrust", NULL);
     526             :         }
     527       22402 :         if (_trust_parent_tdo != NULL) {
     528       22168 :                 trust_parent_dn = samdb_result_dn(sam_ctx, frame, msg,
     529             :                                                    "trustParent", NULL);
     530             :         }
     531             : 
     532       22402 :         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       22402 :         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       22402 :         *_tdo = talloc_move(mem_ctx, &tdo);
     591       22402 :         if (_root_trust_tdo != NULL) {
     592       22168 :                 *_root_trust_tdo = talloc_move(mem_ctx, &root_trust_tdo);
     593             :         }
     594       22402 :         if (_trust_parent_tdo != NULL) {
     595       22168 :                 *_trust_parent_tdo = talloc_move(mem_ctx, &trust_parent_tdo);
     596             :         }
     597       22402 :         TALLOC_FREE(frame);
     598       22402 :         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      183953 : static int dns_cmp(const char *s1, const char *s2)
     624             : {
     625      183953 :         size_t l1 = 0;
     626      183953 :         const char *p1 = NULL;
     627      183953 :         size_t num_comp1 = 0;
     628      183953 :         uint16_t comp1[UINT8_MAX] = {0};
     629      183953 :         size_t l2 = 0;
     630      183953 :         const char *p2 = NULL;
     631      183953 :         size_t num_comp2 = 0;
     632      183953 :         uint16_t comp2[UINT8_MAX] = {0};
     633        6870 :         size_t i;
     634             : 
     635      183953 :         if (s1 != NULL) {
     636      183953 :                 l1 = strlen(s1);
     637             :         }
     638             : 
     639      183953 :         if (s2 != NULL) {
     640      183953 :                 l2 = strlen(s2);
     641             :         }
     642             : 
     643             :         /*
     644             :          * trailing '.' are ignored.
     645             :          */
     646      183953 :         if (l1 > 1 && s1[l1 - 1] == '.') {
     647           0 :                 l1--;
     648             :         }
     649      183953 :         if (l2 > 1 && s2[l2 - 1] == '.') {
     650           0 :                 l2--;
     651             :         }
     652             : 
     653      586847 :         for (i = 0; i < ARRAY_SIZE(comp1); i++) {
     654       23146 :                 char *p;
     655             : 
     656      586847 :                 if (i == 0) {
     657      183953 :                         p1 = s1;
     658             : 
     659      183953 :                         if (l1 == 0 || l1 >= UINT16_MAX) {
     660             :                                 /* just use one single component on overflow */
     661             :                                 break;
     662             :                         }
     663             :                 }
     664             : 
     665      586847 :                 comp1[num_comp1++] = PTR_DIFF(p1, s1);
     666             : 
     667      586847 :                 p = strchr_m(p1, '.');
     668      586847 :                 if (p == NULL) {
     669      177083 :                         p1 = NULL;
     670      177083 :                         break;
     671             :                 }
     672             : 
     673      402894 :                 p1 = p + 1;
     674             :         }
     675             : 
     676      183953 :         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      722982 :         for (i = 0; i < ARRAY_SIZE(comp2); i++) {
     684       29983 :                 char *p;
     685             : 
     686      722982 :                 if (i == 0) {
     687      183953 :                         p2 = s2;
     688             : 
     689      183953 :                         if (l2 == 0 || l2 >= UINT16_MAX) {
     690             :                                 /* just use one single component on overflow */
     691             :                                 break;
     692             :                         }
     693             :                 }
     694             : 
     695      722982 :                 comp2[num_comp2++] = PTR_DIFF(p2, s2);
     696             : 
     697      722982 :                 p = strchr_m(p2, '.');
     698      722982 :                 if (p == NULL) {
     699      177083 :                         p2 = NULL;
     700      177083 :                         break;
     701             :                 }
     702             : 
     703      539029 :                 p2 = p + 1;
     704             :         }
     705             : 
     706      183953 :         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      216850 :         for (i = 0; i < UINT8_MAX; i++) {
     714        6870 :                 int cmp;
     715             : 
     716      216850 :                 if (i < num_comp1) {
     717      215617 :                         size_t idx = num_comp1 - (i + 1);
     718      215617 :                         p1 = s1 + comp1[idx];
     719             :                 } else {
     720        1233 :                         p1 = NULL;
     721             :                 }
     722             : 
     723      216850 :                 if (i < num_comp2) {
     724      213621 :                         size_t idx = num_comp2 - (i + 1);
     725      213621 :                         p2 = s2 + comp2[idx];
     726             :                 } else {
     727        3229 :                         p2 = NULL;
     728             :                 }
     729             : 
     730      216850 :                 if (p1 == NULL && p2 == NULL) {
     731        1233 :                         return DNS_CMP_MATCH;
     732             :                 }
     733      215617 :                 if (p1 != NULL && p2 == NULL) {
     734        1996 :                         return DNS_CMP_FIRST_IS_CHILD;
     735             :                 }
     736      213621 :                 if (p1 == NULL && p2 != NULL) {
     737           0 :                         return DNS_CMP_SECOND_IS_CHILD;
     738             :                 }
     739             : 
     740      213621 :                 cmp = strcasecmp_m(p1, p2);
     741      213621 :                 if (cmp < 0) {
     742       99042 :                         return DNS_CMP_FIRST_IS_LESS;
     743             :                 }
     744      110213 :                 if (cmp > 0) {
     745       74812 :                         return DNS_CMP_SECOND_IS_LESS;
     746             :                 }
     747             :         }
     748             : 
     749           0 :         smb_panic(__location__);
     750             :         return -1;
     751             : }
     752             : 
     753       71568 : 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        2505 :         uint32_t i;
     759             : 
     760      213574 :         for (i = 0; i < info->count; i++) {
     761      142058 :                 struct lsa_ForestTrustRecord *e = info->entries[i];
     762      142058 :                 struct lsa_StringLarge *t = NULL;
     763        5618 :                 int cmp;
     764             : 
     765      142058 :                 if (e == NULL) {
     766           0 :                         continue;
     767             :                 }
     768             : 
     769      142058 :                 if (e->type != type) {
     770      101283 :                         continue;
     771             :                 }
     772             : 
     773       40775 :                 if (e->flags & disable_mask) {
     774           0 :                         continue;
     775             :                 }
     776             : 
     777       40775 :                 switch (type) {
     778       40763 :                 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
     779       40763 :                         t = &e->forest_trust_data.top_level_name;
     780       40763 :                         break;
     781          12 :                 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
     782          12 :                         t = &e->forest_trust_data.top_level_name_ex;
     783          12 :                         break;
     784           0 :                 default:
     785           0 :                         break;
     786             :                 }
     787             : 
     788       40775 :                 if (t == NULL) {
     789           0 :                         continue;
     790             :                 }
     791             : 
     792       40775 :                 cmp = dns_cmp(tln, t->string);
     793       40775 :                 switch (cmp) {
     794          52 :                 case DNS_CMP_MATCH:
     795             :                 case DNS_CMP_FIRST_IS_CHILD:
     796          52 :                         return i;
     797             :                 }
     798             :         }
     799             : 
     800       69011 :         return -1;
     801             : }
     802             : 
     803       48063 : static bool dsdb_trust_find_tln_match(const struct lsa_ForestTrustInformation *info,
     804             :                                       const char *tln)
     805             : {
     806        1882 :         int m;
     807             : 
     808       49945 :         m = dsdb_trust_find_tln_match_internal(info,
     809             :                                                LSA_FOREST_TRUST_TOP_LEVEL_NAME,
     810             :                                                LSA_TLN_DISABLED_MASK,
     811             :                                                tln);
     812       48063 :         if (m != -1) {
     813          52 :                 return true;
     814             :         }
     815             : 
     816       46129 :         return false;
     817             : }
     818             : 
     819       23505 : static bool dsdb_trust_find_tln_ex_match(const struct lsa_ForestTrustInformation *info,
     820             :                                          const char *tln)
     821             : {
     822         623 :         int m;
     823             : 
     824       24128 :         m = dsdb_trust_find_tln_match_internal(info,
     825             :                                                LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX,
     826             :                                                0,
     827             :                                                tln);
     828       23505 :         if (m != -1) {
     829           0 :                 return true;
     830             :         }
     831             : 
     832       22882 :         return false;
     833             : }
     834             : 
     835         147 : NTSTATUS dsdb_trust_local_tdo_info(TALLOC_CTX *mem_ctx,
     836             :                                    struct ldb_context *sam_ctx,
     837             :                                    struct lsa_TrustDomainInfoInfoEx **_tdo)
     838             : {
     839         147 :         struct ldb_dn *domain_dn = NULL;
     840             : 
     841         147 :         domain_dn = ldb_get_default_basedn(sam_ctx);
     842         147 :         if (domain_dn == NULL) {
     843           0 :                 return NT_STATUS_INTERNAL_ERROR;
     844             :         }
     845             : 
     846         147 :         return dsdb_trust_crossref_tdo_info(mem_ctx, sam_ctx,
     847             :                                             domain_dn, NULL,
     848             :                                             _tdo, NULL, NULL);
     849             : }
     850             : 
     851          87 : 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          87 :         const char *extra_filter = "(!(|(rootTrust=*)(trustParent=*)))";
     859          87 :         struct ldb_dn *domain_dn = NULL;
     860             : 
     861          87 :         domain_dn = ldb_get_default_basedn(sam_ctx);
     862          87 :         if (domain_dn == NULL) {
     863           0 :                 return NT_STATUS_INTERNAL_ERROR;
     864             :         }
     865             : 
     866          87 :         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           0 :         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       13994 : static int dsdb_trust_xref_sort_vals(struct ldb_val *v1,
     913             :                                      struct ldb_val *v2)
     914             : {
     915       13994 :         const char *dns1 = (const char *)v1->data;
     916       13994 :         const char *dns2 = (const char *)v2->data;
     917             : 
     918       13994 :         return dns_cmp(dns1, dns2);
     919             : }
     920             : 
     921       22430 : NTSTATUS dsdb_trust_xref_forest_info(TALLOC_CTX *mem_ctx,
     922             :                                      struct ldb_context *sam_ctx,
     923             :                                      struct lsa_ForestTrustInformation **_info)
     924             : {
     925       22430 :         TALLOC_CTX *frame = talloc_stackframe();
     926       22430 :         struct lsa_ForestTrustInformation *info = NULL;
     927       22430 :         struct ldb_dn *partitions_dn = NULL;
     928       22430 :         const char * const cross_attrs1[] = {
     929             :                 "uPNSuffixes",
     930             :                 "msDS-SPNSuffixes",
     931             :                 NULL,
     932             :         };
     933       22430 :         struct ldb_result *cross_res1 = NULL;
     934       22430 :         struct ldb_message_element *upn_el = NULL;
     935       22430 :         struct ldb_message_element *spn_el = NULL;
     936       22430 :         struct ldb_message *tln_msg = NULL;
     937       22430 :         struct ldb_message_element *tln_el = NULL;
     938       22430 :         const char * const cross_attrs2[] = {
     939             :                 "dnsRoot",
     940             :                 "nETBIOSName",
     941             :                 "nCName",
     942             :                 "rootTrust",
     943             :                 "trustParent",
     944             :                 NULL,
     945             :         };
     946       22430 :         struct ldb_result *cross_res2 = NULL;
     947         630 :         int ret;
     948         630 :         unsigned int i;
     949       22430 :         bool restart = false;
     950             : 
     951       22430 :         *_info = NULL;
     952       22430 :         info = talloc_zero(mem_ctx, struct lsa_ForestTrustInformation);
     953       22430 :         if (info == NULL) {
     954           0 :                 TALLOC_FREE(frame);
     955           0 :                 return NT_STATUS_NO_MEMORY;
     956             :         }
     957       22430 :         talloc_steal(frame, info);
     958             : 
     959       22430 :         partitions_dn = samdb_partitions_dn(sam_ctx, frame);
     960       22430 :         if (partitions_dn == NULL) {
     961           0 :                 TALLOC_FREE(frame);
     962           0 :                 return NT_STATUS_NO_MEMORY;
     963             :         }
     964             : 
     965       22430 :         ret = dsdb_search_dn(sam_ctx, partitions_dn, &cross_res1,
     966             :                              partitions_dn, cross_attrs1, 0);
     967       22430 :         if (ret != LDB_SUCCESS) {
     968           0 :                 TALLOC_FREE(frame);
     969           0 :                 return dsdb_ldb_err_to_ntstatus(ret);
     970             :         }
     971             : 
     972       22430 :         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       22430 :         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       22430 :         TYPESAFE_QSORT(cross_res2->msgs, cross_res2->count,
     989             :                        dsdb_trust_xref_sort_msgs);
     990             : 
     991       22430 :         upn_el = ldb_msg_find_element(cross_res1->msgs[0], "uPNSuffixes");
     992       22430 :         if (upn_el != NULL) {
     993       12248 :                 upn_el->name = "__tln__";
     994             :         }
     995       22430 :         spn_el = ldb_msg_find_element(cross_res1->msgs[0], "msDS-SPNSuffixes");
     996       22430 :         if (spn_el != NULL) {
     997       12248 :                 spn_el->name = "__tln__";
     998             :         }
     999       22430 :         ret = ldb_msg_normalize(sam_ctx, frame, cross_res1->msgs[0], &tln_msg);
    1000       22430 :         if (ret != LDB_SUCCESS) {
    1001           0 :                 TALLOC_FREE(frame);
    1002           0 :                 return dsdb_ldb_err_to_ntstatus(ret);
    1003             :         }
    1004       22430 :         tln_el = ldb_msg_find_element(tln_msg, "__tln__");
    1005       22430 :         if (tln_el != NULL) {
    1006             :                 /*
    1007             :                  * Sort the domains as trees
    1008             :                  */
    1009       12248 :                 TYPESAFE_QSORT(tln_el->values, tln_el->num_values,
    1010             :                                dsdb_trust_xref_sort_vals);
    1011             :         }
    1012             : 
    1013       44860 :         for (i=0; i < cross_res2->count; i++) {
    1014       22430 :                 struct ldb_message *m = cross_res2->msgs[i];
    1015       22430 :                 const char *dns = NULL;
    1016       22430 :                 const char *netbios = NULL;
    1017       22430 :                 struct ldb_dn *nc_dn = NULL;
    1018       22430 :                 struct dom_sid sid = {
    1019             :                         .num_auths = 0,
    1020             :                 };
    1021       22430 :                 struct lsa_ForestTrustRecord e = {
    1022             :                         .flags = 0,
    1023             :                 };
    1024       22430 :                 struct lsa_ForestTrustDomainInfo *d = NULL;
    1025       22430 :                 struct lsa_StringLarge *t = NULL;
    1026       22430 :                 bool match = false;
    1027         630 :                 NTSTATUS status;
    1028             : 
    1029       22430 :                 dns = ldb_msg_find_attr_as_string(m, "dnsRoot", NULL);
    1030       22430 :                 if (dns == NULL) {
    1031           0 :                         TALLOC_FREE(frame);
    1032           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
    1033             :                 }
    1034             : 
    1035       22430 :                 netbios = ldb_msg_find_attr_as_string(m, "nETBIOSName", NULL);
    1036       22430 :                 if (netbios == NULL) {
    1037           0 :                         TALLOC_FREE(frame);
    1038           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
    1039             :                 }
    1040             : 
    1041       22430 :                 nc_dn = samdb_result_dn(sam_ctx, m, m, "ncName", NULL);
    1042       22430 :                 if (nc_dn == NULL) {
    1043           0 :                         TALLOC_FREE(frame);
    1044           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
    1045             :                 }
    1046             : 
    1047       22430 :                 status = dsdb_get_extended_dn_sid(nc_dn, &sid, "SID");
    1048       22430 :                 if (!NT_STATUS_IS_OK(status)) {
    1049           0 :                         TALLOC_FREE(frame);
    1050           0 :                         return status;
    1051             :                 }
    1052             : 
    1053       22430 :                 match = dsdb_trust_find_tln_match(info, dns);
    1054       22430 :                 if (!match) {
    1055             :                         /*
    1056             :                          * First the TOP_LEVEL_NAME, if required
    1057             :                          */
    1058       22430 :                         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       22430 :                         t = &e.forest_trust_data.top_level_name;
    1065       22430 :                         t->string = dns;
    1066             : 
    1067       22430 :                         status = dsdb_trust_forest_info_add_record(info, &e);
    1068       22430 :                         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       22430 :                 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       22430 :                 d = &e.forest_trust_data.domain_info;
    1083       22430 :                 d->domain_sid = &sid;
    1084       22430 :                 d->dns_domain_name.string = dns;
    1085       22430 :                 d->netbios_domain_name.string = netbios;
    1086             : 
    1087       22430 :                 status = dsdb_trust_forest_info_add_record(info, &e);
    1088       22430 :                 if (!NT_STATUS_IS_OK(status)) {
    1089           0 :                         TALLOC_FREE(frame);
    1090           0 :                         return status;
    1091             :                 }
    1092             :         }
    1093             : 
    1094       47976 :         for (i=0; (tln_el != NULL) && i < tln_el->num_values; i++) {
    1095       25546 :                 const struct ldb_val *v = &tln_el->values[i];
    1096       25546 :                 const char *dns = (const char *)v->data;
    1097       25546 :                 struct lsa_ForestTrustRecord e = {
    1098             :                         .flags = 0,
    1099             :                 };
    1100       25546 :                 struct lsa_StringLarge *t = NULL;
    1101       25546 :                 bool match = false;
    1102        1252 :                 NTSTATUS status;
    1103             : 
    1104       25546 :                 if (dns == NULL) {
    1105           0 :                         TALLOC_FREE(frame);
    1106           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
    1107             :                 }
    1108             : 
    1109       25546 :                 match = dsdb_trust_find_tln_match(info, dns);
    1110       25546 :                 if (match) {
    1111           0 :                         continue;
    1112             :                 }
    1113             : 
    1114             :                 /*
    1115             :                  * an additional the TOP_LEVEL_NAME
    1116             :                  */
    1117       25546 :                 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       25546 :                 t = &e.forest_trust_data.top_level_name;
    1123       25546 :                 t->string = dns;
    1124             : 
    1125       25546 :                 status = dsdb_trust_forest_info_add_record(info, &e);
    1126       25546 :                 if (!NT_STATUS_IS_OK(status)) {
    1127           0 :                         TALLOC_FREE(frame);
    1128           0 :                         return status;
    1129             :                 }
    1130             :         }
    1131             : 
    1132       97140 :         for (i=0; i < info->count; restart ? i=0 : i++) {
    1133       70406 :                 struct lsa_ForestTrustRecord *tr = info->entries[i];
    1134       70406 :                 const struct lsa_StringLarge *ts = NULL;
    1135        2512 :                 uint32_t c;
    1136             : 
    1137       70406 :                 restart = false;
    1138             : 
    1139       70406 :                 if (tr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
    1140       22430 :                         continue;
    1141             :                 }
    1142             : 
    1143       47976 :                 ts = &tr->forest_trust_data.top_level_name;
    1144             : 
    1145      110960 :                 for (c = i + 1; c < info->count; c++) {
    1146       62984 :                         struct lsa_ForestTrustRecord *cr = info->entries[c];
    1147       62984 :                         const struct lsa_StringLarge *cs = NULL;
    1148        2508 :                         uint32_t j;
    1149        2508 :                         int cmp;
    1150             : 
    1151       62984 :                         if (cr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
    1152       22430 :                                 continue;
    1153             :                         }
    1154             : 
    1155       40554 :                         cs = &cr->forest_trust_data.top_level_name;
    1156             : 
    1157       40554 :                         cmp = dns_cmp(ts->string, cs->string);
    1158       40554 :                         if (DNS_CMP_IS_NO_MATCH(cmp)) {
    1159       40554 :                                 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       22430 :         *_info = talloc_move(mem_ctx, &info);
    1181       22430 :         TALLOC_FREE(frame);
    1182       22430 :         return NT_STATUS_OK;
    1183             : }
    1184             : 
    1185       11839 : NTSTATUS dsdb_trust_parse_tdo_info(TALLOC_CTX *mem_ctx,
    1186             :                                    struct ldb_message *m,
    1187             :                                    struct lsa_TrustDomainInfoInfoEx **_tdo)
    1188             : {
    1189       11839 :         struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
    1190       11839 :         const char *dns = NULL;
    1191       11839 :         const char *netbios = NULL;
    1192             : 
    1193       11839 :         *_tdo = NULL;
    1194             : 
    1195       11839 :         tdo = talloc_zero(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
    1196       11839 :         if (tdo == NULL) {
    1197           0 :                 return NT_STATUS_NO_MEMORY;
    1198             :         }
    1199             : 
    1200       11839 :         dns = ldb_msg_find_attr_as_string(m, "trustPartner", NULL);
    1201       11839 :         if (dns == NULL) {
    1202           0 :                 TALLOC_FREE(tdo);
    1203           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    1204             :         }
    1205       11839 :         tdo->domain_name.string = talloc_strdup(tdo, dns);
    1206       11839 :         if (tdo->domain_name.string == NULL) {
    1207           0 :                 TALLOC_FREE(tdo);
    1208           0 :                 return NT_STATUS_NO_MEMORY;
    1209             :         }
    1210             : 
    1211       11839 :         netbios = ldb_msg_find_attr_as_string(m, "flatName", NULL);
    1212       11839 :         if (netbios == NULL) {
    1213           0 :                 TALLOC_FREE(tdo);
    1214           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    1215             :         }
    1216       11839 :         tdo->netbios_name.string = talloc_strdup(tdo, netbios);
    1217       11839 :         if (tdo->netbios_name.string == NULL) {
    1218           0 :                 TALLOC_FREE(tdo);
    1219           0 :                 return NT_STATUS_NO_MEMORY;
    1220             :         }
    1221             : 
    1222       11839 :         tdo->sid = samdb_result_dom_sid(tdo, m, "securityIdentifier");
    1223       11839 :         if (tdo->sid == NULL) {
    1224           0 :                 TALLOC_FREE(tdo);
    1225           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    1226             :         }
    1227             : 
    1228       11839 :         tdo->trust_type = ldb_msg_find_attr_as_uint(m, "trustType", 0);
    1229       11839 :         tdo->trust_direction = ldb_msg_find_attr_as_uint(m, "trustDirection", 0);
    1230       11839 :         tdo->trust_attributes = ldb_msg_find_attr_as_uint(m, "trustAttributes", 0);
    1231             : 
    1232       11839 :         *_tdo = tdo;
    1233       11839 :         return NT_STATUS_OK;
    1234             : }
    1235             : 
    1236        2842 : NTSTATUS dsdb_trust_parse_forest_info(TALLOC_CTX *mem_ctx,
    1237             :                                       struct ldb_message *m,
    1238             :                                       struct ForestTrustInfo **_fti)
    1239             : {
    1240        2842 :         const struct ldb_val *ft_blob = NULL;
    1241        2842 :         struct ForestTrustInfo *fti = NULL;
    1242           0 :         enum ndr_err_code ndr_err;
    1243             : 
    1244        2842 :         *_fti = NULL;
    1245             : 
    1246        2842 :         ft_blob = ldb_msg_find_ldb_val(m, "msDS-TrustForestTrustInfo");
    1247        2842 :         if (ft_blob == NULL) {
    1248         959 :                 return NT_STATUS_NOT_FOUND;
    1249             :         }
    1250             : 
    1251        1883 :         fti = talloc_zero(mem_ctx, struct ForestTrustInfo);
    1252        1883 :         if (fti == NULL) {
    1253           0 :                 return NT_STATUS_NO_MEMORY;
    1254             :         }
    1255             : 
    1256             :         /* ldb_val is equivalent to DATA_BLOB */
    1257        1883 :         ndr_err = ndr_pull_struct_blob_all(ft_blob, fti, fti,
    1258             :                                 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
    1259        1883 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1260           0 :                 TALLOC_FREE(fti);
    1261           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    1262             :         }
    1263             : 
    1264        1883 :         *_fti = fti;
    1265        1883 :         return NT_STATUS_OK;
    1266             : }
    1267             : 
    1268          87 : NTSTATUS dsdb_trust_normalize_forest_info_step1(TALLOC_CTX *mem_ctx,
    1269             :                                 const struct lsa_ForestTrustInformation *gfti,
    1270             :                                 struct lsa_ForestTrustInformation **_nfti)
    1271             : {
    1272          87 :         TALLOC_CTX *frame = talloc_stackframe();
    1273           0 :         struct lsa_ForestTrustInformation *nfti;
    1274           0 :         uint32_t n;
    1275             : 
    1276          87 :         *_nfti = NULL;
    1277             : 
    1278          87 :         nfti = talloc_zero(mem_ctx, struct lsa_ForestTrustInformation);
    1279          87 :         if (nfti == NULL) {
    1280           0 :                 TALLOC_FREE(frame);
    1281           0 :                 return NT_STATUS_NO_MEMORY;
    1282             :         }
    1283          87 :         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 duplicates. 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         625 :         for (n = 0; n < gfti->count; n++) {
    1294         538 :                 const struct lsa_ForestTrustRecord *gftr = gfti->entries[n];
    1295         538 :                 struct lsa_ForestTrustRecord *nftr = NULL;
    1296         538 :                 struct lsa_ForestTrustDomainInfo *ninfo = NULL;
    1297         538 :                 struct lsa_StringLarge *ntln = NULL;
    1298         538 :                 struct lsa_StringLarge *nnb = NULL;
    1299         538 :                 struct dom_sid *nsid = NULL;
    1300           0 :                 NTSTATUS status;
    1301         538 :                 size_t len = 0;
    1302         538 :                 char *p = NULL;
    1303           0 :                 uint32_t c;
    1304             : 
    1305         538 :                 if (gftr == NULL) {
    1306           0 :                         TALLOC_FREE(frame);
    1307           0 :                         return NT_STATUS_INVALID_PARAMETER;
    1308             :                 }
    1309             : 
    1310         538 :                 status = dsdb_trust_forest_info_add_record(nfti, gftr);
    1311         538 :                 if (!NT_STATUS_IS_OK(status)) {
    1312           0 :                         TALLOC_FREE(frame);
    1313           0 :                         return status;
    1314             :                 }
    1315             : 
    1316         538 :                 nftr = nfti->entries[n];
    1317             : 
    1318         538 :                 switch (nftr->type) {
    1319         435 :                 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
    1320         435 :                         ntln = &nftr->forest_trust_data.top_level_name;
    1321         435 :                         break;
    1322             : 
    1323          16 :                 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
    1324          16 :                         ntln = &nftr->forest_trust_data.top_level_name_ex;
    1325          16 :                         break;
    1326             : 
    1327          87 :                 case LSA_FOREST_TRUST_DOMAIN_INFO:
    1328          87 :                         ninfo = &nftr->forest_trust_data.domain_info;
    1329          87 :                         ntln = &ninfo->dns_domain_name;
    1330          87 :                         nnb = &ninfo->netbios_domain_name;
    1331          87 :                         nsid = ninfo->domain_sid;
    1332          87 :                         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         538 :                 len = strlen(ntln->string);
    1353         538 :                 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         538 :                 if (ntln->string[0] == '.') {
    1359           0 :                         TALLOC_FREE(frame);
    1360           0 :                         return NT_STATUS_INVALID_PARAMETER;
    1361             :                 }
    1362         538 :                 p = strstr_m(ntln->string, "..");
    1363         538 :                 if (p != NULL) {
    1364           0 :                         TALLOC_FREE(frame);
    1365           0 :                         return NT_STATUS_INVALID_PARAMETER;
    1366             :                 }
    1367             : 
    1368        2061 :                 for (c = 0; c < n; c++) {
    1369        1523 :                         const struct lsa_ForestTrustRecord *cftr = nfti->entries[c];
    1370        1523 :                         const struct lsa_ForestTrustDomainInfo *cinfo = NULL;
    1371        1523 :                         const struct lsa_StringLarge *ctln = NULL;
    1372        1523 :                         const struct lsa_StringLarge *cnb = NULL;
    1373        1523 :                         const struct dom_sid *csid = NULL;
    1374           0 :                         int cmp;
    1375             : 
    1376        1523 :                         if (cftr == NULL) {
    1377           0 :                                 continue;
    1378             :                         }
    1379             : 
    1380        1523 :                         if (cftr->type != nftr->type) {
    1381         547 :                                 continue;
    1382             :                         }
    1383             : 
    1384         976 :                         switch (cftr->type) {
    1385         972 :                         case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
    1386         972 :                                 ctln = &cftr->forest_trust_data.top_level_name;
    1387         972 :                                 break;
    1388             : 
    1389           4 :                         case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
    1390           4 :                                 ctln = &cftr->forest_trust_data.top_level_name_ex;
    1391           4 :                                 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         976 :                         cmp = dns_cmp(ntln->string, ctln->string);
    1406         976 :                         if (cmp == DNS_CMP_MATCH) {
    1407           0 :                                 nftr = NULL;
    1408           0 :                                 TALLOC_FREE(nfti->entries[n]);
    1409           0 :                                 break;
    1410             :                         }
    1411             : 
    1412         976 :                         if (cinfo == NULL) {
    1413         976 :                                 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         625 :         for (n = 0; n < nfti->count; n++) {
    1436         538 :                 const struct lsa_ForestTrustRecord *nftr = nfti->entries[n];
    1437         538 :                 const struct lsa_StringLarge *ntln = NULL;
    1438           0 :                 uint32_t c;
    1439             : 
    1440         538 :                 if (nftr == NULL) {
    1441           0 :                         continue;
    1442             :                 }
    1443             : 
    1444         538 :                 if (nftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
    1445         103 :                         continue;
    1446             :                 }
    1447             : 
    1448         435 :                 ntln = &nftr->forest_trust_data.top_level_name;
    1449             : 
    1450        3345 :                 for (c = 0; c < nfti->count; c++) {
    1451        2910 :                         const struct lsa_ForestTrustRecord *cftr = nfti->entries[c];
    1452        2910 :                         const struct lsa_StringLarge *ctln = NULL;
    1453           0 :                         int cmp;
    1454             : 
    1455        2910 :                         if (cftr == NULL) {
    1456        2910 :                                 continue;
    1457             :                         }
    1458             : 
    1459        2910 :                         if (cftr == nftr) {
    1460         435 :                                 continue;
    1461             :                         }
    1462             : 
    1463        2475 :                         if (cftr->type != nftr->type) {
    1464         531 :                                 continue;
    1465             :                         }
    1466             : 
    1467        1944 :                         ctln = &cftr->forest_trust_data.top_level_name;
    1468             : 
    1469        1944 :                         cmp = dns_cmp(ntln->string, ctln->string);
    1470        1944 :                         if (DNS_CMP_IS_NO_MATCH(cmp)) {
    1471        1944 :                                 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         625 :         for (n = 0; n < nfti->count; n++) {
    1483         538 :                 const struct lsa_ForestTrustRecord *nftr = nfti->entries[n];
    1484         538 :                 const struct lsa_StringLarge *ntln = NULL;
    1485           0 :                 uint32_t c;
    1486         538 :                 bool found_tln = false;
    1487             : 
    1488         538 :                 if (nftr == NULL) {
    1489         538 :                         continue;
    1490             :                 }
    1491             : 
    1492         538 :                 if (nftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX) {
    1493         522 :                         continue;
    1494             :                 }
    1495             : 
    1496          16 :                 ntln = &nftr->forest_trust_data.top_level_name;
    1497             : 
    1498          68 :                 for (c = 0; c < nfti->count; c++) {
    1499          68 :                         const struct lsa_ForestTrustRecord *cftr = nfti->entries[c];
    1500          68 :                         const struct lsa_StringLarge *ctln = NULL;
    1501           0 :                         int cmp;
    1502             : 
    1503          68 :                         if (cftr == NULL) {
    1504           0 :                                 continue;
    1505             :                         }
    1506             : 
    1507          68 :                         if (cftr == nftr) {
    1508           8 :                                 continue;
    1509             :                         }
    1510             : 
    1511          60 :                         if (cftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
    1512           4 :                                 continue;
    1513             :                         }
    1514             : 
    1515          56 :                         ctln = &cftr->forest_trust_data.top_level_name;
    1516             : 
    1517          56 :                         cmp = dns_cmp(ntln->string, ctln->string);
    1518          56 :                         if (cmp == DNS_CMP_FIRST_IS_CHILD) {
    1519          16 :                                 found_tln = true;
    1520          16 :                                 break;
    1521             :                         }
    1522             :                 }
    1523             : 
    1524          16 :                 if (found_tln) {
    1525          16 :                         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         625 :         for (n = 0; n < nfti->count; n++) {
    1536         538 :                 const struct lsa_ForestTrustRecord *nftr = nfti->entries[n];
    1537         538 :                 const struct lsa_ForestTrustDomainInfo *ninfo = NULL;
    1538         538 :                 const struct lsa_StringLarge *ntln = NULL;
    1539           0 :                 uint32_t c;
    1540         538 :                 bool found_tln = false;
    1541             : 
    1542         538 :                 if (nftr == NULL) {
    1543         538 :                         continue;
    1544             :                 }
    1545             : 
    1546         538 :                 if (nftr->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
    1547         451 :                         continue;
    1548             :                 }
    1549             : 
    1550          87 :                 ninfo = &nftr->forest_trust_data.domain_info;
    1551          87 :                 ntln = &ninfo->dns_domain_name;
    1552             : 
    1553         215 :                 for (c = 0; c < nfti->count; c++) {
    1554         215 :                         const struct lsa_ForestTrustRecord *cftr = nfti->entries[c];
    1555         215 :                         const struct lsa_StringLarge *ctln = NULL;
    1556           0 :                         int cmp;
    1557             : 
    1558         215 :                         if (cftr == NULL) {
    1559           0 :                                 continue;
    1560             :                         }
    1561             : 
    1562         215 :                         if (cftr == nftr) {
    1563           0 :                                 continue;
    1564             :                         }
    1565             : 
    1566         215 :                         if (cftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
    1567           8 :                                 continue;
    1568             :                         }
    1569             : 
    1570         207 :                         ctln = &cftr->forest_trust_data.top_level_name;
    1571             : 
    1572         207 :                         cmp = dns_cmp(ntln->string, ctln->string);
    1573         207 :                         if (cmp == DNS_CMP_MATCH) {
    1574          87 :                                 found_tln = true;
    1575          87 :                                 break;
    1576             :                         }
    1577         120 :                         if (cmp == DNS_CMP_FIRST_IS_CHILD) {
    1578           0 :                                 found_tln = true;
    1579           0 :                                 break;
    1580             :                         }
    1581             :                 }
    1582             : 
    1583          87 :                 if (found_tln) {
    1584          87 :                         continue;
    1585             :                 }
    1586             : 
    1587           0 :                 TALLOC_FREE(frame);
    1588           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1589             :         }
    1590             : 
    1591          87 :         *_nfti = talloc_move(mem_ctx, &nfti);
    1592          87 :         TALLOC_FREE(frame);
    1593          87 :         return NT_STATUS_OK;
    1594             : }
    1595             : 
    1596          79 : NTSTATUS dsdb_trust_normalize_forest_info_step2(TALLOC_CTX *mem_ctx,
    1597             :                                 const struct lsa_ForestTrustInformation *gfti,
    1598             :                                 struct lsa_ForestTrustInformation **_nfti)
    1599             : {
    1600          79 :         TALLOC_CTX *frame = talloc_stackframe();
    1601          79 :         struct timeval tv = timeval_current();
    1602          79 :         NTTIME now = timeval_to_nttime(&tv);
    1603           0 :         struct lsa_ForestTrustInformation *nfti;
    1604           0 :         uint32_t g;
    1605             : 
    1606          79 :         *_nfti = NULL;
    1607             : 
    1608          79 :         nfti = talloc_zero(mem_ctx, struct lsa_ForestTrustInformation);
    1609          79 :         if (nfti == NULL) {
    1610           0 :                 TALLOC_FREE(frame);
    1611           0 :                 return NT_STATUS_NO_MEMORY;
    1612             :         }
    1613          79 :         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         561 :         for (g = 0; g < gfti->count; g++) {
    1623         482 :                 const struct lsa_ForestTrustRecord *gftr = gfti->entries[gfti->count - (g+1)];
    1624           0 :                 struct lsa_ForestTrustRecord tftr;
    1625         482 :                 bool skip = false;
    1626           0 :                 NTSTATUS status;
    1627             : 
    1628         482 :                 if (gftr == NULL) {
    1629          79 :                         continue;
    1630             :                 }
    1631             : 
    1632         482 :                 switch (gftr->type) {
    1633         403 :                 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
    1634             :                 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
    1635         403 :                         break;
    1636             : 
    1637          79 :                 case LSA_FOREST_TRUST_DOMAIN_INFO:
    1638          79 :                         skip = true;
    1639          79 :                         break;
    1640             : 
    1641           0 :                 default:
    1642           0 :                         TALLOC_FREE(frame);
    1643           0 :                         return NT_STATUS_INVALID_PARAMETER;
    1644             :                 }
    1645             : 
    1646         482 :                 if (skip) {
    1647          79 :                         continue;
    1648             :                 }
    1649             : 
    1650             :                 /* make a copy in order to update the time. */
    1651         403 :                 tftr = *gftr;
    1652         403 :                 if (tftr.time == 0) {
    1653         107 :                         tftr.time = now;
    1654             :                 }
    1655             : 
    1656         403 :                 status = dsdb_trust_forest_info_add_record(nfti, &tftr);
    1657         403 :                 if (!NT_STATUS_IS_OK(status)) {
    1658           0 :                         TALLOC_FREE(frame);
    1659           0 :                         return status;
    1660             :                 }
    1661             :         }
    1662             : 
    1663         561 :         for (g = 0; g < gfti->count; g++) {
    1664         482 :                 const struct lsa_ForestTrustRecord *gftr = gfti->entries[gfti->count - (g+1)];
    1665           0 :                 struct lsa_ForestTrustRecord tftr;
    1666         482 :                 bool skip = false;
    1667           0 :                 NTSTATUS status;
    1668             : 
    1669         482 :                 if (gftr == NULL) {
    1670         403 :                         continue;
    1671             :                 }
    1672             : 
    1673         482 :                 switch (gftr->type) {
    1674         403 :                 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
    1675             :                 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
    1676         403 :                         skip = true;
    1677         403 :                         break;
    1678             : 
    1679          79 :                 case LSA_FOREST_TRUST_DOMAIN_INFO:
    1680          79 :                         break;
    1681             : 
    1682           0 :                 default:
    1683           0 :                         TALLOC_FREE(frame);
    1684           0 :                         return NT_STATUS_INVALID_PARAMETER;
    1685             :                 }
    1686             : 
    1687         482 :                 if (skip) {
    1688         403 :                         continue;
    1689             :                 }
    1690             : 
    1691             :                 /* make a copy in order to update the time. */
    1692          79 :                 tftr = *gftr;
    1693          79 :                 if (tftr.time == 0) {
    1694          39 :                         tftr.time = now;
    1695             :                 }
    1696             : 
    1697          79 :                 status = dsdb_trust_forest_info_add_record(nfti, &tftr);
    1698          79 :                 if (!NT_STATUS_IS_OK(status)) {
    1699           0 :                         TALLOC_FREE(frame);
    1700           0 :                         return status;
    1701             :                 }
    1702             :         }
    1703             : 
    1704          79 :         *_nfti = talloc_move(mem_ctx, &nfti);
    1705          79 :         TALLOC_FREE(frame);
    1706          79 :         return NT_STATUS_OK;
    1707             : }
    1708             : 
    1709          36 : 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           0 :         struct lsa_ForestTrustCollisionRecord **es;
    1716          36 :         uint32_t i = c_info->count;
    1717             : 
    1718          36 :         es = talloc_realloc(c_info, c_info->entries,
    1719             :                             struct lsa_ForestTrustCollisionRecord *, i + 1);
    1720          36 :         if (es == NULL) {
    1721           0 :                 return NT_STATUS_NO_MEMORY;
    1722             :         }
    1723          36 :         c_info->entries = es;
    1724          36 :         c_info->count = i + 1;
    1725             : 
    1726          36 :         es[i] = talloc_zero(es, struct lsa_ForestTrustCollisionRecord);
    1727          36 :         if (es[i] == NULL) {
    1728           0 :                 return NT_STATUS_NO_MEMORY;
    1729             :         }
    1730             : 
    1731          36 :         es[i]->index = idx;
    1732          36 :         es[i]->type = type;
    1733          36 :         es[i]->flags = flags;
    1734          36 :         es[i]->name.string = talloc_strdup(es[i], tdo_name);
    1735          36 :         if (es[i]->name.string == NULL) {
    1736           0 :                 return NT_STATUS_NO_MEMORY;
    1737             :         }
    1738             : 
    1739          36 :         return NT_STATUS_OK;
    1740             : }
    1741             : 
    1742          87 : 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           0 :         uint32_t n;
    1749             : 
    1750         625 :         for (n = 0; n < new_fti->count; n++) {
    1751         538 :                 struct lsa_ForestTrustRecord *nftr = new_fti->entries[n];
    1752         538 :                 struct lsa_StringLarge *ntln = NULL;
    1753         538 :                 bool ntln_excluded = false;
    1754         538 :                 uint32_t flags = 0;
    1755           0 :                 uint32_t r;
    1756           0 :                 NTSTATUS status;
    1757             : 
    1758         538 :                 if (nftr == NULL) {
    1759         502 :                         continue;
    1760             :                 }
    1761             : 
    1762         538 :                 if (nftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
    1763         103 :                         continue;
    1764             :                 }
    1765             : 
    1766         435 :                 ntln = &nftr->forest_trust_data.top_level_name;
    1767         435 :                 if (ntln->string == NULL) {
    1768           0 :                         return NT_STATUS_INVALID_PARAMETER;
    1769             :                 }
    1770             : 
    1771         435 :                 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        3111 :                 for (r = 0; r < ref_fti->count; r++) {
    1776        2676 :                         const struct lsa_ForestTrustRecord *rftr =
    1777        2676 :                                 ref_fti->entries[r];
    1778        2676 :                         const struct lsa_StringLarge *rtln = NULL;
    1779           0 :                         int cmp;
    1780             : 
    1781        2676 :                         if (rftr == NULL) {
    1782           0 :                                 continue;
    1783             :                         }
    1784             : 
    1785        2676 :                         if (rftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
    1786         435 :                                 continue;
    1787             :                         }
    1788             : 
    1789        2241 :                         rtln = &rftr->forest_trust_data.top_level_name;
    1790        2241 :                         if (rtln->string == NULL) {
    1791           0 :                                 continue;
    1792             :                         }
    1793             : 
    1794        2241 :                         cmp = dns_cmp(ntln->string, rtln->string);
    1795        2241 :                         if (DNS_CMP_IS_NO_MATCH(cmp)) {
    1796        2077 :                                 continue;
    1797             :                         }
    1798         164 :                         if (cmp == DNS_CMP_MATCH) {
    1799             :                                 /* We need to normalize the string */
    1800         328 :                                 ntln->string = talloc_strdup(nftr,
    1801         164 :                                                              rtln->string);
    1802         164 :                                 if (ntln->string == NULL) {
    1803           0 :                                         return NT_STATUS_NO_MEMORY;
    1804             :                                 }
    1805             :                         }
    1806             : 
    1807         164 :                         if (ntln_excluded) {
    1808           0 :                                 continue;
    1809             :                         }
    1810             : 
    1811         164 :                         if (rftr->flags & LSA_TLN_DISABLED_MASK) {
    1812           0 :                                 continue;
    1813             :                         }
    1814             : 
    1815         164 :                         if (nftr->flags & LSA_TLN_DISABLED_MASK) {
    1816         128 :                                 continue;
    1817             :                         }
    1818             : 
    1819          36 :                         if (cmp == DNS_CMP_SECOND_IS_CHILD) {
    1820           0 :                                 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           0 :                                                                  rtln->string);
    1828           0 :                                 if (m) {
    1829           0 :                                         continue;
    1830             :                                 }
    1831             :                         }
    1832             : 
    1833          36 :                         flags |= LSA_TLN_DISABLED_CONFLICT;
    1834             :                 }
    1835             : 
    1836         435 :                 if (flags == 0) {
    1837         399 :                         continue;
    1838             :                 }
    1839             : 
    1840          36 :                 nftr->flags |= flags;
    1841             : 
    1842          36 :                 status = dsdb_trust_add_collision(c_info,
    1843             :                                                   collision_type,
    1844             :                                                   n, nftr->flags,
    1845          36 :                                                   ref_tdo->domain_name.string);
    1846          36 :                 if (!NT_STATUS_IS_OK(status)) {
    1847           0 :                         return status;
    1848             :                 }
    1849             :         }
    1850             : 
    1851         625 :         for (n = 0; n < new_fti->count; n++) {
    1852         538 :                 struct lsa_ForestTrustRecord *nftr = new_fti->entries[n];
    1853         538 :                 struct lsa_ForestTrustDomainInfo *ninfo = NULL;
    1854         538 :                 struct lsa_StringLarge *ntln = NULL;
    1855         538 :                 struct lsa_StringLarge *nnb = NULL;
    1856         538 :                 struct dom_sid *nsid = NULL;
    1857         538 :                 bool ntln_found = false;
    1858         538 :                 uint32_t flags = 0;
    1859           0 :                 uint32_t r;
    1860           0 :                 NTSTATUS status;
    1861             : 
    1862         538 :                 if (nftr == NULL) {
    1863         538 :                         continue;
    1864             :                 }
    1865             : 
    1866         538 :                 if (nftr->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
    1867         451 :                         continue;
    1868             :                 }
    1869             : 
    1870          87 :                 ninfo = &nftr->forest_trust_data.domain_info;
    1871          87 :                 ntln = &ninfo->dns_domain_name;
    1872          87 :                 if (ntln->string == NULL) {
    1873           0 :                         return NT_STATUS_INVALID_PARAMETER;
    1874             :                 }
    1875          87 :                 nnb = &ninfo->netbios_domain_name;
    1876          87 :                 if (nnb->string == NULL) {
    1877           0 :                         return NT_STATUS_INVALID_PARAMETER;
    1878             :                 }
    1879          87 :                 nsid = ninfo->domain_sid;
    1880          87 :                 if (nsid == NULL) {
    1881           0 :                         return NT_STATUS_INVALID_PARAMETER;
    1882             :                 }
    1883             : 
    1884          87 :                 ntln_found = dsdb_trust_find_tln_match(ref_fti, ntln->string);
    1885             : 
    1886             :                 /* check if this is already taken and not excluded */
    1887         591 :                 for (r = 0; r < ref_fti->count; r++) {
    1888         504 :                         const struct lsa_ForestTrustRecord *rftr =
    1889         504 :                                 ref_fti->entries[r];
    1890         504 :                         const struct lsa_ForestTrustDomainInfo *rinfo = NULL;
    1891         504 :                         const struct lsa_StringLarge *rtln = NULL;
    1892         504 :                         const struct lsa_StringLarge *rnb = NULL;
    1893         504 :                         const struct dom_sid *rsid = NULL;
    1894         504 :                         bool nb_possible = true;
    1895         504 :                         bool sid_possible = true;
    1896           0 :                         int cmp;
    1897             : 
    1898         504 :                         if (rftr == NULL) {
    1899           0 :                                 continue;
    1900             :                         }
    1901             : 
    1902         504 :                         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         140 :                                 nb_possible = false;
    1912         140 :                                 sid_possible = false;
    1913             :                         }
    1914             : 
    1915         504 :                         if (nftr->flags & LSA_SID_DISABLED_MASK) {
    1916         184 :                                 sid_possible = false;
    1917             :                         }
    1918             : 
    1919         504 :                         if (nftr->flags & LSA_NB_DISABLED_MASK) {
    1920         196 :                                 nb_possible = false;
    1921             :                         }
    1922             : 
    1923         504 :                         switch (rftr->type) {
    1924         417 :                         case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
    1925         417 :                                 rtln = &rftr->forest_trust_data.top_level_name;
    1926         417 :                                 nb_possible = false;
    1927         417 :                                 sid_possible = false;
    1928         417 :                                 break;
    1929             : 
    1930          87 :                         case LSA_FOREST_TRUST_DOMAIN_INFO:
    1931          87 :                                 rinfo = &rftr->forest_trust_data.domain_info;
    1932          87 :                                 rtln = &rinfo->dns_domain_name;
    1933          87 :                                 rnb = &rinfo->netbios_domain_name;
    1934          87 :                                 rsid = rinfo->domain_sid;
    1935             : 
    1936          87 :                                 if (rftr->flags & LSA_SID_DISABLED_MASK) {
    1937           0 :                                         sid_possible = false;
    1938             :                                 }
    1939             : 
    1940          87 :                                 if (rftr->flags & LSA_NB_DISABLED_MASK) {
    1941           0 :                                         nb_possible = false;
    1942             :                                 }
    1943          87 :                                 break;
    1944             : 
    1945           0 :                         default:
    1946           0 :                                 break;
    1947             :                         }
    1948             : 
    1949         504 :                         if (rtln == NULL) {
    1950           0 :                                 continue;
    1951             :                         }
    1952             : 
    1953         504 :                         if (rtln->string == NULL) {
    1954           0 :                                 continue;
    1955             :                         }
    1956             : 
    1957         504 :                         cmp = dns_cmp(ntln->string, rtln->string);
    1958         504 :                         if (DNS_CMP_IS_NO_MATCH(cmp)) {
    1959         452 :                                 nb_possible = false;
    1960         452 :                                 sid_possible = false;
    1961             :                         }
    1962         504 :                         if (cmp == DNS_CMP_MATCH) {
    1963             :                                 /* We need to normalize the string */
    1964         104 :                                 ntln->string = talloc_strdup(nftr,
    1965          52 :                                                              rtln->string);
    1966          52 :                                 if (ntln->string == NULL) {
    1967           0 :                                         return NT_STATUS_NO_MEMORY;
    1968             :                                 }
    1969             :                         }
    1970             : 
    1971         504 :                         if (rinfo == NULL) {
    1972         417 :                                 continue;
    1973             :                         }
    1974             : 
    1975          87 :                         if (rsid != NULL) {
    1976          87 :                                 cmp = dom_sid_compare(nsid, rsid);
    1977             :                         } else {
    1978           0 :                                 cmp = -1;
    1979             :                         }
    1980          87 :                         if (cmp == 0) {
    1981           0 :                                 if (sid_possible) {
    1982           0 :                                         flags |= LSA_SID_DISABLED_CONFLICT;
    1983             :                                 }
    1984             :                         }
    1985             : 
    1986          87 :                         if (rnb->string != NULL) {
    1987          87 :                                 cmp = strcasecmp_m(nnb->string, rnb->string);
    1988             :                         } else {
    1989           0 :                                 cmp = -1;
    1990             :                         }
    1991          87 :                         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          87 :                 if (flags == 0) {
    2003          87 :                         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           0 :                                                   ref_tdo->domain_name.string);
    2012           0 :                 if (!NT_STATUS_IS_OK(status)) {
    2013           0 :                         return status;
    2014             :                 }
    2015             :         }
    2016             : 
    2017          87 :         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           0 :         uint32_t ni;
    2029           0 :         uint32_t oi;
    2030           0 :         NTSTATUS status;
    2031           0 :         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           0 :                 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           0 :                 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           0 :                 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           0 :                 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        1867 : 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        1867 :         TALLOC_CTX *frame = talloc_stackframe();
    2449           0 :         int ret;
    2450        1867 :         struct ldb_dn *system_dn = NULL;
    2451        1867 :         char *netbios_encoded = NULL;
    2452        1867 :         char *dns_encoded = NULL;
    2453        1867 :         char *filter = NULL;
    2454             : 
    2455        1867 :         *msg = NULL;
    2456             : 
    2457        1867 :         if (netbios == NULL && dns == NULL) {
    2458           0 :                 TALLOC_FREE(frame);
    2459           0 :                 return NT_STATUS_INVALID_PARAMETER_MIX;
    2460             :         }
    2461             : 
    2462        1867 :         system_dn = samdb_system_container_dn(sam_ctx, frame);
    2463        1867 :         if (system_dn == NULL) {
    2464           0 :                 TALLOC_FREE(frame);
    2465           0 :                 return NT_STATUS_NO_MEMORY;
    2466             :         }
    2467             : 
    2468        1867 :         if (netbios != NULL) {
    2469        1620 :                 netbios_encoded = ldb_binary_encode_string(frame, netbios);
    2470        1620 :                 if (netbios_encoded == NULL) {
    2471           0 :                         TALLOC_FREE(frame);
    2472           0 :                         return NT_STATUS_NO_MEMORY;
    2473             :                 }
    2474             :         }
    2475             : 
    2476        1867 :         if (dns != NULL) {
    2477        1658 :                 dns_encoded = ldb_binary_encode_string(frame, dns);
    2478        1658 :                 if (dns_encoded == NULL) {
    2479           0 :                         TALLOC_FREE(frame);
    2480           0 :                         return NT_STATUS_NO_MEMORY;
    2481             :                 }
    2482             :         }
    2483             : 
    2484        1867 :         if (netbios != NULL && dns != NULL) {
    2485        1411 :                 filter = talloc_asprintf(frame,
    2486             :                                 "(&(objectClass=trustedDomain)"
    2487             :                                   "(|(trustPartner=%s)(flatName=%s))"
    2488             :                                 ")",
    2489             :                                 dns_encoded, netbios_encoded);
    2490        1411 :                 if (filter == NULL) {
    2491           0 :                         TALLOC_FREE(frame);
    2492           0 :                         return NT_STATUS_NO_MEMORY;
    2493             :                 }
    2494         456 :         } else if (netbios != NULL) {
    2495         209 :                 filter = talloc_asprintf(frame,
    2496             :                                 "(&(objectClass=trustedDomain)(flatName=%s))",
    2497             :                                 netbios_encoded);
    2498         209 :                 if (filter == NULL) {
    2499           0 :                         TALLOC_FREE(frame);
    2500           0 :                         return NT_STATUS_NO_MEMORY;
    2501             :                 }
    2502         247 :         } else if (dns != NULL) {
    2503         247 :                 filter = talloc_asprintf(frame,
    2504             :                                 "(&(objectClass=trustedDomain)(trustPartner=%s))",
    2505             :                                 dns_encoded);
    2506         247 :                 if (filter == NULL) {
    2507           0 :                         TALLOC_FREE(frame);
    2508           0 :                         return NT_STATUS_NO_MEMORY;
    2509             :                 }
    2510             :         }
    2511             : 
    2512        1867 :         ret = dsdb_search_one(sam_ctx, mem_ctx, msg,
    2513             :                               system_dn,
    2514             :                               LDB_SCOPE_ONELEVEL, attrs,
    2515             :                               DSDB_SEARCH_NO_GLOBAL_CATALOG,
    2516             :                               "%s", filter);
    2517        1867 :         if (ret != LDB_SUCCESS) {
    2518           9 :                 NTSTATUS status = dsdb_ldb_err_to_ntstatus(ret);
    2519           9 :                 DEBUG(3, ("Failed to search for %s: %s - %s\n",
    2520             :                           filter, nt_errstr(status), ldb_errstring(sam_ctx)));
    2521           9 :                 TALLOC_FREE(frame);
    2522           9 :                 return status;
    2523             :         }
    2524             : 
    2525        1858 :         TALLOC_FREE(frame);
    2526        1858 :         return NT_STATUS_OK;
    2527             : }
    2528             : 
    2529         146 : NTSTATUS dsdb_trust_search_tdo_by_type(struct ldb_context *sam_ctx,
    2530             :                                        enum netr_SchannelType type,
    2531             :                                        const char *name,
    2532             :                                        const char * const *attrs,
    2533             :                                        TALLOC_CTX *mem_ctx,
    2534             :                                        struct ldb_message **msg)
    2535             : {
    2536         146 :         TALLOC_CTX *frame = talloc_stackframe();
    2537           0 :         NTSTATUS status;
    2538           0 :         size_t len;
    2539         146 :         char trailer = '$';
    2540         146 :         bool require_trailer = true;
    2541         146 :         char *encoded_name = NULL;
    2542         146 :         const char *netbios = NULL;
    2543         146 :         const char *dns = NULL;
    2544             : 
    2545         146 :         if (type != SEC_CHAN_DOMAIN && type != SEC_CHAN_DNS_DOMAIN) {
    2546           0 :                 TALLOC_FREE(frame);
    2547           0 :                 return NT_STATUS_INVALID_PARAMETER;
    2548             :         }
    2549             : 
    2550         146 :         if (type == SEC_CHAN_DNS_DOMAIN) {
    2551          36 :                 trailer = '.';
    2552          36 :                 require_trailer = false;
    2553             :         }
    2554             : 
    2555         146 :         encoded_name = ldb_binary_encode_string(frame, name);
    2556         146 :         if (encoded_name == NULL) {
    2557           0 :                 TALLOC_FREE(frame);
    2558           0 :                 return NT_STATUS_NO_MEMORY;
    2559             :         }
    2560             : 
    2561         146 :         len = strlen(encoded_name);
    2562         146 :         if (len < 2) {
    2563           0 :                 TALLOC_FREE(frame);
    2564           0 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    2565             :         }
    2566             : 
    2567         146 :         if (require_trailer && encoded_name[len - 1] != trailer) {
    2568           0 :                 TALLOC_FREE(frame);
    2569           0 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    2570             :         }
    2571         146 :         encoded_name[len - 1] = '\0';
    2572             : 
    2573         146 :         if (type == SEC_CHAN_DNS_DOMAIN) {
    2574          36 :                 dns = encoded_name;
    2575             :         } else {
    2576         110 :                 netbios = encoded_name;
    2577             :         }
    2578             : 
    2579         146 :         status = dsdb_trust_search_tdo(sam_ctx, netbios, dns,
    2580             :                                        attrs, mem_ctx, msg);
    2581         146 :         if (!NT_STATUS_IS_OK(status)) {
    2582           0 :                 TALLOC_FREE(frame);
    2583           0 :                 return status;
    2584             :         }
    2585             : 
    2586         146 :         TALLOC_FREE(frame);
    2587         146 :         return NT_STATUS_OK;
    2588             : }
    2589             : 
    2590           0 : NTSTATUS dsdb_trust_search_tdo_by_sid(struct ldb_context *sam_ctx,
    2591             :                                       const struct dom_sid *sid,
    2592             :                                       const char * const *attrs,
    2593             :                                       TALLOC_CTX *mem_ctx,
    2594             :                                       struct ldb_message **msg)
    2595             : {
    2596           0 :         TALLOC_CTX *frame = talloc_stackframe();
    2597           0 :         int ret;
    2598           0 :         struct ldb_dn *system_dn = NULL;
    2599           0 :         char *encoded_sid = NULL;
    2600           0 :         char *filter = NULL;
    2601             : 
    2602           0 :         *msg = NULL;
    2603             : 
    2604           0 :         if (sid == NULL) {
    2605           0 :                 TALLOC_FREE(frame);
    2606           0 :                 return NT_STATUS_INVALID_PARAMETER_MIX;
    2607             :         }
    2608             : 
    2609           0 :         encoded_sid = ldap_encode_ndr_dom_sid(frame, sid);
    2610           0 :         if (encoded_sid == NULL) {
    2611           0 :                 TALLOC_FREE(frame);
    2612           0 :                 return NT_STATUS_NO_MEMORY;
    2613             :         }
    2614             : 
    2615           0 :         system_dn = samdb_system_container_dn(sam_ctx, frame);
    2616           0 :         if (system_dn == NULL) {
    2617           0 :                 TALLOC_FREE(frame);
    2618           0 :                 return NT_STATUS_NO_MEMORY;
    2619             :         }
    2620             : 
    2621           0 :         filter = talloc_asprintf(frame,
    2622             :                                 "(&"
    2623             :                                   "(objectClass=trustedDomain)"
    2624             :                                   "(securityIdentifier=%s)"
    2625             :                                 ")",
    2626             :                                 encoded_sid);
    2627           0 :         if (filter == NULL) {
    2628           0 :                 TALLOC_FREE(frame);
    2629           0 :                 return NT_STATUS_NO_MEMORY;
    2630             :         }
    2631             : 
    2632           0 :         ret = dsdb_search_one(sam_ctx, mem_ctx, msg,
    2633             :                               system_dn,
    2634             :                               LDB_SCOPE_ONELEVEL, attrs,
    2635             :                               DSDB_SEARCH_NO_GLOBAL_CATALOG,
    2636             :                               "%s", filter);
    2637           0 :         if (ret != LDB_SUCCESS) {
    2638           0 :                 NTSTATUS status = dsdb_ldb_err_to_ntstatus(ret);
    2639           0 :                 DEBUG(3, ("Failed to search for %s: %s - %s\n",
    2640             :                           filter, nt_errstr(status), ldb_errstring(sam_ctx)));
    2641           0 :                 TALLOC_FREE(frame);
    2642           0 :                 return status;
    2643             :         }
    2644             : 
    2645           0 :         TALLOC_FREE(frame);
    2646           0 :         return NT_STATUS_OK;
    2647             : }
    2648             : 
    2649         358 : NTSTATUS dsdb_trust_get_incoming_passwords(struct ldb_message *msg,
    2650             :                                            TALLOC_CTX *mem_ctx,
    2651             :                                            struct samr_Password **_current,
    2652             :                                            struct samr_Password **_previous)
    2653             : {
    2654         358 :         TALLOC_CTX *frame = talloc_stackframe();
    2655         358 :         struct samr_Password __current = {
    2656             :                 .hash = {0},
    2657             :         };
    2658         358 :         struct samr_Password __previous = {
    2659             :                 .hash = {0},
    2660             :         };
    2661         358 :         struct samr_Password *current = NULL;
    2662         358 :         struct samr_Password *previous = NULL;
    2663         358 :         const struct ldb_val *blob = NULL;
    2664           0 :         enum ndr_err_code ndr_err;
    2665         358 :         struct trustAuthInOutBlob incoming = {
    2666             :                 .count = 0,
    2667             :         };
    2668           0 :         uint32_t i;
    2669             : 
    2670         358 :         if (_current != NULL) {
    2671         358 :                 *_current = NULL;
    2672             :         }
    2673         358 :         if (_previous != NULL) {
    2674         358 :                 *_previous = NULL;
    2675             :         }
    2676             : 
    2677         358 :         blob = ldb_msg_find_ldb_val(msg, "trustAuthIncoming");
    2678         358 :         if (blob == NULL) {
    2679           0 :                 TALLOC_FREE(frame);
    2680           0 :                 return NT_STATUS_ACCOUNT_DISABLED;
    2681             :         }
    2682             : 
    2683             :         /* ldb_val is equivalent to DATA_BLOB */
    2684         358 :         ndr_err = ndr_pull_struct_blob_all(blob, frame, &incoming,
    2685             :                                 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
    2686         358 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    2687           0 :                 TALLOC_FREE(frame);
    2688           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    2689             :         }
    2690             : 
    2691         716 :         for (i = 0; i < incoming.current.count; i++) {
    2692         584 :                 struct AuthenticationInformation *a =
    2693         584 :                         &incoming.current.array[i];
    2694             : 
    2695         584 :                 if (current != NULL) {
    2696         226 :                         break;
    2697             :                 }
    2698             : 
    2699         358 :                 switch (a->AuthType) {
    2700           0 :                 case TRUST_AUTH_TYPE_NONE:
    2701             :                 case TRUST_AUTH_TYPE_VERSION:
    2702           0 :                         break;
    2703           0 :                 case TRUST_AUTH_TYPE_NT4OWF:
    2704           0 :                         current = &a->AuthInfo.nt4owf.password;
    2705           0 :                         break;
    2706         358 :                 case TRUST_AUTH_TYPE_CLEAR:
    2707         358 :                         mdfour(__current.hash,
    2708         358 :                                a->AuthInfo.clear.password,
    2709         358 :                                a->AuthInfo.clear.size);
    2710         358 :                         current = &__current;
    2711         358 :                         break;
    2712             :                 }
    2713             :         }
    2714             : 
    2715         358 :         if (current == NULL) {
    2716           0 :                 TALLOC_FREE(frame);
    2717           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    2718             :         }
    2719             : 
    2720         716 :         for (i = 0; i < incoming.previous.count; i++) {
    2721         584 :                 struct AuthenticationInformation *a =
    2722         584 :                         &incoming.previous.array[i];
    2723             : 
    2724         584 :                 if (previous != NULL) {
    2725         226 :                         break;
    2726             :                 }
    2727             : 
    2728         358 :                 switch (a->AuthType) {
    2729           0 :                 case TRUST_AUTH_TYPE_NONE:
    2730             :                 case TRUST_AUTH_TYPE_VERSION:
    2731           0 :                         break;
    2732           0 :                 case TRUST_AUTH_TYPE_NT4OWF:
    2733           0 :                         previous = &a->AuthInfo.nt4owf.password;
    2734           0 :                         break;
    2735         358 :                 case TRUST_AUTH_TYPE_CLEAR:
    2736         358 :                         mdfour(__previous.hash,
    2737         358 :                                a->AuthInfo.clear.password,
    2738         358 :                                a->AuthInfo.clear.size);
    2739         358 :                         previous = &__previous;
    2740         358 :                         break;
    2741             :                 }
    2742             :         }
    2743             : 
    2744         358 :         if (previous == NULL) {
    2745           0 :                 previous = current;
    2746             :         }
    2747             : 
    2748         358 :         if (_current != NULL) {
    2749         358 :                 *_current = talloc_memdup(mem_ctx, current, sizeof(*current));
    2750         358 :                 if (*_current == NULL) {
    2751           0 :                         TALLOC_FREE(frame);
    2752           0 :                         return NT_STATUS_NO_MEMORY;
    2753             :                 }
    2754             :         }
    2755         358 :         if (_previous != NULL) {
    2756         358 :                 *_previous =
    2757         358 :                         talloc_memdup(mem_ctx, previous, sizeof(*previous));
    2758         358 :                 if (*_previous == NULL) {
    2759           0 :                         if (_current != NULL) {
    2760           0 :                                 TALLOC_FREE(*_current);
    2761             :                         }
    2762           0 :                         TALLOC_FREE(frame);
    2763           0 :                         return NT_STATUS_NO_MEMORY;
    2764             :                 }
    2765             :         }
    2766         358 :         ZERO_STRUCTP(current);
    2767         358 :         ZERO_STRUCTP(previous);
    2768         358 :         TALLOC_FREE(frame);
    2769         358 :         return NT_STATUS_OK;
    2770             : }
    2771             : 
    2772       22402 : NTSTATUS dsdb_trust_search_tdos(struct ldb_context *sam_ctx,
    2773             :                                 const char *exclude,
    2774             :                                 const char * const *attrs,
    2775             :                                 TALLOC_CTX *mem_ctx,
    2776             :                                 struct ldb_result **res)
    2777             : {
    2778       22402 :         TALLOC_CTX *frame = talloc_stackframe();
    2779         644 :         int ret;
    2780       22402 :         struct ldb_dn *system_dn = NULL;
    2781       22402 :         const char *filter = NULL;
    2782       22402 :         char *exclude_encoded = NULL;
    2783             : 
    2784       22402 :         *res = NULL;
    2785             : 
    2786       22402 :         system_dn = samdb_system_container_dn(sam_ctx, frame);
    2787       22402 :         if (system_dn == NULL) {
    2788           0 :                 TALLOC_FREE(frame);
    2789           0 :                 return NT_STATUS_NO_MEMORY;
    2790             :         }
    2791             : 
    2792       22402 :         if (exclude != NULL) {
    2793          87 :                 exclude_encoded = ldb_binary_encode_string(frame, exclude);
    2794          87 :                 if (exclude_encoded == NULL) {
    2795           0 :                         TALLOC_FREE(frame);
    2796           0 :                         return NT_STATUS_NO_MEMORY;
    2797             :                 }
    2798             : 
    2799          87 :                 filter = talloc_asprintf(frame,
    2800             :                                 "(&(objectClass=trustedDomain)"
    2801             :                                   "(!(|(trustPartner=%s)(flatName=%s)))"
    2802             :                                 ")",
    2803             :                                 exclude_encoded, exclude_encoded);
    2804          87 :                 if (filter == NULL) {
    2805           0 :                         TALLOC_FREE(frame);
    2806           0 :                         return NT_STATUS_NO_MEMORY;
    2807             :                 }
    2808             :         } else {
    2809       21671 :                 filter = "(objectClass=trustedDomain)";
    2810             :         }
    2811             : 
    2812       22402 :         ret = dsdb_search(sam_ctx, mem_ctx, res,
    2813             :                           system_dn,
    2814             :                           LDB_SCOPE_ONELEVEL, attrs,
    2815             :                           DSDB_SEARCH_NO_GLOBAL_CATALOG,
    2816             :                           "%s", filter);
    2817       22402 :         if (ret != LDB_SUCCESS) {
    2818           0 :                 NTSTATUS status = dsdb_ldb_err_to_ntstatus(ret);
    2819           0 :                 DEBUG(3, ("Failed to search for %s: %s - %s\n",
    2820             :                           filter, nt_errstr(status), ldb_errstring(sam_ctx)));
    2821           0 :                 TALLOC_FREE(frame);
    2822           0 :                 return status;
    2823             :         }
    2824             : 
    2825       22402 :         TALLOC_FREE(frame);
    2826       22402 :         return NT_STATUS_OK;
    2827             : }
    2828             : 
    2829             : struct dsdb_trust_routing_domain;
    2830             : 
    2831             : struct dsdb_trust_routing_table {
    2832             :         struct dsdb_trust_routing_domain *domains;
    2833             : };
    2834             : 
    2835             : struct dsdb_trust_routing_domain {
    2836             :         struct dsdb_trust_routing_domain *prev, *next;
    2837             : 
    2838             :         struct lsa_TrustDomainInfoInfoEx *tdo;
    2839             : 
    2840             :         struct lsa_ForestTrustDomainInfo di;
    2841             : 
    2842             :         struct lsa_ForestTrustInformation *fti;
    2843             : };
    2844             : 
    2845       22168 : NTSTATUS dsdb_trust_routing_table_load(struct ldb_context *sam_ctx,
    2846             :                                        TALLOC_CTX *mem_ctx,
    2847             :                                        struct dsdb_trust_routing_table **_table)
    2848             : {
    2849       22168 :         TALLOC_CTX *frame = talloc_stackframe();
    2850         623 :         struct dsdb_trust_routing_table *table;
    2851       22168 :         struct dsdb_trust_routing_domain *d = NULL;
    2852       22168 :         struct ldb_dn *domain_dn = NULL;
    2853       22168 :         struct lsa_TrustDomainInfoInfoEx *root_trust_tdo = NULL;
    2854       22168 :         struct lsa_TrustDomainInfoInfoEx *trust_parent_tdo = NULL;
    2855       22168 :         struct lsa_TrustDomainInfoInfoEx *root_direction_tdo = NULL;
    2856       22168 :         const char * const trusts_attrs[] = {
    2857             :                 "securityIdentifier",
    2858             :                 "flatName",
    2859             :                 "trustPartner",
    2860             :                 "trustAttributes",
    2861             :                 "trustDirection",
    2862             :                 "trustType",
    2863             :                 "msDS-TrustForestTrustInfo",
    2864             :                 NULL
    2865             :         };
    2866       22168 :         struct ldb_result *trusts_res = NULL;
    2867         623 :         unsigned int i;
    2868         623 :         NTSTATUS status;
    2869             : 
    2870       22168 :         *_table = NULL;
    2871             : 
    2872       22168 :         domain_dn = ldb_get_default_basedn(sam_ctx);
    2873       22168 :         if (domain_dn == NULL) {
    2874           0 :                 TALLOC_FREE(frame);
    2875           0 :                 return NT_STATUS_INTERNAL_ERROR;
    2876             :         }
    2877             : 
    2878       22168 :         table = talloc_zero(mem_ctx, struct dsdb_trust_routing_table);
    2879       22168 :         if (table == NULL) {
    2880           0 :                 TALLOC_FREE(frame);
    2881           0 :                 return NT_STATUS_NO_MEMORY;
    2882             :         }
    2883       22168 :         talloc_steal(frame, table);
    2884             : 
    2885       22168 :         d = talloc_zero(table, struct dsdb_trust_routing_domain);
    2886       22168 :         if (d == NULL) {
    2887           0 :                 TALLOC_FREE(frame);
    2888           0 :                 return NT_STATUS_NO_MEMORY;
    2889             :         }
    2890             : 
    2891       22168 :         status = dsdb_trust_crossref_tdo_info(d, sam_ctx,
    2892             :                                               domain_dn, NULL,
    2893             :                                               &d->tdo,
    2894             :                                               &root_trust_tdo,
    2895             :                                               &trust_parent_tdo);
    2896       22168 :         if (!NT_STATUS_IS_OK(status)) {
    2897           0 :                 TALLOC_FREE(frame);
    2898           0 :                 return status;
    2899             :         }
    2900             : 
    2901             :         /*
    2902             :          * d->tdo should not be NULL of status above is 'NT_STATUS_OK'
    2903             :          * check is needed to satisfy clang static checker
    2904             :         */
    2905       22168 :         if (d->tdo == NULL) {
    2906           0 :                 TALLOC_FREE(frame);
    2907           0 :                 return NT_STATUS_NO_MEMORY;
    2908             :         }
    2909       22168 :         d->di.domain_sid = d->tdo->sid;
    2910       22168 :         d->di.netbios_domain_name.string = d->tdo->netbios_name.string;
    2911       22168 :         d->di.dns_domain_name.string = d->tdo->domain_name.string;
    2912             : 
    2913       22168 :         if (root_trust_tdo != NULL) {
    2914           0 :                 root_direction_tdo = root_trust_tdo;
    2915       22168 :         } else if (trust_parent_tdo != NULL) {
    2916           0 :                 root_direction_tdo = trust_parent_tdo;
    2917             :         }
    2918             : 
    2919       21545 :         if (root_direction_tdo == NULL) {
    2920             :                 /* we're the forest root */
    2921       22168 :                 status = dsdb_trust_xref_forest_info(d, sam_ctx, &d->fti);
    2922       22168 :                 if (!NT_STATUS_IS_OK(status)) {
    2923           0 :                         TALLOC_FREE(frame);
    2924           0 :                         return status;
    2925             :                 }
    2926             :         }
    2927             : 
    2928       22168 :         DLIST_ADD(table->domains, d);
    2929             : 
    2930       22168 :         status = dsdb_trust_search_tdos(sam_ctx, NULL, trusts_attrs,
    2931             :                                         frame, &trusts_res);
    2932       22168 :         if (!NT_STATUS_IS_OK(status)) {
    2933           0 :                 TALLOC_FREE(frame);
    2934           0 :                 return status;
    2935             :         }
    2936             : 
    2937       32571 :         for (i = 0; i < trusts_res->count; i++) {
    2938           0 :                 bool ok;
    2939           0 :                 int cmp;
    2940             : 
    2941       10403 :                 d = talloc_zero(table, struct dsdb_trust_routing_domain);
    2942       10403 :                 if (d == NULL) {
    2943           0 :                         TALLOC_FREE(frame);
    2944           0 :                         return NT_STATUS_NO_MEMORY;
    2945             :                 }
    2946             : 
    2947       10403 :                 status = dsdb_trust_parse_tdo_info(d,
    2948       10403 :                                                    trusts_res->msgs[i],
    2949             :                                                    &d->tdo);
    2950       10403 :                 if (!NT_STATUS_IS_OK(status)) {
    2951           0 :                         TALLOC_FREE(frame);
    2952           0 :                         return status;
    2953             :                 }
    2954             : 
    2955       10403 :                 d->di.domain_sid = d->tdo->sid;
    2956       10403 :                 d->di.netbios_domain_name.string = d->tdo->netbios_name.string;
    2957       10403 :                 d->di.dns_domain_name.string = d->tdo->domain_name.string;
    2958             : 
    2959       10403 :                 DLIST_ADD_END(table->domains, d);
    2960             : 
    2961       10403 :                 if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
    2962        2644 :                         struct ForestTrustInfo *fti = NULL;
    2963             : 
    2964        2644 :                         status = dsdb_trust_parse_forest_info(frame,
    2965        2644 :                                                               trusts_res->msgs[i],
    2966             :                                                               &fti);
    2967        2644 :                         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
    2968         917 :                                 fti = NULL;
    2969         917 :                                 status = NT_STATUS_OK;
    2970             :                         }
    2971        2644 :                         if (!NT_STATUS_IS_OK(status)) {
    2972           0 :                                 TALLOC_FREE(frame);
    2973           0 :                                 return status;
    2974             :                         }
    2975             : 
    2976        2644 :                         if (fti == NULL) {
    2977        2644 :                                 continue;
    2978             :                         }
    2979             : 
    2980        1727 :                         status = dsdb_trust_forest_info_to_lsa(d, fti, &d->fti);
    2981        1727 :                         if (!NT_STATUS_IS_OK(status)) {
    2982           0 :                                 TALLOC_FREE(frame);
    2983           0 :                                 return status;
    2984             :                         }
    2985             : 
    2986        1727 :                         continue;
    2987             :                 }
    2988             : 
    2989        7759 :                 if (!(d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST)) {
    2990        7759 :                         continue;
    2991             :                 }
    2992             : 
    2993           0 :                 if (root_direction_tdo == NULL) {
    2994           0 :                         continue;
    2995             :                 }
    2996             : 
    2997           0 :                 ok = dom_sid_equal(root_direction_tdo->sid, d->tdo->sid);
    2998           0 :                 if (!ok) {
    2999           0 :                         continue;
    3000             :                 }
    3001             : 
    3002           0 :                 cmp = strcasecmp_m(root_direction_tdo->netbios_name.string,
    3003           0 :                                    d->tdo->netbios_name.string);
    3004           0 :                 if (cmp != 0) {
    3005           0 :                         continue;
    3006             :                 }
    3007             : 
    3008           0 :                 cmp = strcasecmp_m(root_direction_tdo->domain_name.string,
    3009           0 :                                    d->tdo->domain_name.string);
    3010           0 :                 if (cmp != 0) {
    3011           0 :                         continue;
    3012             :                 }
    3013             : 
    3014             :                 /* this our route to the forest root */
    3015           0 :                 status = dsdb_trust_xref_forest_info(d, sam_ctx, &d->fti);
    3016           0 :                 if (!NT_STATUS_IS_OK(status)) {
    3017           0 :                         TALLOC_FREE(frame);
    3018           0 :                         return status;
    3019             :                 }
    3020             :         }
    3021             : 
    3022       22168 :         *_table = talloc_move(mem_ctx, &table);
    3023       22168 :         TALLOC_FREE(frame);
    3024       22168 :         return NT_STATUS_OK;
    3025             : }
    3026             : 
    3027        1986 : static void dsdb_trust_update_best_tln(
    3028             :         const struct dsdb_trust_routing_domain **best_d,
    3029             :         const char **best_tln,
    3030             :         const struct dsdb_trust_routing_domain *d,
    3031             :         const char *tln)
    3032             : {
    3033           0 :         int cmp;
    3034             : 
    3035        1986 :         if (*best_tln == NULL) {
    3036        1986 :                 *best_tln = tln;
    3037        1986 :                 *best_d = d;
    3038        1986 :                 return;
    3039             :         }
    3040             : 
    3041           0 :         cmp = dns_cmp(*best_tln, tln);
    3042           0 :         if (cmp != DNS_CMP_FIRST_IS_CHILD) {
    3043           0 :                 return;
    3044             :         }
    3045             : 
    3046           0 :         *best_tln = tln;
    3047           0 :         *best_d = d;
    3048             : }
    3049             : 
    3050       21721 : const struct lsa_TrustDomainInfoInfoEx *dsdb_trust_routing_by_name(
    3051             :                 const struct dsdb_trust_routing_table *table,
    3052             :                 const char *name)
    3053             : {
    3054       21721 :         const struct dsdb_trust_routing_domain *best_d = NULL;
    3055       21721 :         const char *best_tln = NULL;
    3056       21721 :         const struct dsdb_trust_routing_domain *d = NULL;
    3057             : 
    3058       21721 :         if (name == NULL) {
    3059           0 :                 return NULL;
    3060             :         }
    3061             : 
    3062       51288 :         for (d = table->domains; d != NULL; d = d->next) {
    3063       30433 :                 bool transitive = false;
    3064       30433 :                 bool allow_netbios = false;
    3065       30433 :                 bool exclude = false;
    3066         623 :                 uint32_t i;
    3067             : 
    3068       30433 :                 if (d->tdo->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
    3069             :                         /*
    3070             :                          * Only uplevel trusts have top level names
    3071             :                          */
    3072        2199 :                         continue;
    3073             :                 }
    3074             : 
    3075       28234 :                 if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
    3076       21721 :                         transitive = true;
    3077             :                 }
    3078             : 
    3079       28234 :                 if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
    3080        2247 :                         transitive = true;
    3081             :                 }
    3082             : 
    3083       28234 :                 if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE) {
    3084           0 :                         transitive = false;
    3085             :                 }
    3086             : 
    3087       28234 :                 if (d->tdo->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
    3088           0 :                         transitive = false;
    3089             :                 }
    3090             : 
    3091       28234 :                 switch (d->tdo->trust_type) {
    3092       27611 :                 case LSA_TRUST_TYPE_UPLEVEL:
    3093       28234 :                         if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_UPLEVEL_ONLY) {
    3094           0 :                                 break;
    3095             :                         }
    3096       28234 :                         allow_netbios = true;
    3097       28234 :                         break;
    3098           0 :                 case LSA_TRUST_TYPE_DOWNLEVEL:
    3099           0 :                         allow_netbios = true;
    3100           0 :                         break;
    3101           0 :                 default:
    3102           0 :                         allow_netbios = false;
    3103           0 :                         break;
    3104             :                 }
    3105             : 
    3106       28234 :                 if (!transitive || d->fti == NULL) {
    3107           0 :                         int cmp;
    3108             : 
    3109        5164 :                         if (allow_netbios) {
    3110        5164 :                                 cmp = dns_cmp(name, d->tdo->netbios_name.string);
    3111        5164 :                                 if (cmp == DNS_CMP_MATCH) {
    3112             :                                         /*
    3113             :                                          * exact match
    3114             :                                          */
    3115         386 :                                         return d->tdo;
    3116             :                                 }
    3117             :                         }
    3118             : 
    3119        4778 :                         cmp = dns_cmp(name, d->tdo->domain_name.string);
    3120        4778 :                         if (cmp == DNS_CMP_MATCH) {
    3121             :                                 /*
    3122             :                                  * exact match
    3123             :                                  */
    3124         468 :                                 return d->tdo;
    3125             :                         }
    3126        4310 :                         if (cmp != DNS_CMP_FIRST_IS_CHILD) {
    3127        4308 :                                 continue;
    3128             :                         }
    3129             : 
    3130           2 :                         if (!transitive) {
    3131           2 :                                 continue;
    3132             :                         }
    3133             : 
    3134           0 :                         dsdb_trust_update_best_tln(&best_d, &best_tln, d,
    3135           0 :                                                    d->tdo->domain_name.string);
    3136           0 :                         continue;
    3137             :                 }
    3138             : 
    3139       23070 :                 exclude = dsdb_trust_find_tln_ex_match(d->fti, name);
    3140       22447 :                 if (exclude) {
    3141           0 :                         continue;
    3142             :                 }
    3143             : 
    3144       96044 :                 for (i = 0; i < d->fti->count; i++ ) {
    3145       72986 :                         const struct lsa_ForestTrustRecord *f = d->fti->entries[i];
    3146       72986 :                         const struct lsa_ForestTrustDomainInfo *di = NULL;
    3147       72986 :                         const char *fti_nbt = NULL;
    3148        2488 :                         int cmp;
    3149             : 
    3150       72986 :                         if (!allow_netbios) {
    3151           0 :                                 break;
    3152             :                         }
    3153             : 
    3154       72986 :                         if (f == NULL) {
    3155             :                                 /* broken record */
    3156           0 :                                 continue;
    3157             :                         }
    3158             : 
    3159       72986 :                         if (f->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
    3160       49916 :                                 continue;
    3161             :                         }
    3162             : 
    3163       23070 :                         if (f->flags & LSA_NB_DISABLED_MASK) {
    3164             :                                 /*
    3165             :                                  * any flag disables the entry.
    3166             :                                  */
    3167          28 :                                 continue;
    3168             :                         }
    3169             : 
    3170       23042 :                         di = &f->forest_trust_data.domain_info;
    3171       23042 :                         fti_nbt = di->netbios_domain_name.string;
    3172       23042 :                         if (fti_nbt == NULL) {
    3173             :                                 /* broken record */
    3174           0 :                                 continue;
    3175             :                         }
    3176             : 
    3177       23042 :                         cmp = dns_cmp(name, fti_nbt);
    3178       23042 :                         if (cmp == DNS_CMP_MATCH) {
    3179             :                                 /*
    3180             :                                  * exact match
    3181             :                                  */
    3182          12 :                                 return d->tdo;
    3183             :                         }
    3184             :                 }
    3185             : 
    3186       95996 :                 for (i = 0; i < d->fti->count; i++ ) {
    3187       72938 :                         const struct lsa_ForestTrustRecord *f = d->fti->entries[i];
    3188       72938 :                         const union lsa_ForestTrustData *u = NULL;
    3189       72938 :                         const char *fti_tln = NULL;
    3190        2488 :                         int cmp;
    3191             : 
    3192       72938 :                         if (f == NULL) {
    3193             :                                 /* broken record */
    3194           0 :                                 continue;
    3195             :                         }
    3196             : 
    3197       72938 :                         if (f->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
    3198       23070 :                                 continue;
    3199             :                         }
    3200             : 
    3201       49868 :                         if (f->flags & LSA_TLN_DISABLED_MASK) {
    3202             :                                 /*
    3203             :                                  * any flag disables the entry.
    3204             :                                  */
    3205         150 :                                 continue;
    3206             :                         }
    3207             : 
    3208       49718 :                         u = &f->forest_trust_data;
    3209       49718 :                         fti_tln = u->top_level_name.string;
    3210       49718 :                         if (fti_tln == NULL) {
    3211           0 :                                 continue;
    3212             :                         }
    3213             : 
    3214       49718 :                         cmp = dns_cmp(name, fti_tln);
    3215       49718 :                         switch (cmp) {
    3216        1986 :                         case DNS_CMP_MATCH:
    3217             :                         case DNS_CMP_FIRST_IS_CHILD:
    3218        4474 :                                 dsdb_trust_update_best_tln(&best_d, &best_tln,
    3219             :                                                            d, fti_tln);
    3220        1986 :                                 break;
    3221       45867 :                         default:
    3222       45867 :                                 break;
    3223             :                         }
    3224             :                 }
    3225             :         }
    3226             : 
    3227       20855 :         if (best_d != NULL) {
    3228        1986 :                 return best_d->tdo;
    3229             :         }
    3230             : 
    3231       18246 :         return NULL;
    3232             : }
    3233             : 
    3234         368 : const struct lsa_TrustDomainInfoInfoEx *dsdb_trust_domain_by_sid(
    3235             :                 const struct dsdb_trust_routing_table *table,
    3236             :                 const struct dom_sid *sid,
    3237             :                 const struct lsa_ForestTrustDomainInfo **pdi)
    3238             : {
    3239         368 :         const struct dsdb_trust_routing_domain *d = NULL;
    3240             : 
    3241         368 :         if (pdi != NULL) {
    3242         325 :                 *pdi = NULL;
    3243             :         }
    3244             : 
    3245         368 :         if (sid == NULL) {
    3246           0 :                 return NULL;
    3247             :         }
    3248             : 
    3249        1334 :         for (d = table->domains; d != NULL; d = d->next) {
    3250        1003 :                 bool transitive = false;
    3251           0 :                 uint32_t i;
    3252             : 
    3253        1003 :                 if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
    3254         368 :                         transitive = true;
    3255             :                 }
    3256             : 
    3257        1003 :                 if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
    3258         328 :                         transitive = true;
    3259             :                 }
    3260             : 
    3261        1003 :                 if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE) {
    3262           0 :                         transitive = false;
    3263             :                 }
    3264             : 
    3265        1003 :                 if (d->tdo->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
    3266           0 :                         transitive = false;
    3267             :                 }
    3268             : 
    3269        1003 :                 if (!transitive || d->fti == NULL) {
    3270         309 :                         bool match = false;
    3271             : 
    3272         309 :                         match = dom_sid_equal(d->di.domain_sid, sid);
    3273         309 :                         if (match) {
    3274             :                                 /*
    3275             :                                  * exact match, it's the domain itself.
    3276             :                                  */
    3277          13 :                                 if (pdi != NULL) {
    3278           6 :                                         *pdi = &d->di;
    3279             :                                 }
    3280          13 :                                 return d->tdo;
    3281             :                         }
    3282         296 :                         continue;
    3283             :                 }
    3284             : 
    3285        3432 :                 for (i = 0; i < d->fti->count; i++ ) {
    3286        2762 :                         const struct lsa_ForestTrustRecord *f = d->fti->entries[i];
    3287        2762 :                         const struct lsa_ForestTrustDomainInfo *di = NULL;
    3288        2762 :                         const struct dom_sid *fti_sid = NULL;
    3289        2762 :                         bool match = false;
    3290             : 
    3291        2762 :                         if (f == NULL) {
    3292             :                                 /* broken record */
    3293           0 :                                 continue;
    3294             :                         }
    3295             : 
    3296        2762 :                         if (f->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
    3297        2068 :                                 continue;
    3298             :                         }
    3299             : 
    3300         694 :                         if (f->flags & LSA_SID_DISABLED_MASK) {
    3301             :                                 /*
    3302             :                                  * any flag disables the entry.
    3303             :                                  */
    3304           0 :                                 continue;
    3305             :                         }
    3306             : 
    3307         694 :                         di = &f->forest_trust_data.domain_info;
    3308         694 :                         fti_sid = di->domain_sid;
    3309         694 :                         if (fti_sid == NULL) {
    3310             :                                 /* broken record */
    3311           0 :                                 continue;
    3312             :                         }
    3313             : 
    3314         694 :                         match = dom_sid_equal(fti_sid, sid);
    3315         694 :                         if (match) {
    3316             :                                 /*
    3317             :                                  * exact match, it's a domain in the forest.
    3318             :                                  */
    3319          24 :                                 if (pdi != NULL) {
    3320          20 :                                         *pdi = di;
    3321             :                                 }
    3322          24 :                                 return d->tdo;
    3323             :                         }
    3324             :                 }
    3325             :         }
    3326             : 
    3327         331 :         return NULL;
    3328             : }
    3329             : 
    3330         135 : const struct lsa_TrustDomainInfoInfoEx *dsdb_trust_domain_by_name(
    3331             :                 const struct dsdb_trust_routing_table *table,
    3332             :                 const char *name,
    3333             :                 const struct lsa_ForestTrustDomainInfo **pdi)
    3334             : {
    3335         135 :         const struct dsdb_trust_routing_domain *d = NULL;
    3336             : 
    3337         135 :         if (pdi != NULL) {
    3338         135 :                 *pdi = NULL;
    3339             :         }
    3340             : 
    3341         135 :         if (name == NULL) {
    3342           0 :                 return NULL;
    3343             :         }
    3344             : 
    3345         347 :         for (d = table->domains; d != NULL; d = d->next) {
    3346         322 :                 bool transitive = false;
    3347           0 :                 uint32_t i;
    3348             : 
    3349         322 :                 if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
    3350         135 :                         transitive = true;
    3351             :                 }
    3352             : 
    3353         322 :                 if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
    3354         113 :                         transitive = true;
    3355             :                 }
    3356             : 
    3357         322 :                 if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE) {
    3358           0 :                         transitive = false;
    3359             :                 }
    3360             : 
    3361         322 :                 if (d->tdo->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
    3362           0 :                         transitive = false;
    3363             :                 }
    3364             : 
    3365         322 :                 if (!transitive || d->fti == NULL) {
    3366          87 :                         bool match = false;
    3367             : 
    3368          87 :                         match = strequal_m(d->di.netbios_domain_name.string,
    3369             :                                            name);
    3370          87 :                         if (match) {
    3371             :                                 /*
    3372             :                                  * exact match for netbios name,
    3373             :                                  * it's the domain itself.
    3374             :                                  */
    3375          28 :                                 if (pdi != NULL) {
    3376          28 :                                         *pdi = &d->di;
    3377             :                                 }
    3378          28 :                                 return d->tdo;
    3379             :                         }
    3380          59 :                         match = strequal_m(d->di.dns_domain_name.string,
    3381             :                                            name);
    3382          59 :                         if (match) {
    3383             :                                 /*
    3384             :                                  * exact match for dns name,
    3385             :                                  * it's the domain itself.
    3386             :                                  */
    3387          28 :                                 if (pdi != NULL) {
    3388          28 :                                         *pdi = &d->di;
    3389             :                                 }
    3390          28 :                                 return d->tdo;
    3391             :                         }
    3392          31 :                         continue;
    3393             :                 }
    3394             : 
    3395        1057 :                 for (i = 0; i < d->fti->count; i++ ) {
    3396         876 :                         const struct lsa_ForestTrustRecord *f = d->fti->entries[i];
    3397         876 :                         const struct lsa_ForestTrustDomainInfo *di = NULL;
    3398         876 :                         bool match = false;
    3399             : 
    3400         876 :                         if (f == NULL) {
    3401             :                                 /* broken record */
    3402           0 :                                 continue;
    3403             :                         }
    3404             : 
    3405         876 :                         if (f->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
    3406         641 :                                 continue;
    3407             :                         }
    3408         235 :                         di = &f->forest_trust_data.domain_info;
    3409             : 
    3410         235 :                         if (!(f->flags & LSA_NB_DISABLED_MASK)) {
    3411         235 :                                 match = strequal_m(di->netbios_domain_name.string,
    3412             :                                                    name);
    3413         235 :                                 if (match) {
    3414             :                                         /*
    3415             :                                          * exact match for netbios name,
    3416             :                                          * it's a domain in the forest.
    3417             :                                          */
    3418          32 :                                         if (pdi != NULL) {
    3419          32 :                                                 *pdi = di;
    3420             :                                         }
    3421          32 :                                         return d->tdo;
    3422             :                                 }
    3423             :                         }
    3424             : 
    3425         203 :                         if (!(f->flags & LSA_TLN_DISABLED_MASK)) {
    3426         203 :                                 match = strequal_m(di->dns_domain_name.string,
    3427             :                                                    name);
    3428         203 :                                 if (match) {
    3429             :                                         /*
    3430             :                                          * exact match for dns name,
    3431             :                                          * it's a domain in the forest.
    3432             :                                          */
    3433          22 :                                         if (pdi != NULL) {
    3434          22 :                                                 *pdi = di;
    3435             :                                         }
    3436          22 :                                         return d->tdo;
    3437             :                                 }
    3438             :                         }
    3439             :                 }
    3440             :         }
    3441             : 
    3442          25 :         return NULL;
    3443             : }

Generated by: LCOV version 1.14