diff --git a/server/src/uds/auths/IP/Authenticator.py b/server/src/uds/auths/IP/Authenticator.py
index 3690995bf..d3447d9fe 100644
--- a/server/src/uds/auths/IP/Authenticator.py
+++ b/server/src/uds/auths/IP/Authenticator.py
@@ -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 ''
+ return ''
else:
- return '
This ip is not allowed to autologin (' + request.ip + ')
'
+ return 'Invalid auth (' + ip + ')
'
# We will authenticate ip here, from request.ip
# If valid, it will simply submit form with ip submited and a cached generated random password
diff --git a/server/src/uds/core/auths/auth.py b/server/src/uds/core/auths/auth.py
index ce9dc3e13..7b30dc88e 100644
--- a/server/src/uds/core/auths/auth.py
+++ b/server/src/uds/core/auths/auth.py
@@ -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)
diff --git a/server/src/uds/core/util/request.py b/server/src/uds/core/util/request.py
index ce6299a57..19196b07b 100644
--- a/server/src/uds/core/util/request.py
+++ b/server/src/uds/core/util/request.py
@@ -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
diff --git a/server/src/uds/web/views.py b/server/src/uds/web/views.py
index 954dcb74d..a65ed5558 100644
--- a/server/src/uds/web/views.py
+++ b/server/src/uds/web/views.py
@@ -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:
diff --git a/server/src/uds/xmlrpc/auths/AdminAuth.py b/server/src/uds/xmlrpc/auths/AdminAuth.py
index 11c40a230..643dae7d4 100644
--- a/server/src/uds/xmlrpc/auths/AdminAuth.py
+++ b/server/src/uds/xmlrpc/auths/AdminAuth.py
@@ -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):