Updating windowmain to be functional on python2 & python3

This commit is contained in:
Adolfo Gómez García 2018-02-09 06:10:50 +01:00
parent 54136ae077
commit ca0fc6a61d
2 changed files with 69 additions and 65 deletions

View File

@ -43,6 +43,18 @@ from uds.core.util import tools
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class LDAPError(Exception):
@staticmethod
def reraise(e):
_str = _('Connection error: ')
if hasattr(e, 'message') and isinstance(e.message, dict):
_str += ', '.join((e.message.get('info', ''), e.message.get('desc')))
else:
_str += "{}".format(e)
raise LDAPError(_str)
def escape(value): def escape(value):
""" """
Escape filter chars for ldap search filter Escape filter chars for ldap search filter
@ -78,17 +90,12 @@ def connection(username, password, host, port=-1, ssl=False, timeout=3, debug=Fa
l.simple_bind_s(who=username, cred=password) l.simple_bind_s(who=username, cred=password)
except ldap.SERVER_DOWN: except ldap.SERVER_DOWN:
raise Exception(_('Can\'t contact LDAP server')) raise LDAPError(_('Can\'t contact LDAP server'))
except ldap.LDAPError as e: except ldap.LDAPError as e:
_str = _('Connection error: ') LDAPError.reraise(e)
if hasattr(e, 'message') and isinstance(e.message, dict): except Exception as e:
_str += ', '.join((e.message.get('info', ''), e.message.get('desc')))
else:
_str += "{}".format(e)
raise Exception(_str)
except Exception:
logger.exception('Exception connection:') logger.exception('Exception connection:')
raise raise LDAPError('{}'.format(e))
logger.debug('Conneciton was success') logger.debug('Conneciton was success')
return l return l
@ -104,13 +111,19 @@ def getAsDict(con, base, ldapFilter, attrList, sizeLimit, scope=ldap.SCOPE_SUBTR
if attrList is not None: if attrList is not None:
attrList = [tools.b2(i) for i in attrList] attrList = [tools.b2(i) for i in attrList]
# On python2, attrs and search string is str (not unicode), in 3, str (not bytes) try:
res = con.search_ext_s(base, # On python2, attrs and search string is str (not unicode), in 3, str (not bytes)
scope=scope, res = con.search_ext_s(base,
filterstr=tools.b2(ldapFilter), scope=scope,
attrlist=attrList, filterstr=tools.b2(ldapFilter),
sizelimit=sizeLimit attrlist=attrList,
) sizelimit=sizeLimit
)
except ldap.LDAPError as e:
LDAPError.reraise(e)
except Exception as e:
logger.exception('Exception connection:')
raise LDAPError('{}'.format(e))
logger.debug('Result of search {} on {}: {}'.format(ldapFilter, base, res)) logger.debug('Result of search {} on {}: {}'.format(ldapFilter, base, res))

View File

@ -17,6 +17,8 @@ from uds.core.managers.CryptoManager import CryptoManager
from uds.core import osmanagers from uds.core import osmanagers
from uds.core.util import log from uds.core.util import log
from uds.core.util import encoders from uds.core.util import encoders
from uds.core.util import ldaputil
import dns.resolver import dns.resolver
import ldap import ldap
from .WindowsOsManager import WindowsOsManager from .WindowsOsManager import WindowsOsManager
@ -76,16 +78,6 @@ class WinDomainOsManager(WindowsOsManager):
if self._ou.lower().find(lpath) == -1: if self._ou.lower().find(lpath) == -1:
self._ou += ',' + lpath self._ou += ',' + lpath
def __getLdapError(self, e):
logger.debug('Ldap Error: {0} {1}'.format(e, e.message))
_str = ''
if type(e.message) == dict:
# _str += e.message.has_key('info') and e.message['info'] + ',' or ''
_str += e.message.get('desc', '')
else:
_str += str(e)
return _str
def __getServerList(self): def __getServerList(self):
if self._serverHint != '': if self._serverHint != '':
yield (self._serverHint, 389) yield (self._serverHint, 389)
@ -98,61 +90,54 @@ class WinDomainOsManager(WindowsOsManager):
Tries to connect to LDAP Tries to connect to LDAP
Raises an exception if not found: Raises an exception if not found:
dns.resolver.NXDOMAIN dns.resolver.NXDOMAIN
ldap.LDAPError ldaputil.LDAPError
""" """
if servers is None: if servers is None:
servers = self.__getServerList() servers = self.__getServerList()
account = self._account
if account.find('@') == -1:
account += '@' + self._domain
_str = "No servers found" _str = "No servers found"
for server in servers: for server in servers:
_str = '' _str = ''
try: try:
uri = "%s://%s:%d" % ('ldap', server[0], server[1]) return ldaputil.connection(account, self._password, server[0], server[1], ssl=False, timeout=10, debug=False)
logger.debug('URI: {0}'.format(uri)) except Exception as e:
_str = 'Error: {}'.format(e)
ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER) # Disable certificate check raise ldaputil.LDAPError(_str)
l = ldap.initialize(uri=uri)
l.set_option(ldap.OPT_REFERRALS, 0)
l.network_timeout = l.timeout = 5
l.protocol_version = ldap.VERSION3
account = self._account
if account.find('@') == -1:
account += '@' + self._domain
logger.debug('Account data: {0}, {1}, {2}, {3}'.format(self._account, self._domain, account, self._password))
l.simple_bind_s(who=account, cred=self._password)
return l
except ldap.LDAPError as e:
_str = self.__getLdapError(e)
raise ldap.LDAPError(_str)
def __getGroup(self, l): def __getGroup(self, l):
base = ','.join(['DC=' + i for i in self._domain.split('.')]) base = ','.join(['DC=' + i for i in self._domain.split('.')])
group = self._group.replace('\\', '\\\\').replace('(', '\\(').replace(')', '\\)') group = ldaputil.escape(self._group)
try:
obj = next(ldaputil.getAsDict(l, base, "(&(objectClass=group)(|(cn={0})(sAMAccountName={0})))".format(group), ['dn'], sizeLimit=50))
except StopIteration:
obj = None
res = l.search_ext_s(base=base, scope=ldap.SCOPE_SUBTREE, filterstr="(&(objectClass=group)(|(cn={0})(sAMAccountName={0})))".format(group), attrlist=[b'dn']) if obj is None:
if res[0] is None:
return None return None
return res[0][0] # Returns the DN return obj['dn'] # Returns the DN
def __getMachine(self, l, machineName): def __getMachine(self, l, machineName):
if self._ou: if self._ou:
ou = self._ou base = self._ou
else: else:
ou = ','.join(['DC=' + i for i in self._domain.split('.')]) base = ','.join(['DC=' + i for i in self._domain.split('.')])
fltr = '(&(objectClass=computer)(sAMAccountName={}$))'.format(machineName) fltr = '(&(objectClass=computer)(sAMAccountName={}$))'.format(ldaputil.escape(machineName))
res = l.search_ext_s(base=ou, scope=ldap.SCOPE_SUBTREE, filterstr=fltr, attrlist=[b'dn']) try:
if res[0] is None: obj = next(ldaputil.getAsDict(l, base, fltr, ['dn'], sizeLimit=50))
except StopIteration:
obj = None
if obj is None:
return None return None
return res[0][0] # Returns the DN return obj['dn'] # Returns the DN
def readyReceived(self, userService, data): def readyReceived(self, userService, data):
# No group to add # No group to add
@ -173,6 +158,9 @@ class WinDomainOsManager(WindowsOsManager):
machine = self.__getMachine(l, userService.friendly_name) machine = self.__getMachine(l, userService.friendly_name)
group = self.__getGroup(l) group = self.__getGroup(l)
# #
# Direct LDAP operation "modify", maybe this need to be added to ldaputil? :)
# #
l.modify_s(group, ((ldap.MOD_ADD, 'member', machine),)) l.modify_s(group, ((ldap.MOD_ADD, 'member', machine),))
error = None error = None
break break
@ -183,7 +171,7 @@ class WinDomainOsManager(WindowsOsManager):
# Already added this machine to this group, pass # Already added this machine to this group, pass
error = None error = None
break break
except ldap.LDAPError: except ldaputil.LDAPError:
logger.exception('Ldap Exception caught') logger.exception('Ldap Exception caught')
error = "Could not remove machine from domain (invalid credentials for {0})".format(self._account) error = "Could not remove machine from domain (invalid credentials for {0})".format(self._account)
except Exception as e: except Exception as e:
@ -210,7 +198,7 @@ class WinDomainOsManager(WindowsOsManager):
logger.warn('Could not find _ldap._tcp.' + self._domain) logger.warn('Could not find _ldap._tcp.' + self._domain)
log.doLog(service, log.WARN, "Could not remove machine from domain (_ldap._tcp.{0} not found)".format(self._domain), log.OSMANAGER) log.doLog(service, log.WARN, "Could not remove machine from domain (_ldap._tcp.{0} not found)".format(self._domain), log.OSMANAGER)
return return
except ldap.LDAPError: except ldaputil.LDAPError:
logger.exception('Ldap Exception caught') logger.exception('Ldap Exception caught')
log.doLog(service, log.WARN, "Could not remove machine from domain (invalid credentials for {0})".format(self._account), log.OSMANAGER) log.doLog(service, log.WARN, "Could not remove machine from domain (invalid credentials for {0})".format(self._account), log.OSMANAGER)
return return
@ -222,6 +210,9 @@ class WinDomainOsManager(WindowsOsManager):
res = self.__getMachine(l, service.friendly_name) res = self.__getMachine(l, service.friendly_name)
if res is None: if res is None:
raise Exception('Machine {} not found on AD (permissions?)'.format(service.friendly_name)) raise Exception('Machine {} not found on AD (permissions?)'.format(service.friendly_name))
# #
# Direct LDAP operation "modify", maybe this need to be added to ldaputil? :)
# #
l.delete_s(res) # Remove by DN, SYNC l.delete_s(res) # Remove by DN, SYNC
except IndexError: except IndexError:
logger.error('Error deleting {} from BASE {}'.format(service.friendly_name, self._ou)) logger.error('Error deleting {} from BASE {}'.format(service.friendly_name, self._ou))
@ -231,7 +222,7 @@ class WinDomainOsManager(WindowsOsManager):
def check(self): def check(self):
try: try:
l = self.__connectLdap() l = self.__connectLdap()
except ldap.LDAPError as e: except ldaputil.LDAPError as e:
return _('Check error: {0}').format(self.__getLdapError(e)) return _('Check error: {0}').format(self.__getLdapError(e))
except dns.resolver.NXDOMAIN: except dns.resolver.NXDOMAIN:
return [True, _('Could not find server parameters (_ldap._tcp.{0} can\'t be resolved)').format(self._domain)] return [True, _('Could not find server parameters (_ldap._tcp.{0} can\'t be resolved)').format(self._domain)]
@ -241,7 +232,7 @@ class WinDomainOsManager(WindowsOsManager):
try: try:
l.search_st(self._ou, ldap.SCOPE_BASE) l.search_st(self._ou, ldap.SCOPE_BASE)
except ldap.LDAPError as e: except ldaputil.LDAPError as e:
return _('Check error: {0}').format(self.__getLdapError(e)) return _('Check error: {0}').format(self.__getLdapError(e))
# Group # Group
@ -260,7 +251,7 @@ class WinDomainOsManager(WindowsOsManager):
logger.debug(wd) logger.debug(wd)
try: try:
l = wd.__connectLdap() l = wd.__connectLdap()
except ldap.LDAPError as e: except ldaputil.LDAPError as e:
return [False, _('Could not access AD using LDAP ({0})').format(wd.__getLdapError(e))] return [False, _('Could not access AD using LDAP ({0})').format(wd.__getLdapError(e))]
ou = wd._ou ou = wd._ou
@ -271,7 +262,7 @@ class WinDomainOsManager(WindowsOsManager):
r = l.search_st(ou, ldap.SCOPE_BASE) r = l.search_st(ou, ldap.SCOPE_BASE)
logger.debug('Result of search: {0}'.format(r)) logger.debug('Result of search: {0}'.format(r))
except ldap.LDAPError: except ldaputil.LDAPError:
if wd._ou == '': if wd._ou == '':
return [False, _('The default path {0} for computers was not found!!!').format(wd._ou)] return [False, _('The default path {0} for computers was not found!!!').format(wd._ou)]
else: else: