1
0
mirror of https://github.com/dkmstr/openuds.git synced 2025-03-22 14:50:29 +03:00

* renamed "translateProxy" to "acceptProxy" in IP authenticator

* Removed getIp from trustedSourceRequired auth decorator
* Added "remove request global cache" after being used by system
* Removed unused getIp from web & xmlrpc
This commit is contained in:
Adolfo Gómez 2014-06-11 08:56:19 +00:00
parent ed602e9354
commit 0a3433b2f5
5 changed files with 72 additions and 55 deletions

View File

@ -49,7 +49,7 @@ logger = logging.getLogger(__name__)
class IPAuth(Authenticator):
translateProxy = gui.CheckBoxField(label=_('Accept proxy'), order=3, tooltip=_('If checked, requests via proxy will get FORWARDED ip address (take care with this bein checked, can take internal IP addresses from internet)'))
acceptProxy = gui.CheckBoxField(label=_('Accept proxy'), order=3, tooltip=_('If checked, requests via proxy will get FORWARDED ip address (take care with this bein checked, can take internal IP addresses from internet)'))
typeName = _('IP Authenticator')
typeType = 'IPAuth'
@ -69,6 +69,9 @@ class IPAuth(Authenticator):
def __unicode__(self):
return "IP Authenticator"
def getIp(self):
return getRequest().ip_proxy if self.acceptProxy.isTrue() else getRequest().ip
def getGroups(self, ip, groupsManager):
# these groups are a bit special. They are in fact ip-ranges, and we must check that the ip is in betwen
# The ranges are stored in group names
@ -82,12 +85,14 @@ class IPAuth(Authenticator):
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 username == getRequest().ip:
if username == self.getIp():
self.getGroups(username, groupsManager)
return True
return False
def internalAuthenticate(self, username, credentials, groupsManager):
# In fact, username does not matter, will get IP from request
username = self.getIp()
self.getGroups(username, groupsManager)
if groupsManager.hasValidGroups() and self.dbAuthenticator().isValidUser(username, True):
return True
@ -95,19 +100,21 @@ class IPAuth(Authenticator):
@staticmethod
def test(env, data):
return _("All seems fine in the authenticator.")
return _("All seems to be fine.")
def check(self):
return _("All seems fine in the authenticator.")
return _("All seems to be fine.")
def getHtml(self, request):
# doAutoLogin = Config.section('IPAUTH').value('autoLogin', '0').getBool()
ip = self.getIp()
gm = GroupsManager(self.dbAuthenticator())
self.getGroups(request.ip, gm)
if gm.hasValidGroups() and self.dbAuthenticator().isValidUser(request.ip, True):
self.getGroups(ip, gm)
if gm.hasValidGroups() and self.dbAuthenticator().isValidUser(ip, True):
passw = ''
return '<script type="text/javascript">$("#id_user").val("' + request.ip + '");$("#id_password").val("' + passw + '");$("#loginform").submit();</script>'
return '<script type="text/javascript">$("#id_user").val("' + ip + '");$("#id_password").val("' + passw + '");$("#loginform").submit();</script>'
else:
return '<div>This ip is not allowed to autologin (' + request.ip + ')</div><script type="text/javascript">$("#backToLogin").click()</script>'
return '<div>Invalid auth (' + ip + ')</div><script type="text/javascript">$("#backToLogin").click()</script>'
# We will authenticate ip here, from request.ip
# If valid, it will simply submit form with ip submited and a cached generated random password

View File

@ -131,7 +131,6 @@ def trustedSourceRequired(view_func):
Wrapped function for decorator
'''
from uds.core.util import net
getIp(request, False)
if net.ipInNetwork(request.ip, GlobalConfig.TRUSTED_SOURCES.get(True)) is False:
return HttpResponseForbidden()
return view_func(request, *args, **kwargs)

View File

@ -49,18 +49,32 @@ def getRequest():
class GlobalRequestMiddleware(object):
def process_request(self, request):
# Add IP to request
GlobalRequestMiddleware.getIp(request)
GlobalRequestMiddleware.fillIps(request)
_requests[threading._get_ident()] = request
return None
def process_response(self, request, response):
# Remove IP from global cache (processing responses after this will make global request unavailable,
# but can be got from request again)
try:
del _requests[threading._get_ident()]
except:
logger.exception('Deleting stored request')
return response
@staticmethod
def getIp(request):
def fillIps(request):
'''
Obtains the IP of a Django Request, even behind a proxy
Returns the obtained IP, that is always be a valid ip address.
'''
request.ip = request.META['REMOTE_ADDR']
try:
request.ip = request.META['REMOTE_ADDR']
except:
logger.exception('Request ip not found!!')
request.ip = '0.0.0.0' # No remote addr?? set this IP to a "basic" one, anyway, this should never ocur
try:
request.ip_proxy = request.META['HTTP_X_FORWARDED_FOR'].split(",")[0]
request.is_proxy = True

View File

@ -42,7 +42,7 @@ from django.utils import timezone
from django.views.decorators.http import last_modified
from django.views.i18n import javascript_catalog
from uds.core.auths.auth import getIp, webLogin, webLogout, webLoginRequired, authenticate, webPassword, authenticateViaCallback, authLogLogin, authLogLogout, getUDSCookie
from uds.core.auths.auth import webLogin, webLogout, webLoginRequired, authenticate, webPassword, authenticateViaCallback, authLogLogin, authLogLogout, getUDSCookie
from uds.models import Authenticator, DeployedService, Transport, UserService, Network
from uds.web.forms.LoginForm import LoginForm
from uds.core.managers.UserServiceManager import UserServiceManager
@ -140,7 +140,6 @@ def login(request, smallName=None):
def customAuth(request, idAuth):
res = ''
try:
getIp(request)
a = Authenticator.objects.get(pk=idAuth).getInstance()
res = a.getHtml(request)
if res is None:

View File

@ -4,27 +4,27 @@
# Copyright (c) 2012 Virtual Cable S.L.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# 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,
# * 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
# * 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
# * 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
# 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
# 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.
'''
@ -37,7 +37,7 @@ from uds.models import Authenticator
from uds.xmlrpc.util.Exceptions import AuthException
from uds.core.util.Config import GlobalConfig
from uds.core.util import log
from uds.core.auths.auth import authenticate, getIp
from uds.core.auths.auth import authenticate
from functools import wraps
from django.conf import settings
import logging
@ -59,20 +59,20 @@ class Credentials(object):
self.user = session['username']
self.locale = session['locale']
self.key = credential_key
def __unicode__(self):
return "authId: {0}, isAdmin: {1}, user: {2}, locale: {3}, key: {4}".format(self.idAuth, self.isAdmin, self.user, self.locale, self.key)
def __str__(self):
return "authId: {0}, isAdmin: {1}, user: {2}, locale: {3}, key: {4}".format(self.idAuth, self.isAdmin, self.user, self.locale, self.key)
def logout(self):
'''
Logout administration user
'''
logger.info('Logged out admin user {0}'.format(self))
if self.idAuth == ADMIN_AUTH: # Root administrator does nothing on logout
if self.idAuth == ADMIN_AUTH: # Root administrator does nothing on logout
return ''
try:
a = Authenticator.objects.get(pk=self.idAuth).getInstance()
@ -80,10 +80,10 @@ class Credentials(object):
return a.logout(self.user)
except Exception:
logger.exception('Exception at logout (managed)')
return ''
def makeCredentials(idAuth, username, locale, isAdmin):
session = SessionStore()
@ -105,10 +105,10 @@ def needs_credentials(xmlrpc_func):
def _wrapped_xmlrcp_func(credentials, *args, **kwargs):
# We expect that request is passed in as last argument ALWAYS (look at views)
args = list(args)
request = args.pop() # Last argumment is request
request = args.pop() # Last argumment is request
args = tuple(args)
logger.debug('Checkin credentials {0} for function {1}'.format(credentials, xmlrpc_func.__name__))
cred = validateCredentials(request, credentials)
cred = validateCredentials(request, credentials)
if cred is not None:
logger.debug('Credentials valid, executing')
return xmlrpc_func(cred, *args, **kwargs)
@ -121,7 +121,7 @@ def validateCredentials(request, credentials):
Validates the credentials of an user
:param credentials:
'''
session = SessionStore(session_key = credentials)
session = SessionStore(session_key=credentials)
if session.exists(credentials) is False:
return None
if session.has_key('idAuth') is False:
@ -131,34 +131,32 @@ def validateCredentials(request, credentials):
# Updates the expire key, this is the slow part as we can see at debug log, better if we can only update the expire_key this takes 80 ms!!!
session.save()
logger.debug('Session updated')
return Credentials(request, session, credentials )
return Credentials(request, session, credentials)
def invalidateCredentials(credentials):
session = SessionStore(session_key = credentials.key)
session = SessionStore(session_key=credentials.key)
session.delete()
def getAdminAuths(locale):
'''
Returns the authenticators
Returns the authenticators
'''
activate(locale)
res = []
for a in Authenticator.all():
if a.getType().isCustom() is False:
res.append( { 'id' : str(a.id), 'name' : a.name } )
return res + [ {'id' : ADMIN_AUTH, 'name' : _('Administration') }]
res.append({ 'id' : str(a.id), 'name' : a.name })
return res + [ {'id' : ADMIN_AUTH, 'name' : _('Administration') }]
# Xmlrpc functions
def login(username, password, idAuth, locale, request):
'''
Validates the user/password credentials, assign to it the specified locale for this session and returns a credentials response
'''
getIp(request)
logger.info("Validating user {0} with authenticator {1} with locale {2}".format(username, idAuth, locale))
activate(locale)
if idAuth == ADMIN_AUTH:
@ -171,7 +169,7 @@ def login(username, password, idAuth, locale, request):
user = authenticate(username, password, auth)
except Exception:
raise AuthException(_('Invalid authenticator'))
if user is None:
log.doLog(auth, log.ERROR, 'Invalid credentials for {0} from {1}'.format(username, request.ip), log.ADMIN)
try:
@ -180,18 +178,18 @@ def login(username, password, idAuth, locale, request):
except:
pass
raise AuthException(_('Access denied'))
if user.staff_member is False:
log.doLog(auth, log.ERROR, 'Access denied from {1}. User {0} is not membef of staff'.format(username, request.ip), log.ADMIN)
log.doLog(user, log.ERROR, 'Access denied from {0}. This user is not membef of staff'.format(request.ip), log.ADMIN)
raise AuthException(_('Access denied'))
log.doLog(auth, log.INFO, 'Access granted to user {0} from {1} to administration'.format(username, request.ip), log.ADMIN)
log.doLog(user, log.INFO, 'Access granted from {0} to administration'.format(request.ip), log.ADMIN)
return makeCredentials(idAuth, username, locale, user.is_admin)
@needs_credentials
def logout(credentials):