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

Generated by: LCOV version 1.14