1
0
mirror of https://github.com/dkmstr/openuds.git synced 2025-01-08 21:18:00 +03:00

* Added so we can access requests from anywhere without having to pass it

* Added So we can transform user names on login
* Added the posibility to give a different user to each internal db user based on the source (IP or reversed ip)
* Added "ignore and notify" invalid serialized data. This is so we can migrate "all" modules to auto serialization/deserialization
This commit is contained in:
Adolfo Gómez 2013-04-08 03:11:00 +00:00
parent 3140dd0bca
commit 6bd242bb9d
8 changed files with 124 additions and 39 deletions

View File

@ -89,6 +89,7 @@ encoding//src/uds/core/util/connection.py=utf-8
encoding//src/uds/core/util/log.py=utf-8
encoding//src/uds/core/util/modfinder.py=utf-8
encoding//src/uds/core/util/net.py=utf-8
encoding//src/uds/core/util/request.py=utf-8
encoding//src/uds/core/util/stats/__init__.py=utf-8
encoding//src/uds/core/util/stats/charts.py=utf-8
encoding//src/uds/core/util/stats/counters.py=utf-8

View File

@ -61,7 +61,7 @@ class IPAuth(Authenticator):
return res
def __str__(self):
return "Internal IP Authenticator"
return "IP Authenticator"
def marshal(self):
return "v1"

View File

@ -34,9 +34,10 @@
'''
from django.utils.translation import ugettext_noop as _
from uds.core.auths import Authenticator
from uds.core.managers.CryptoManager import CryptoManager
from uds.models import Authenticator as dbAuthenticator
from uds.core.ui import gui
from uds.core.util.State import State
import dns
import hashlib
import logging
@ -55,25 +56,40 @@ class InternalDBAuth(Authenticator):
# This is the only internal source
isExternalSource = False
differentForEachHost = gui.CheckBoxField(label = _('Different user for each host'), order = 1, tooltip = _('If checked, each host will have a different user name'), defvalue = "false", rdonly = True)
reverseDns = gui.CheckBoxField(label = _('Reverse DNS'), order = 2, tooltip = _('If checked, the host will be reversed dns'), defvalue = "false", rdonly = True)
def __init__(self, dbAuth, environment, values = None):
super(InternalDBAuth, self).__init__(dbAuth, environment, values)
# Ignore values
def initialize(self, values):
if values is None:
return
def valuesDict(self):
res = {}
return res
def getIp(self, ip):
if self.reverseDns.isTrue():
try:
return str(dns.resolver.query(dns.reversename.from_address(ip), 'PTR')[0])
except:
pass
return ip
def __str__(self):
return "Internal DB Authenticator Authenticator"
def transformUsername(self, username):
from uds.core.util.request import getRequest
if self.differentForEachHost.isTrue():
newUsername = self.getIp(getRequest().ip) + '-' + username
# Duplicate basic user into username.
auth = self.dbAuthenticator()
# "Derived" users will belong to no group at all, because we will extract groups from "base" user
# This way also, we protect from using forged "ip" + "username", because those will belong in fact to no group
# and access will be denied
try:
usr = auth.users.get(name=username, state=State.ACTIVE)
usr.id = None
usr.name = newUsername
usr.save()
except:
logger.exception('Exception')
username = newUsername
def marshal(self):
return "v1"
def unmarshal(self, str_):
data = str_.split('\t')
if data[0] == 'v1':
pass
return username
def authenticate(self, username, credentials, groupsManager):
logger.debug('Username: {0}, Password: {1}'.format(username, credentials))
@ -101,6 +117,8 @@ class InternalDBAuth(Authenticator):
def check(self):
return _("All seems fine in the authenticator.")
def __str__(self):
return "Internal DB Authenticator Authenticator"

View File

@ -33,4 +33,5 @@
@author: Adolfo Gómez, dkmaster at dkmon dot com
'''
from Authenticator import InternalDBAuth
from IPInternal import IPInternalAuth

View File

@ -302,6 +302,21 @@ class Authenticator(Module):
'''
return False
def transformUsername(self, username):
'''
On login, this method get called so we can "transform" provided user name.
Args:
username: Username to transform
Returns
Transformed user name
:note: You don't need to implement this method if your authenticator (as most authenticators does), does not
transforms username.
'''
return username
def internalAuthenticate(self,username, credentials, groupsManager):
'''
This method is provided so "plugins" (For example, a custom dispatcher), can test

View File

@ -102,6 +102,9 @@ def __registerUser(authenticator, authInstance, username):
This will work correctly with both internal or externals cause we first authenticate the user, if internal and user do not exists in database
authenticate will return false, if external and return true, will create a reference in database
'''
username = authInstance.transformUsername(username)
logger.debug('Transformed username: {0}'.format(username))
usr = authenticator.getOrCreateUser(username, authInstance.getRealName(username))
if usr is not None and State.isActive(usr.state):
# Now we update database groups for this user

View File

@ -774,25 +774,28 @@ class UserInterface(object):
if values == '': # Has nothing
return
# Set all values to defaults ones
for k in self._gui.iterkeys():
if self._gui[k].isType(gui.InputField.HIDDEN_TYPE) and self._gui[k].isSerializable() is False:
#logger.debug('Field {0} is not unserializable'.format(k))
continue
self._gui[k].value = self._gui[k].defValue
try:
# Set all values to defaults ones
for k in self._gui.iterkeys():
if self._gui[k].isType(gui.InputField.HIDDEN_TYPE) and self._gui[k].isSerializable() is False:
#logger.debug('Field {0} is not unserializable'.format(k))
continue
self._gui[k].value = self._gui[k].defValue
for txt in values.decode('zip').split('\002'):
k, v = txt.split('\003')
if self._gui.has_key(k):
try:
if v[0] == '\001':
val = cPickle.loads(v[1:])
else:
val = v
except:
val = ''
self._gui[k].value = val
#logger.debug('Value for {0}:{1}'.format(k, val))
for txt in values.decode('zip').split('\002'):
k, v = txt.split('\003')
if self._gui.has_key(k):
try:
if v[0] == '\001':
val = cPickle.loads(v[1:])
else:
val = v
except:
val = ''
self._gui[k].value = val
#logger.debug('Value for {0}:{1}'.format(k, val))
except:
logger.info('Seralized data invalid: {0}'.format(values))
@classmethod
def guiDescription(cls, obj = None):

View File

@ -0,0 +1,44 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2012 Virtual Cable S.L.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# 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.
'''
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
'''
import threading
_requests = {}
def getRequest():
return _requests[threading._get_ident()]
class GlobalRequestMiddleware(object):
def process_request(self, request):
_requests[threading._get_ident()] = request
return None