]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s4:dsdb: fix logic of dsdb_trust_routing_by_name()
authorStefan Metzmacher <metze@samba.org>
Tue, 7 Jan 2025 13:06:43 +0000 (14:06 +0100)
committerJule Anger <janger@samba.org>
Thu, 9 Jan 2025 09:56:59 +0000 (09:56 +0000)
We need to use the longest dnsname match as possible.

If we are the domain samba.example.com and have a trust
to example.com, a routing request for dc.samba.example.com
should return the tdo for samba.example.com instead
of example.com.

I reproduced the problem with the following diff:

> diff --git a/selftest/target/Samba.pm b/selftest/target/Samba.pm
> index 15d7692b5d64..6e9595b784c4 100644
> --- a/selftest/target/Samba.pm
> +++ b/selftest/target/Samba.pm
> @@ -564,7 +564,7 @@ sub realm_to_ip_mappings
>   'samba2000.example.com'           => 'dc5',
>   'samba2003.example.com'           => 'dc6',
>   'samba2008r2.example.com'         => 'dc7',
> - 'addom.samba.example.com'         => 'addc',
> + 'addom.samba2008r2.example.com'         => 'addc',
>   'addom2.samba.example.com'        => 'addcsmb1',
>   'sub.samba.example.com'           => 'localsubdc',
>   'chgdcpassword.samba.example.com' => 'chgdcpass',
> diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm
> index 0e4cf50235c3..6bca0cfd0c89 100755
> --- a/selftest/target/Samba4.pm
> +++ b/selftest/target/Samba4.pm
> @@ -2631,7 +2631,7 @@ sub setup_fl2008r2dc
>       return undef;
>   }
>
> - $env = $self->setup_trust($env, $ad_dc_vars, "forest", "");
> + $env = $self->setup_trust($env, $ad_dc_vars, "forest", "--skip-validation");
>   if (!defined $env) {
>       return undef;
>   }
> @@ -2843,7 +2843,7 @@ sub _setup_ad_dc
>   $server = "addc";
>   }
>   if (!defined($dom)) {
> - $dom = "addom.samba.example.com";
> + $dom = "addom.samba2008r2.example.com";
>   }
>   my $env = $self->provision_ad_dc($path, $server, "ADDOMAIN",
>    $dom,

and running:
 make -j testenv SELFTEST_TESTENV="fl2008r2dc:local"

Inside the testenv:
bin/smbclient //addc.addom.samba2008r2.example.com/netlogon \
  -U$TRUST_USERNAME@$TRUST_REALM%$TRUST_PASSWORD \
  --use-kerberos=required \
  -c 'ls'

It lets the KDC of ADDOM.SAMBA2008R2.EXAMPLE.COM to
generate a (referral) ticket for
krbtgt/SAMBA2008R2.EXAMPLE.COM@ADDOM.SAMBA2008R2.EXAMPLE.COM
instead of
cifs/addc.addom.samba2008r2.example.com@ADDOM.SAMBA2008R2.EXAMPLE.COM

As ADDOM.SAMBA2008R2.EXAMPLE.COM has a forest trust (without msDS-TrustForestTrustInfo)
to SAMBA2008R2.EXAMPLE.COM dsdb_trust_update_best_tln() overwrote the
best match of addom.samba2008r2.example.com with samba2008r2.example.com.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15778

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Autobuild-User(master): Douglas Bagnall <dbagnall@samba.org>
Autobuild-Date(master): Wed Jan  8 04:14:47 UTC 2025 on atb-devel-224

(cherry picked from commit 56947612452c32bd26f30ad6c9767830fe608d67)

Autobuild-User(v4-20-test): Jule Anger <janger@samba.org>
Autobuild-Date(v4-20-test): Thu Jan  9 09:56:59 UTC 2025 on atb-devel-224

source4/dsdb/common/util_trusts.c

index 34a836a6a6f21f11c0d237a0a3c8049049520839..c1797e3138edc1b4ddb42e07aab66c7dd2bcc240 100644 (file)
@@ -3038,7 +3038,7 @@ static void dsdb_trust_update_best_tln(
                return;
        }
 
-       cmp = dns_cmp(*best_tln, tln);
+       cmp = dns_cmp(tln, *best_tln);
        if (cmp != DNS_CMP_FIRST_IS_CHILD) {
                return;
        }
@@ -3127,10 +3127,6 @@ const struct lsa_TrustDomainInfoInfoEx *dsdb_trust_routing_by_name(
                                continue;
                        }
 
-                       if (!transitive) {
-                               continue;
-                       }
-
                        dsdb_trust_update_best_tln(&best_d, &best_tln, d,
                                                   d->tdo->domain_name.string);
                        continue;
@@ -3212,15 +3208,19 @@ const struct lsa_TrustDomainInfoInfoEx *dsdb_trust_routing_by_name(
                        }
 
                        cmp = dns_cmp(name, fti_tln);
-                       switch (cmp) {
-                       case DNS_CMP_MATCH:
-                       case DNS_CMP_FIRST_IS_CHILD:
-                               dsdb_trust_update_best_tln(&best_d, &best_tln,
-                                                          d, fti_tln);
-                               break;
-                       default:
-                               break;
+                       if (cmp == DNS_CMP_MATCH) {
+                               /*
+                                * exact match
+                                */
+                               return d->tdo;
                        }
+                       if (cmp != DNS_CMP_FIRST_IS_CHILD) {
+                               continue;
+                       }
+
+                       dsdb_trust_update_best_tln(&best_d, &best_tln,
+                                                  d, fti_tln);
+                       continue;
                }
        }