diff --git a/server/src/uds/osmanagers/WindowsOsManager/WinDomainOsManager.py b/server/src/uds/osmanagers/WindowsOsManager/WinDomainOsManager.py index 6f82775e9..43ded2fa7 100644 --- a/server/src/uds/osmanagers/WindowsOsManager/WinDomainOsManager.py +++ b/server/src/uds/osmanagers/WindowsOsManager/WinDomainOsManager.py @@ -14,6 +14,9 @@ from uds.core.ui.UserInterface import gui from uds.core.managers.CryptoManager import CryptoManager from uds.core import osmanagers from WindowsOsManager import WindowsOsManager, scrambleMsg +from uds.core.util import log +import dns.resolver +import ldap import logging @@ -26,7 +29,7 @@ class WinDomainOsManager(WindowsOsManager): iconFile = 'wosmanager.png' # Apart form data from windows os manager, we need also domain and credentials - domain = gui.TextField(length=64, label = _('Domain'), order = 1, tooltip = _('Domain to join machines to (better use dns form of domain)'), required = True) + domain = gui.TextField(length=64, label = _('Domain'), order = 1, tooltip = _('Domain to join machines to (use FQDN form, netbios name not allowed)'), required = True) account = gui.TextField(length=64, label = _('Account'), order = 2, tooltip = _('Account with rights to add machines to domain'), required = True) password = gui.PasswordField(length=64, label = _('Password'), order = 3, tooltip = _('Password of the account'), required = True) ou = gui.TextField(length=64, label = _('OU'), order = 4, tooltip = _('Organizational unit where to add machines in domain (check it before using it)')) @@ -38,6 +41,8 @@ class WinDomainOsManager(WindowsOsManager): if values != None: if values['domain'] == '': raise osmanagers.OSManager.ValidationException(_('Must provide a domain!!!')) + if values['domain'].find('.') == -1: + raise osmanagers.OSManager.ValidationException(_('Must provide domain in FQDN')) if values['account'] == '': raise osmanagers.OSManager.ValidationException(_('Must provide an account to add machines to domain!!!')) if values['password'] == '': @@ -51,10 +56,121 @@ class WinDomainOsManager(WindowsOsManager): self._ou = "" self._account = "" self._password = "" + + self._ou = self._ou.replace(' ', '') + if self._domain != '' and self._ou != '': + lpath = 'dc=' + ',dc='.join(self._domain.split('.')) + if self._ou.find(lpath) == -1: + 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.has_key('desc') and e.message['desc'] or '' + else : + _str += str(e) + return _str + + def __connectLdap(self): + ''' + Tries to connect to LDAP + Raises an exception if not found: + dns.resolver.NXDOMAIN + ldap.LDAPError + ''' + servers = reversed(sorted(dns.resolver.query('_ldap._tcp.'+self._domain, 'SRV'), key=lambda i: i.priority * 10000 + i.weight)) + + for server in servers: + + _str = '' + try: + uri = "%s://%s:%d" % ('ldap', str(server.target)[:-1], server.port) + logger.debug('URI: {0}'.format(uri)) + + ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER) # Disable certificate check + l = ldap.initialize(uri=uri) + l.set_option(ldap.OPT_REFERRALS, 0) + l.network_timeout = l.timeout = 5 + l.protocol_version = ldap.VERSION3 + + l.simple_bind_s(who = self._account+'@'+self._domain, cred = self._password) + + return l + except ldap.LDAPError as e: + _str = self.__getLdapError(e) + + raise ldap.LDAPError(_str) + def release(self, service): + ''' + service is a db user service object + ''' super(WinDomainOsManager,self).release(service) + + try: + ldap = self.__connectLdap() + except dns.resolver.NXDOMAIN: # No domain found, log it and pass + 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); + except ldap.LDAPError as e: + log.doLog(service, log.WARN, "Could not remove machine from domain (invalid credentials for {0})".format(self._account), log.OSMANAGER); + # TODO: remove machine from active directory os, under ou or default location if not specified + + def check(self): + try: + l = self.__connectLdap() + except ldap.LDAPError as e: + return _('Check error: {0}').format(self.__getLdapError(e)) + except dns.resolver.NXDOMAIN: + return [True, _('Could not find server parameters (_ldap._tcp.{0} can\'r be resolved)').format(self._domain)] + except Exception as e: + logger.exception('Exception ') + return [False, str(e)] + try: + r = l.search_st(self._ou, ldap.SCOPE_BASE) + except ldap.LDAPError as e: + return _('Check error: {0}').format(self.__getLdapError(e)) + + + return _('Server check was successful') + + + @staticmethod + def test(env, data): + logger.debug('Test invoked') + try: + wd = WinDomainOsManager(env, data) + logger.debug(wd) + try: + l = wd.__connectLdap() + except ldap.LDAPError as e: + return [False, _('Could not access AD using LDAP ({0})').format(wd.__getLdapError(e))] + + ou = wd._ou + if ou == '': + ou = 'cn=Computers,dc='+',dc='.join(wd._domain.split('.')) + + logger.debug('Checking {0} with ou {1}'.format(wd._domain,ou)) + r = l.search_st(ou, ldap.SCOPE_BASE) + logger.debug('Result of search: {0}'.format(r)) + + except ldap.LDAPError: + if wd._ou == '': + return [False, _('The default path {0} for computers was not found!!!').format(ou)] + else: + return [False, _('The ou path {0} was not found!!!').format(ou)] + except dns.resolver.NXDOMAIN: + return [True, _('Could not check parameters (_ldap._tcp.{0} can\'r be resolved)').format(wd._domain)] + except Exception as e: + logger.exception('Exception ') + return [False, str(e)] + + return [True, _("All parameters seems to work fine.")] + def infoVal(self, service): return 'domain:{0}\t{1}\t{2}\t{3}\t{4}'.format( self.getName(service), self._domain, self._ou, self._account, self._password) diff --git a/server/src/uds/xmlrpc/auths/AdminAuth.py b/server/src/uds/xmlrpc/auths/AdminAuth.py index c80a8cda6..0286262f2 100644 --- a/server/src/uds/xmlrpc/auths/AdminAuth.py +++ b/server/src/uds/xmlrpc/auths/AdminAuth.py @@ -111,7 +111,6 @@ def needs_credentials(xmlrpc_func): cred = validateCredentials(request, credentials) if cred is not None: logger.debug('Credentials valid, executing') - logger.debug('args: {0}'.format(args)) return xmlrpc_func(cred, *args, **kwargs) raise AuthException(_('Credentials no longer valid')) return _wrapped_xmlrcp_func diff --git a/server/src/uds/xmlrpc/stats/stats.py b/server/src/uds/xmlrpc/stats/stats.py index 668d72275..b1fb63b19 100644 --- a/server/src/uds/xmlrpc/stats/stats.py +++ b/server/src/uds/xmlrpc/stats/stats.py @@ -61,7 +61,7 @@ def getDeployedServiceCounters(credentials, id, counter_type, since, to, points, all = False val = [] for x in counters.getCounters(us, counter_type, since=since, to=to, limit=points, use_max=use_max, all=all): - val.append({ 'stamp': x[0], 'value': x[1] }) + val.append({ 'stamp': x[0], 'value': int(x[1]) }) if len(val) > 2: cache.put(cacheKey, cPickle.dumps(val).encode('zip'), 3600) else: