From 74148210a92251db7c91d63ad5c7170f97102b28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20G=C3=B3mez=20Garc=C3=ADa?= Date: Mon, 27 Oct 2014 18:39:31 +0100 Subject: [PATCH] * Fixed ticket to accept also "auth" name * started to add filters to models * removed import from deprecated getIp * added tickets url * added ticket view --- server/src/uds/REST/methods/tickets.py | 18 +++++-- server/src/uds/REST/model.py | 9 +++- .../src/uds/auths/InternalDB/Authenticator.py | 6 ++- server/src/uds/core/auths/auth.py | 4 +- server/src/uds/core/util/net.py | 14 +++--- server/src/uds/urls.py | 3 ++ server/src/uds/web/views.py | 50 ++++++++++++++++--- 7 files changed, 78 insertions(+), 26 deletions(-) diff --git a/server/src/uds/REST/methods/tickets.py b/server/src/uds/REST/methods/tickets.py index a22e8ccc..b470415d 100644 --- a/server/src/uds/REST/methods/tickets.py +++ b/server/src/uds/REST/methods/tickets.py @@ -73,7 +73,7 @@ class Ticket(Handler): raise RequestError('Invalid request') - # Must be invoked as '/rest/ticket/create, with "username", ("authId" or "authSmallName", "group" and optionally "time" (in seconds) as paramteres + # Must be invoked as '/rest/ticket/create, with "username", ("authId" or "authSmallName", "groups" (array) and optionally "time" (in seconds) as paramteres def put(self): ''' Processes put requests, currently only under "create" @@ -84,23 +84,30 @@ class Ticket(Handler): if 'username' not in self._params or 'group' not in self._params: raise RequestError('Invalid parameters') - if 'authId' not in self._params and 'authSmallName' not in self._params: + if 'authId' not in self._params and 'authSmallName' not in self._params and 'auth' not in self._params: raise RequestError('Invalid parameters (no auth)') try: authId = self._params.get('authId', None) authSmallName = self._params.get('authSmallName', None) + authName = self._params.get('auth', None) # Will raise an exception if no auth found if authId is not None: auth = Authenticator.objects.get(uuid=authId) + elif authName is not None: + auth = Authenticator.objects.get(name=authName) else: auth = Authenticator.objects.get(small_name=authSmallName) username = self._params['username'] - group = self._params['group'] + groups = self._params['groups'] time = int(self._params.get('time', 60)) - # Try to get auth, or raise an exception if auth is not found + realname = self._params.get('realname', self._params['username']) + servicePool = self._params.get('servicePool', None) + backUrl = self._params.get('exitUrl', None) + # Groups will be checked on user login stage, and invalid groups will be simply ignored + # If user is no part of ANY group, access will be denied except Exception as e: return Ticket.result(error=six.text_type(e)) @@ -110,7 +117,8 @@ class Ticket(Handler): store = SessionStore() store.set_expiry(time) store['username'] = username - store['group'] = group + store['realname'] = realname + store['groups'] = groups store['auth'] = auth.uuid store.save() diff --git a/server/src/uds/REST/model.py b/server/src/uds/REST/model.py index 2c2fac98..0b76bb71 100644 --- a/server/src/uds/REST/model.py +++ b/server/src/uds/REST/model.py @@ -44,7 +44,7 @@ import logging logger = logging.getLogger(__name__) -__updated__ = '2014-09-25' +__updated__ = '2014-10-27' # a few constants @@ -541,7 +541,12 @@ class ModelHandler(BaseModelHandler): # nArgs > 1 # Request type info or gui, or detail - if self._args[0] == TYPES: + if self._args[0] == OVERVIEW: + if nArgs != 2: + self.invalidRequestException() + # TODO: Parse _args[1] + + elif self._args[0] == TYPES: if nArgs != 2: self.invalidRequestException() return self.getType(self._args[1]) diff --git a/server/src/uds/auths/InternalDB/Authenticator.py b/server/src/uds/auths/InternalDB/Authenticator.py index 436ecacc..37470829 100644 --- a/server/src/uds/auths/InternalDB/Authenticator.py +++ b/server/src/uds/auths/InternalDB/Authenticator.py @@ -38,12 +38,13 @@ from django.utils.translation import ugettext_noop as _ from uds.core.auths import Authenticator from uds.models import Authenticator as dbAuthenticator from uds.core.ui import gui +from uds.core.managers import cryptoManager from uds.core.util.State import State import dns import hashlib import logging -__updated__ = '2014-06-02' +__updated__ = '2014-10-27' logger = logging.getLogger(__name__) @@ -111,7 +112,8 @@ class InternalDBAuth(Authenticator): return False # Internal Db Auth has its own groups, and if it active it is valid - if usr.password == hashlib.sha1(credentials.encode('utf-8')).hexdigest(): + if usr.password == cryptoManager().hash(credentials): + # hashlib.sha1(credentials.encode('utf-8')).hexdigest(): groupsManager.validate([g.name for g in usr.groups.all()]) return True return False diff --git a/server/src/uds/core/auths/auth.py b/server/src/uds/core/auths/auth.py index bd47e3ab..9d1e09ad 100644 --- a/server/src/uds/core/auths/auth.py +++ b/server/src/uds/core/auths/auth.py @@ -50,7 +50,7 @@ from uds.models import User import logging -__updated__ = '2014-10-07' +__updated__ = '2014-10-27' logger = logging.getLogger(__name__) authLogger = logging.getLogger('authLog') @@ -82,9 +82,9 @@ def getRootUser(): u.logout = lambda: None return u + @deprecated def getIp(request): - import inspect logger.info('Deprecated IP') return request.ip diff --git a/server/src/uds/core/util/net.py b/server/src/uds/core/util/net.py index 23563548..23320556 100644 --- a/server/src/uds/core/util/net.py +++ b/server/src/uds/core/util/net.py @@ -36,13 +36,13 @@ import re from exceptions import ValueError # Test patters for networks -reCIDR = re.compile('^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/([0-9]{1,2})$') -reMask = re.compile('^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})netmask([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$') -re1Asterisk = re.compile('^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.\*$') -re2Asterisk = re.compile('^([0-9]{1,3})\.([0-9]{1,3})\.\*\.?\*?$') -re3Asterisk = re.compile('^([0-9]{1,3})\.\*\.?\*?\.?\*?$') -reRange = re.compile('^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})-([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$') -reHost = re.compile('^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$') +reCIDR = re.compile(r'^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/([0-9]{1,2})$') +reMask = re.compile(r'^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})netmask([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$') +re1Asterisk = re.compile(r'^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.\*$') +re2Asterisk = re.compile(r'^([0-9]{1,3})\.([0-9]{1,3})\.\*\.?\*?$') +re3Asterisk = re.compile(r'^([0-9]{1,3})\.\*\.?\*?\.?\*?$') +reRange = re.compile(r'^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})-([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$') +reHost = re.compile(r'^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$') def ipToLong(ip): diff --git a/server/src/uds/urls.py b/server/src/uds/urls.py index 0dac5cc3..225e2bda 100644 --- a/server/src/uds/urls.py +++ b/server/src/uds/urls.py @@ -70,6 +70,9 @@ urlpatterns = patterns( (r'^authJava/(?P.+)/(?P.*)$', 'web.views.authJava'), (r'^authinfo/(?P.+)', 'web.views.authInfo'), (r'^about', 'web.views.about'), + # Ticket authentication + (r'^tkauth/(?P.+)/(?P.*)', 'web.views.ticketAuth'), + # XMLRPC Processor (r'^xmlrpc$', 'xmlrpc.views.xmlrpc'), diff --git a/server/src/uds/web/views.py b/server/src/uds/web/views.py index 9d0279ff..cdd96d44 100644 --- a/server/src/uds/web/views.py +++ b/server/src/uds/web/views.py @@ -25,7 +25,6 @@ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ''' @author: Adolfo Gómez, dkmaster at dkmon dot com ''' @@ -39,9 +38,10 @@ from django.shortcuts import redirect from django.template import RequestContext from django.utils.translation import ugettext as _ from django.core.urlresolvers import reverse -from django.utils import timezone from django.views.decorators.http import last_modified from django.views.i18n import javascript_catalog +from django.contrib.sessions.backends.db import SessionStore +from django.utils import timezone from uds.core.auths.auth import webLogin, webLogout, webLoginRequired, authenticate, webPassword, authenticateViaCallback, authLogLogin, authLogLogout, getUDSCookie from uds.models import Authenticator, DeployedService, Transport, UserService, Network @@ -53,14 +53,14 @@ from uds.core.util.Config import GlobalConfig from uds.core.util.Cache import Cache from uds.core.util import OsDetector from uds.core.util import log +from uds.core.util.State import State from uds.core.ui import theme +from uds.core.auths.Exceptions import InvalidUserException from transformers import transformId, scrambleId -import errors +import uds.web.errors as errors import logging -import random -import string logger = logging.getLogger(__name__) @@ -293,7 +293,7 @@ def transcomp(request, idTransport, componentId): trans = Transport.objects.get(pk=idTransport) itrans = trans.getInstance() res = itrans.getHtmlComponent(scrambleId(request, trans.id), request.session['OS'], componentId) - response = HttpResponse(res[1], mimetype=res[0]) + response = HttpResponse(res[1], content_type=res[0]) response['Content-Length'] = len(res[1]) return response except Exception, e: @@ -323,14 +323,14 @@ def sernotify(request, idUserService, notification): except Exception as e: logger.exception("Exception") return errors.errorView(request, e) - return HttpResponse('ok', mimetype='text/plain') + return HttpResponse('ok', content_type='text/plain') @transformId def transportIcon(request, idTrans): try: icon = Transport.objects.get(pk=idTrans).getInstance().icon(False) - return HttpResponse(icon, mimetype='image/png') + return HttpResponse(icon, content_type='image/png') except Exception: return HttpResponseRedirect('/static/img/unknown.png') @@ -456,6 +456,7 @@ def download(request, idDownload): return DownloadsManager.manager().send(request, idDownload) + last_modified_date = timezone.now() @@ -464,3 +465,36 @@ def jsCatalog(request, lang, domain='djangojs', packages=None): if lang != '': request.GET = {'language': lang} # Fake args for catalog :-) return javascript_catalog(request, domain, packages) + + +def ticketAuth(request, ticketId): + ''' + Used to authenticate an user via a ticket + ''' + session = SessionStore(session_key=ticketId) + + try: + for k in ('username', 'groups', 'auth', 'realname'): + if k not in session: # No valid data stored, maybe session is expired, or no session at all + raise InvalidUserException() + auth = Authenticator.objects.get(uuid=session['auth']) + # If user does not exists in DB, create it right now + usr = auth.getOrCreateUser(session['username'], session['realname']) + if usr is None or State.isActive(usr.state) is False: # If user is inactive, raise an exception + raise InvalidUserException() + # Add user to groups, if they exists... + grps = [] + for g in iter(session['groups']): + try: + grps.append(auth.groups.get(name=g)) + except Exception: + logger.info('Group {} from ticket does not exists'.format(g)) + # Add groups + usr.groups = grps + + except Authenticator.DoesNotExist: + return error(request, InvalidUserException()) + except Exception as e: + return errors.exceptionView(request, e) + + return HttpResponse(ticketId, content_type='text/plain')