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:
parent
3140dd0bca
commit
6bd242bb9d
@ -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
|
||||
|
@ -61,7 +61,7 @@ class IPAuth(Authenticator):
|
||||
return res
|
||||
|
||||
def __str__(self):
|
||||
return "Internal IP Authenticator"
|
||||
return "IP Authenticator"
|
||||
|
||||
def marshal(self):
|
||||
return "v1"
|
||||
|
@ -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"
|
||||
|
||||
|
||||
|
@ -33,4 +33,5 @@
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from Authenticator import InternalDBAuth
|
||||
from IPInternal import IPInternalAuth
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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):
|
||||
|
44
server/src/uds/core/util/request.py
Normal file
44
server/src/uds/core/util/request.py
Normal 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
|
||||
|
Loading…
Reference in New Issue
Block a user