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:
parent
ed602e9354
commit
0a3433b2f5
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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):
|
||||
|
Loading…
x
Reference in New Issue
Block a user