From 8afb17ff98b35057b176fe93ae5c48048726566f Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy 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 --- 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 52c70acfacc..1f6b7ce40ab 100644 --- a/python/samba/netcmd/domain.py +++ b/python/samba/netcmd/domain.py @@ -1662,6 +1662,7 @@ def __init__(self): 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 @@ -1726,16 +1727,39 @@ def setup_local_server(self, sambaopts, localdcopts): 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 self.local_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, @@ -1803,15 +1827,19 @@ def setup_remote_server(self, credopts, domain, 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() From 2ff7f035d257c3af33ec4db940379510c91caadc Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Sat, 24 Feb 2018 14:34:44 +0200 Subject: [PATCH 2/2] samba-tool trust: support discovery via own domain controller In case a remote DC does not support netr_DsRGetDCNameEx2(), re-route the call via our DC to try CLDAP 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 --- python/samba/netcmd/domain.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/python/samba/netcmd/domain.py b/python/samba/netcmd/domain.py index 1f6b7ce40ab..e4a8f5fda68 100644 --- a/python/samba/netcmd/domain.py +++ b/python/samba/netcmd/domain.py @@ -2488,7 +2488,11 @@ def random_trust_secret(length): try: remote_netlogon_info = self.get_netlogon_dc_info(remote_netlogon, remote_server) except RuntimeError as error: - raise self.RemoteRuntimeError(self, error, "failed to get netlogon dc info") + # Direct connection failed, re-try via our DC + try: + remote_netlogon_info = self.get_netlogon_dc_info(local_netlogon, remote_server) + except RuntimeError as error: + raise self.RemoteRuntimeError(self, error, "failed to get netlogon dc info") def generate_AuthInOutBlob(secret, update_time): if secret is None: