do not pass strings contening null characters to Lasso, return 400 or ignore (fixes #8939)
This commit is contained in:
parent
f2cf86f7a6
commit
4f77ee0e24
|
@ -202,3 +202,6 @@ def create_logout(request):
|
|||
logout.setSignatureHint(lasso.PROFILE_SIGNATURE_HINT_FORBID)
|
||||
logout.setSessionFromDump(session_dump)
|
||||
return logout
|
||||
|
||||
def is_nonnull(s):
|
||||
return not '\x00' in s
|
||||
|
|
|
@ -34,9 +34,12 @@ class LoginView(LogMixin, View):
|
|||
'''Assertion consumer'''
|
||||
if 'SAMLResponse' not in request.POST:
|
||||
return self.get(request, *args, **kwargs)
|
||||
if not utils.is_nonnull(request.POST['SAMLResponse']):
|
||||
return HttpResponseBadRequest('SAMLResponse contains a null character')
|
||||
login = utils.create_login(request)
|
||||
idp_message = None
|
||||
status_codes = []
|
||||
# prevent null characters in SAMLResponse
|
||||
try:
|
||||
login.processAuthnResponseMsg(request.POST['SAMLResponse'])
|
||||
login.acceptSso()
|
||||
|
@ -63,7 +66,7 @@ class LoginView(LogMixin, View):
|
|||
return HttpResponseBadRequest('error processing the authentication '
|
||||
'response: %r' % e)
|
||||
else:
|
||||
if 'RelayState' in request.POST:
|
||||
if 'RelayState' in request.POST and utils.is_nonnull(request.POST['RelayState']):
|
||||
login.msgRelayState = request.POST['RelayState']
|
||||
return self.sso_success(request, login)
|
||||
return self.sso_failure(request, login, idp_message, status_codes)
|
||||
|
@ -204,7 +207,7 @@ class LoginView(LogMixin, View):
|
|||
return HttpResponseBadRequest('error processing the authentication '
|
||||
'response: %r' % e)
|
||||
else:
|
||||
if 'RelayState' in request.GET:
|
||||
if 'RelayState' in request.GET and utils.is_nonnull(request.GET['RelayState']):
|
||||
login.msgRelayState = request.GET['RelayState']
|
||||
return self.sso_success(request, login)
|
||||
return self.sso_failure(request, login, idp_message, status_codes)
|
||||
|
@ -238,7 +241,7 @@ class LoginView(LogMixin, View):
|
|||
req_authncontext = lasso.RequestedAuthnContext()
|
||||
authn_request.requestedAuthnContext = req_authncontext
|
||||
req_authncontext.authnContextClassRef = authn_classref
|
||||
if next_url:
|
||||
if next_url and utils.is_nonnull(next_url):
|
||||
login.msgRelayState = next_url
|
||||
login.buildAuthnRequestMsg()
|
||||
except lasso.Error, e:
|
||||
|
@ -300,7 +303,8 @@ class LogoutView(LogMixin, View):
|
|||
else:
|
||||
self.log.error('unable to find lasso session dump')
|
||||
logout.initRequest(issuer, lasso.HTTP_METHOD_REDIRECT)
|
||||
logout.msgRelayState = next_url
|
||||
if utils.is_nonnull(next_url):
|
||||
logout.msgRelayState = next_url
|
||||
logout.buildRequestMsg()
|
||||
except lasso.Error, e:
|
||||
self.log.error('unable to initiate a logout request %r', e)
|
||||
|
|
|
@ -1,4 +1,13 @@
|
|||
import pytest
|
||||
import django_webtest
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def app(request):
|
||||
wtm = django_webtest.WebTestMixin()
|
||||
wtm._patch_settings()
|
||||
request.addfinalizer(wtm._unpatch_settings)
|
||||
return django_webtest.DjangoTestApp()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
from django.core.urlresolvers import reverse
|
||||
|
||||
def test_null_character_on_samlresponse_post(app):
|
||||
app.post(reverse('mellon_login'), {'SAMLResponse': '\x00'}, status=400)
|
|
@ -12,6 +12,14 @@ DATABASES = {
|
|||
}
|
||||
DEBUG = True
|
||||
SECRET_KEY='xx'
|
||||
STATIC_URL = '/static/'
|
||||
INSTALLED_APPS = ('mellon', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions')
|
||||
MIDDLEWARE_CLASSES = global_settings.MIDDLEWARE_CLASSES
|
||||
MIDDLEWARE_CLASSES += (
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
)
|
||||
AUTHENTICATION_BACKENDS = (
|
||||
'mellon.backends.SAMLBackend',
|
||||
)
|
||||
ROOT_URLCONF = 'mellon.urls'
|
||||
|
|
Loading…
Reference in New Issue