From 2716707952a0e4daa76b035a6a278d297cb4e0fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20G=C3=B3mez?= Date: Mon, 3 Dec 2012 09:43:12 +0000 Subject: [PATCH] Fixing up core so we can provide some kind of access using Thin Clients or Software clients not using web & html --- .../org.eclipse.core.resources.prefs | 3 ++ server/src/uds/auths/IP/Authenticator.py | 7 +++ .../src/uds/core/auths/BaseAuthenticator.py | 45 ++++++++++++++++++- server/src/uds/core/auths/auth.py | 9 +++- .../src/uds/core/transports/BaseTransport.py | 27 +++++++++++ .../transports/{Protocols.py => protocols.py} | 0 server/src/uds/dispatchers/pam/urls.py | 4 +- 7 files changed, 90 insertions(+), 5 deletions(-) rename server/src/uds/core/transports/{Protocols.py => protocols.py} (100%) diff --git a/server/.settings/org.eclipse.core.resources.prefs b/server/.settings/org.eclipse.core.resources.prefs index e125f364f..1d2c36cb8 100644 --- a/server/.settings/org.eclipse.core.resources.prefs +++ b/server/.settings/org.eclipse.core.resources.prefs @@ -70,6 +70,7 @@ encoding//src/uds/core/services/__init__.py=utf-8 encoding//src/uds/core/transports/BaseTransport.py=utf-8 encoding//src/uds/core/transports/TransportsFactory.py=utf-8 encoding//src/uds/core/transports/__init__.py=utf-8 +encoding//src/uds/core/transports/protocols.py=utf-8 encoding//src/uds/core/ui/UserInterface.py=utf-8 encoding//src/uds/core/util/AutoAttributes.py=utf-8 encoding//src/uds/core/util/Cache.py=utf-8 @@ -94,6 +95,8 @@ encoding//src/uds/dispatchers/pam/urls.py=utf-8 encoding//src/uds/dispatchers/pam/views.py=utf-8 encoding//src/uds/dispatchers/test/urls.py=utf-8 encoding//src/uds/dispatchers/test/views.py=utf-8 +encoding//src/uds/dispatchers/wyse_enterprise/urls.py=utf-8 +encoding//src/uds/dispatchers/wyse_enterprise/views.py=utf-8 encoding//src/uds/management/commands/config.py=utf-8 encoding//src/uds/management/commands/taskManager.py=utf-8 encoding//src/uds/management/commands/taskManager_enterprise.py=utf-8 diff --git a/server/src/uds/auths/IP/Authenticator.py b/server/src/uds/auths/IP/Authenticator.py index 34b9d60bb..826c3dd35 100644 --- a/server/src/uds/auths/IP/Authenticator.py +++ b/server/src/uds/auths/IP/Authenticator.py @@ -84,12 +84,19 @@ class IPAuth(Authenticator): groupsManager.validate(g) def authenticate(self, username, credentials, groupsManager): + # If credentials is a dict, that can't be sent directly from web interface, we allow entering + # We use this "trick" so authenticators if self.cache().get(username) == credentials: self.cache().remove(username) self.getGroups(username, groupsManager) return True return False + def internalAuthenticate(self,username, credentials, groupsManager): + self.getGroups(username, groupsManager) + if len(groupsManager.getValidGroups()) > 0 and self.dbAuthenticator().isValidUser(username, True): + return True + return False @staticmethod def test(env, data): diff --git a/server/src/uds/core/auths/BaseAuthenticator.py b/server/src/uds/core/auths/BaseAuthenticator.py index 348a90c2e..2d44d2c48 100644 --- a/server/src/uds/core/auths/BaseAuthenticator.py +++ b/server/src/uds/core/auths/BaseAuthenticator.py @@ -219,6 +219,13 @@ class Authenticator(Module): ''' return cls.getHtml != Authenticator.getHtml + @classmethod + def canCheckUserPassword(cls): + ''' + Helper method to query if a class can do a login using credentials + ''' + return cls.authenticate != Authenticator.authenticate + def searchUsers(self, pattern): ''' If you provide this method, the user will be allowed to search users, @@ -275,7 +282,7 @@ class Authenticator(Module): Args: username: User name to authenticate - credentilas: Credentials for this user, (password, pki, or whatever needs to be used) + credentilas: Credentials for this user, (password, pki, or whatever needs to be used). (string) groupManager: Group manager to modify with groups to which this users belongs to. Returns: @@ -295,6 +302,42 @@ class Authenticator(Module): ''' return False + def internalAuthenticate(self,username, credentials, groupsManager): + ''' + This method is provided so "plugins" (For example, a custom dispatcher), can test + the username/credentials in an alternative way. + + For example, ip authenticator generates, inside the custom html, a 1 time password + that will be used to authenticate the ip. If we create a custom dispatcher and we want + to auth the user without the html part being displayed, we have a big problem. + + Using this method, the authenticator has the oportunitiy to, (for example, in case of + IP auth), ignore "credentials" + + Args: + username: User name to authenticate + credentilas: Credentials for this user, (password, pki, or whatever needs to be used). (string) + groupManager: Group manager to modify with groups to which this users belongs to. + + Returns: + True if authentication success, False if don't. + By default, internalAuthenticate simply invokes authenticate, but this method + is here so you can provide your own method if needed + + See uds.core.auths.GroupsManager + + :note: This method must check not only that the user has valid credentials, but also + check the valid groups from groupsManager. + If this method returns false, of method getValidGroups of the groupsManager + passed into this method has no elements, the user will be considered invalid. + So remember to check validity of groups this user belongs to (inside the authenticator, + not inside UDS) using groupsManager.validate(group to which this users belongs to). + + This is done in this way, because UDS has only a subset of groups for this user, and + we let the authenticator decide inside wich groups of UDS this users is included. + ''' + return self.authenticate(username, credentials, groupsManager) + def logout(self, username): ''' Invoked whenever an user logs out. diff --git a/server/src/uds/core/auths/auth.py b/server/src/uds/core/auths/auth.py index 7f3241d79..0912d260f 100644 --- a/server/src/uds/core/auths/auth.py +++ b/server/src/uds/core/auths/auth.py @@ -105,7 +105,7 @@ def __registerUser(authenticator, authInstance, username): return None -def authenticate(username, password, authenticator): +def authenticate(username, password, authenticator, useInternalAuthenticate = False): ''' Given an username, password and authenticator, try to authenticate user @param username: username to authenticate @@ -116,7 +116,12 @@ def authenticate(username, password, authenticator): logger.debug('Authenticating user {0} with authenticator {1}'.format(username, authenticator)) gm = auths.GroupsManager(authenticator) authInstance = authenticator.getInstance() - if authInstance.authenticate(username, password, gm) == False: + if useInternalAuthenticate is False: + res = authInstance.authenticate(username, password, gm) + else: + res = authInstance.internalAuthenticate(username, password, gm) + + if res is False: return None logger.debug('Groups manager: {0}'.format(gm)) diff --git a/server/src/uds/core/transports/BaseTransport.py b/server/src/uds/core/transports/BaseTransport.py index d4c3d9ad4..a9336d770 100644 --- a/server/src/uds/core/transports/BaseTransport.py +++ b/server/src/uds/core/transports/BaseTransport.py @@ -34,6 +34,7 @@ from django.utils.translation import ugettext as _ from uds.core.util import OsDetector from uds.core import Module +import protocols class Transport(Module): ''' @@ -101,6 +102,32 @@ class Transport(Module): ''' return cls.supportedOss.count(osName) > 0 + @classmethod + def providesConnetionInfo(cls): + ''' + Helper method to check if transport provides information about connection + ''' + return cls.getConnectionInfo != Transport.getConnectionInfo + + def getConnectionInfo(self, userService, user, password): + ''' + This method must provide information about connection. + We don't have to implement it, but if we wont to allow some types of connections + (such as Client applications, some kinds of TC, etc... we must provide it or those + kind of terminals/application will not work + + Args: + userService: DeployedUserService for witch we are rendering the connection (db model) + user: user (dbUser) logged in + pass: password used in authentication + + The expected result from this method is a dictionary, containing at least: + 'protocol': protocol to use, (there are a few standard defined in 'protocols.py', if yours does not fit those, use your own name + 'username': username (transformed if needed to) used to login to service + 'password': password (transformed if needed to) used to login to service + ''' + return {'protocol': protocols.NONE, 'usename': '', 'password': ''} + def renderForHtml(self, userService, id, ip, os, user, password): ''' Requests the html rendering of connector for the destination ip, (dbUser) and password diff --git a/server/src/uds/core/transports/Protocols.py b/server/src/uds/core/transports/protocols.py similarity index 100% rename from server/src/uds/core/transports/Protocols.py rename to server/src/uds/core/transports/protocols.py diff --git a/server/src/uds/dispatchers/pam/urls.py b/server/src/uds/dispatchers/pam/urls.py index 3933d1a8a..152466bb2 100644 --- a/server/src/uds/dispatchers/pam/urls.py +++ b/server/src/uds/dispatchers/pam/urls.py @@ -11,7 +11,7 @@ from django.conf.urls.defaults import patterns, include -urlpatterns = patterns('uds.dispatchers.pam.views', - (r'^pam$', 'pam'), +urlpatterns = patterns(__package__, + (r'^pam$', 'views.pam'), ) \ No newline at end of file