Move clean_session with the other session management method + add a check for session.hashed for additional security ?

This commit is contained in:
Alexandre Aubin 2019-08-20 19:42:32 +02:00
parent ebc37ea014
commit bcaf8b2e4a
3 changed files with 31 additions and 31 deletions

View file

@ -1,9 +1,10 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import os
import gnupg import gnupg
import logging import logging
from moulinette.cache import open_cachefile from moulinette.cache import open_cachefile, get_cachedir
from moulinette.core import MoulinetteError from moulinette.core import MoulinetteError
logger = logging.getLogger('moulinette.authenticator') logger = logging.getLogger('moulinette.authenticator')
@ -165,3 +166,20 @@ class BaseAuthenticator(object):
logger.error(error_message) logger.error(error_message)
raise MoulinetteError('unable_retrieve_session', exception=error_message) raise MoulinetteError('unable_retrieve_session', exception=error_message)
return decrypted.data return decrypted.data
def _clean_session(self, session_id):
"""Clean a session cache
Remove cache for the session 'session_id' and for this authenticator profile
Keyword arguments:
- session_id -- The session id to clean
"""
sessiondir = get_cachedir('session')
try:
os.remove(os.path.join(sessiondir, self.name, '%s.asc' % session_id))
except OSError:
pass

View file

@ -396,28 +396,6 @@ def init_interface(name, kwargs={}, actionsmap={}):
return interface(amap, **kwargs) return interface(amap, **kwargs)
def clean_session(session_id, profiles=[]):
"""Clean a session cache
Remove cache for the session 'session_id' and for profiles in
'profiles' or for all of them if the list is empty.
Keyword arguments:
- session_id -- The session id to clean
- profiles -- A list of profiles to clean
"""
sessiondir = get_cachedir('session')
if not profiles:
profiles = os.listdir(sessiondir)
for p in profiles:
try:
os.unlink(os.path.join(sessiondir, p, '%s.asc' % session_id))
except OSError:
pass
# Moulinette core classes ---------------------------------------------- # Moulinette core classes ----------------------------------------------
class MoulinetteError(Exception): class MoulinetteError(Exception):

View file

@ -14,7 +14,7 @@ from bottle import run, request, response, Bottle, HTTPResponse
from bottle import abort from bottle import abort
from moulinette import msignals, m18n, env from moulinette import msignals, m18n, env
from moulinette.core import MoulinetteError, clean_session from moulinette.core import MoulinetteError
from moulinette.interfaces import ( from moulinette.interfaces import (
BaseActionsMapParser, BaseInterface, ExtendedArgumentParser, BaseActionsMapParser, BaseInterface, ExtendedArgumentParser,
) )
@ -251,10 +251,7 @@ class _ActionsMapPlugin(object):
def _logout(callback): def _logout(callback):
def wrapper(): def wrapper():
kwargs = {} kwargs = {}
try: kwargs['profile'] = request.POST.get('profile', "default")
kwargs['profile'] = request.POST.get('profile')
except KeyError:
pass
return callback(**kwargs) return callback(**kwargs)
return wrapper return wrapper
@ -362,7 +359,7 @@ class _ActionsMapPlugin(object):
secret=s_secret) secret=s_secret)
return m18n.g('logged_in') return m18n.g('logged_in')
def logout(self, profile=None): def logout(self, profile):
"""Log out from an authenticator profile """Log out from an authenticator profile
Attempt to unregister a given profile - or all by default - from Attempt to unregister a given profile - or all by default - from
@ -374,14 +371,21 @@ class _ActionsMapPlugin(object):
""" """
s_id = request.get_cookie('session.id') s_id = request.get_cookie('session.id')
try: try:
del self.secrets[s_id] # We check that there's a (signed) session.hash available
# for additional security ?
# (An attacker could not craft such signed hashed ? (FIXME : need to make sure of this))
s_secret = self.secrets[s_id]
s_hash = request.get_cookie('session.hashes',
secret=s_secret, default={})[profile]
except KeyError: except KeyError:
raise HTTPUnauthorizedResponse(m18n.g('not_logged_in')) raise HTTPUnauthorizedResponse(m18n.g('not_logged_in'))
else: else:
del self.secrets[s_id]
authenticator = self.actionsmap.get_authenticator_for_profile(profile)
authenticator._clean_session(s_id)
# TODO: Clean the session for profile only # TODO: Clean the session for profile only
# Delete cookie and clean the session # Delete cookie and clean the session
response.set_cookie('session.hashes', '', max_age=-1) response.set_cookie('session.hashes', '', max_age=-1)
clean_session(s_id)
return m18n.g('logged_out') return m18n.g('logged_out')
def messages(self): def messages(self):