diff options
Diffstat (limited to 'ipaserver/dcerpc.py')
-rw-r--r-- | ipaserver/dcerpc.py | 75 |
1 files changed, 60 insertions, 15 deletions
diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py index 6b830f65b..982e12b31 100644 --- a/ipaserver/dcerpc.py +++ b/ipaserver/dcerpc.py @@ -28,6 +28,7 @@ from ipalib.parameters import Enum from ipalib import Command from ipalib import errors from ipapython import ipautil +from ipapython.ipa_log_manager import * from ipaserver.install import installutils import os, string, struct, copy @@ -49,6 +50,31 @@ The code in this module relies heavily on samba4-python package and Samba4 python bindings. """) +access_denied_error = errors.ACIError(info='CIFS server denied your credentials') +dcerpc_error_codes = { + -1073741823: errors.RemoteRetrieveError(reason='communication with CIFS server was unsuccessful'), + -1073741790: access_denied_error, + -1073741715: access_denied_error, + -1073741614: access_denied_error, + -1073741603: errors.ValidationError(name='AD domain controller', error='unsupported functional level'), +} + +dcerpc_error_messages = { + "NT_STATUS_OBJECT_NAME_NOT_FOUND": errors.NotFound(reason='Cannot find specified domain or server name'), + "NT_STATUS_INVALID_PARAMETER_MIX": errors.RequirementError(name='At least the domain or IP address should be specified'), +} + +def assess_dcerpc_exception(num=None,message=None): + """ + Takes error returned by Samba bindings and converts it into + an IPA error class. + """ + if num and num in dcerpc_error_codes: + return dcerpc_error_codes[num] + if message and message in dcerpc_error_messages: + return dcerpc_error_messages[message] + return errors.RemoteRetrieveError(reason='CIFS server communication error: code "%s", message "%s" (both may be "None")' % (num, message)) + class ExtendedDNControl(_ldap.controls.RequestControl): def __init__(self): self.controlType = "1.2.840.113556.1.4.529" @@ -151,8 +177,8 @@ class TrustDomainInstance(object): try: result = lsa.lsarpc(binding, self.parm, self.creds) return result - except: - return None + except RuntimeError, (num, message): + raise assess_dcerpc_exception(num=num, message=message) def __init_lsa_pipe(self, remote_host): """ @@ -168,13 +194,21 @@ class TrustDomainInstance(object): if self._pipe: return + attempts = 0 bindings = self.__gen_lsa_bindings(remote_host) for binding in bindings: - self._pipe = self.__gen_lsa_connection(binding) - if self._pipe: - break + try: + self._pipe = self.__gen_lsa_connection(binding) + if self._pipe: + break + except errors.ACIError, e: + attempts = attempts + 1 + + if self._pipe is None and attempts == len(bindings): + raise errors.ACIError(info='CIFS server %s denied your credentials' % (remote_host)) + if self._pipe is None: - raise errors.RequirementError(name='Working LSA pipe') + raise errors.RemoteRetrieveError(reason='Cannot establish LSA connection to %s. Is CIFS server running?' % (remote_host)) def __gen_lsa_bindings(self, remote_host): """ @@ -195,10 +229,14 @@ class TrustDomainInstance(object): When retrieving DC information anonymously, we can't get SID of the domain """ netrc = net.Net(creds=self.creds, lp=self.parm) - if discover_srv: - result = netrc.finddc(domain=remote_host, flags=nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS) - else: - result = netrc.finddc(address=remote_host, flags=nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS) + try: + if discover_srv: + result = netrc.finddc(domain=remote_host, flags=nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS) + else: + result = netrc.finddc(address=remote_host, flags=nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS) + except RuntimeError, e: + raise assess_dcerpc_exception(message=str(e)) + if not result: return False self.info['name'] = unicode(result.domain_name) @@ -217,7 +255,7 @@ class TrustDomainInstance(object): result = res['defaultNamingContext'][0] self.info['dns_hostname'] = res['dnsHostName'][0] except _ldap.LDAPError, e: - print "LDAP error when connecting to %s: %s" % (unicode(result.pdc_name), str(e)) + root_logger.error("LDAP error when connecting to %s: %s" % (unicode(result.pdc_name), str(e))) if result: self.info['sid'] = self.parse_naming_context(result) @@ -232,8 +270,12 @@ class TrustDomainInstance(object): objectAttribute = lsa.ObjectAttribute() objectAttribute.sec_qos = lsa.QosInfo() - self._policy_handle = self._pipe.OpenPolicy2(u"", objectAttribute, security.SEC_FLAG_MAXIMUM_ALLOWED) - result = self._pipe.QueryInfoPolicy2(self._policy_handle, lsa.LSA_POLICY_INFO_DNS) + try: + self._policy_handle = self._pipe.OpenPolicy2(u"", objectAttribute, security.SEC_FLAG_MAXIMUM_ALLOWED) + result = self._pipe.QueryInfoPolicy2(self._policy_handle, lsa.LSA_POLICY_INFO_DNS) + except RuntimeError, (num, message): + raise assess_dcerpc_exception(num=num, message=message) + self.info['name'] = unicode(result.name.string) self.info['dns_domain'] = unicode(result.dns_domain.string) self.info['dns_forest'] = unicode(result.dns_forest.string) @@ -315,9 +357,12 @@ class TrustDomainInstance(object): dname.string = another_domain.info['dns_domain'] res = self._pipe.QueryTrustedDomainInfoByName(self._policy_handle, dname, lsa.LSA_TRUSTED_DOMAIN_INFO_FULL_INFO) self._pipe.DeleteTrustedDomain(self._policy_handle, res.info_ex.sid) - except: + except RuntimeError, e: pass - self._pipe.CreateTrustedDomainEx2(self._policy_handle, info, self.auth_info, security.SEC_STD_DELETE) + try: + self._pipe.CreateTrustedDomainEx2(self._policy_handle, info, self.auth_info, security.SEC_STD_DELETE) + except RuntimeError, (num, message): + raise assess_dcerpc_exception(num=num, message=message) class TrustDomainJoins(object): def __init__(self, api): |