[PR PATCH] [Updated] samba-tool domain trust: fix trust compatibility to Windows Server 1709 and FreeIPA

Alexander Bokovoy ab at samba.org
Thu Mar 1 06:41:24 UTC 2018


On to, 01 maalis 2018, Stefan Metzmacher wrote:
> Hi Alexander,
> 
> >>> The Travis CI build doesn't run much tests, so this was completely
> >>> untested.
> >>>
> >>> I'll push it with the attached modification:
> >> You picked older version.
> >>
> >> These are the changes that are in the pull request already. I pushed
> >> them second time after Travis CI actually failed.
> > Silly me, sorry! I thought I pushed all of them but I only pushed part
> > with 'def ..' fixes.
> > 
> > Please push with the modification, thanks!
> 
> I thought a bit more about the
> "support discovery via own domain controller" patch.
> 
> As we only use remote_netlogon_info.dc_unc can we
> add get_netlogon_dc_unc() that falls back to netr_GetDcName()
> against the remote dc.
> 
> That would also help if we try to implement trusts against
> an NT4 style domain.
Makes sense. Updated patches attached.


-- 
/ Alexander Bokovoy
-------------- next part --------------
>From ea6c9bd62793072b31d6c4a59f6d0828db0de163 Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <ab at samba.org>
Date: Sat, 24 Feb 2018 13:12:20 +0200
Subject: [PATCH 1/2] samba-tool domain trust: allow using smb2 by default

Windows Server 1709 defaults to SMB2 and does not have SMB1 enabled.
When establishing trust, samba-tool does not specify SMB protocol
version and fail by default.

We have two ways to handle this situation:
 - switch 'client ipc min protocol' to 'SMB2' or later
 - explicitly specify 'smb2' to binding options and retry

Using first approach would be better in a longer term but right now Samba
defaults to 'CORE' in 'client min protocol' and changing it would deny
connecting to older SMB servers.

Another way is to explicitly specify a protocol in a binding string and
fall back to a default if connection fails. A similar approach is used
by the FreeIPA trust code for several years.

Signed-off-by: Alexander Bokovoy <ab at samba.org>
---
 python/samba/netcmd/domain.py | 40 ++++++++++++++++++++++++++++++++++------
 1 file changed, 34 insertions(+), 6 deletions(-)

diff --git a/python/samba/netcmd/domain.py b/python/samba/netcmd/domain.py
index 7b23fa794de..c5a449a8493 100644
--- a/python/samba/netcmd/domain.py
+++ b/python/samba/netcmd/domain.py
@@ -1666,6 +1666,7 @@ class DomainTrustCommand(Command):
         self.remote_server = None
         self.remote_binding_string = None
         self.remote_creds = None
+        self.protocol_options = ['smb2', '']
 
     def _uint32(self, v):
         return ctypes.c_uint32(v).value
@@ -1730,16 +1731,39 @@ class DomainTrustCommand(Command):
         self.local_lp = lp
 
         self.local_server = local_server
-        self.local_binding_string = "%s:%s[%s]" % (local_transport, local_server, local_binding_options)
+        self.local_bindings = ["%s:%s[%s%s]" % (local_transport, local_server,
+                                                protocol, local_binding_options)
+                               for protocol in self.protocol_options]
         self.local_ldap_url = local_ldap_url
         self.local_creds = local_creds
         return self.local_server
 
+    def _get_connection(self, connect_func, lp, creds, bindings):
+        """ _get_connection: try to generate a valid connection
+                             using multiple bindings to allow
+                             protocol fallbacks
+        """
+        bnd = None
+        last_exc = None
+        for binding in bindings:
+            try:
+                bnd = connect_func(binding, lp, creds)
+                if bnd is not None:
+                    break
+            except NTSTATUSError as error:
+                last_exc = error
+                continue
+        if bnd is None:
+            raise last_exc
+        return bnd
+
     def new_local_lsa_connection(self):
-        return lsa.lsarpc(self.local_binding_string, self.local_lp, self.local_creds)
+        return self._get_connection(lsa.lsarpc, self.local_lp,
+                                    self.local_creds, self.local_bindings)
 
     def new_local_netlogon_connection(self):
-        return netlogon.netlogon(self.local_binding_string, self.local_lp, self.local_creds)
+        return self._get_connection(netlogon.netlogon, self.local_lp,
+                                    self.local_creds, self.local_bindings)
 
     def new_local_ldap_connection(self):
         return SamDB(url=self.local_ldap_url,
@@ -1807,15 +1831,19 @@ class DomainTrustCommand(Command):
                         server_type_string))
 
         self.remote_server = remote_info.pdc_dns_name
-        self.remote_binding_string="ncacn_np:%s[%s]" % (self.remote_server, remote_binding_options)
+        self.remote_bindings = ["ncacn_np:%s[%s%s]" % (self.remote_server, protocol,
+                                                       remote_binding_options)
+                                for protocol in self.protocol_options]
         self.remote_creds = remote_creds
         return self.remote_server
 
     def new_remote_lsa_connection(self):
-        return lsa.lsarpc(self.remote_binding_string, self.local_lp, self.remote_creds)
+        return self._get_connection(lsa.lsarpc, self.local_lp,
+                                    self.remote_creds, self.remote_bindings)
 
     def new_remote_netlogon_connection(self):
-        return netlogon.netlogon(self.remote_binding_string, self.local_lp, self.remote_creds)
+        return self._get_connection(netlogon.netlogon, self.local_lp,
+                                    self.remote_creds, self.remote_bindings)
 
     def get_lsa_info(self, conn, policy_access):
         objectAttr = lsa.ObjectAttribute()
-- 
2.14.3


>From 8e4245df78753a0ee01acc7267fe6f1017750793 Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <ab at samba.org>
Date: Sat, 24 Feb 2018 14:34:44 +0200
Subject: [PATCH 2/2] samba-tool trust: support discovery via netr_GetDcName

In case a remote DC does not support netr_DsRGetDCNameEx2(),
use netr_GetDcName() instead.

This should help with FreeIPA where embedded smbd runs as a domain
controller but does not implement full Active Directory compatibility.

Signed-off-by: Alexander Bokovoy <ab at samba.org>
---
 python/samba/netcmd/domain.py | 26 ++++++++++++++++++--------
 1 file changed, 18 insertions(+), 8 deletions(-)

diff --git a/python/samba/netcmd/domain.py b/python/samba/netcmd/domain.py
index c5a449a8493..48f454c8f77 100644
--- a/python/samba/netcmd/domain.py
+++ b/python/samba/netcmd/domain.py
@@ -1856,6 +1856,15 @@ class DomainTrustCommand(Command):
 
         return (policy, info)
 
+    def get_netlogon_dc_unc(self, conn, server, domain):
+        try:
+            info = conn.netr_DsRGetDCNameEx2(server,
+                                             None, 0, None, None, None,
+                                             netlogon.DS_RETURN_DNS_NAME)
+            return info.dc_unc
+        except RuntimeError:
+            return conn.netr_GetDcName(server, domain)
+
     def get_netlogon_dc_info(self, conn, server):
         info = conn.netr_DsRGetDCNameEx2(server,
                                          None, 0, None, None, None,
@@ -2490,7 +2499,8 @@ class cmd_domain_trust_create(DomainTrustCommand):
                 raise self.RemoteRuntimeError(self, error, "failed to connect netlogon server")
 
             try:
-                remote_netlogon_info = self.get_netlogon_dc_info(remote_netlogon, remote_server)
+                remote_netlogon_dc_unc = self.get_netlogon_dc_unc(remote_netlogon,
+                                                                  remote_server, domain)
             except RuntimeError as error:
                 raise self.RemoteRuntimeError(self, error, "failed to get netlogon dc info")
 
@@ -2640,9 +2650,9 @@ class cmd_domain_trust_create(DomainTrustCommand):
                         # this triggers netr_GetForestTrustInformation to our domain.
                         # and lsaRSetForestTrustInformation() remotely, but new top level
                         # names are disabled by default.
-                        remote_forest_info = remote_netlogon.netr_DsRGetForestTrustInformation(remote_netlogon_info.dc_unc,
-                                                                      local_lsa_info.dns_domain.string,
-                                                                      netlogon.DS_GFTI_UPDATE_TDO)
+                        remote_forest_info = remote_netlogon.netr_DsRGetForestTrustInformation(remote_netlogon_dc_unc,
+                                                                                               local_lsa_info.dns_domain.string,
+                                                                                               netlogon.DS_GFTI_UPDATE_TDO)
                     except RuntimeError as error:
                         raise self.RemoteRuntimeError(self, error, "netr_DsRGetForestTrustInformation() failed")
 
@@ -2693,10 +2703,10 @@ class cmd_domain_trust_create(DomainTrustCommand):
                 if remote_trust_info.trust_direction & lsa.LSA_TRUST_DIRECTION_OUTBOUND:
                     self.outf.write("Validating incoming trust...\n")
                     try:
-                        remote_trust_verify = remote_netlogon.netr_LogonControl2Ex(remote_netlogon_info.dc_unc,
-                                                                      netlogon.NETLOGON_CONTROL_TC_VERIFY,
-                                                                      2,
-                                                                      local_lsa_info.dns_domain.string)
+                        remote_trust_verify = remote_netlogon.netr_LogonControl2Ex(remote_netlogon_dc_unc,
+                                                                                   netlogon.NETLOGON_CONTROL_TC_VERIFY,
+                                                                                   2,
+                                                                                   local_lsa_info.dns_domain.string)
                     except RuntimeError as error:
                         raise self.RemoteRuntimeError(self, error, "NETLOGON_CONTROL_TC_VERIFY failed")
 
-- 
2.14.3



More information about the samba-technical mailing list