def __init__(self, cookie=None, **settings): if cookie is not None and not isinstance(cookie, str): raise ValueError("Cookie must be str, cast it explicitly") self.modified = False self.is_new = False self._saved = False self._aborted = False self._data = None log.debug("Recieved cookie '%s'" % cookie) self._id_length = settings.get("session_id_length", 32) self.enc_key = settings.get("encryption_key", None) self.sig_key = settings["signature_key"] self.hashalg = settings.get("hashalg", HASHALG) self.refresh_on_access = settings.get("refresh_on_access", True) self.serializer = settings.get("serializer", json) # Cookie settings self.name = settings.get("name", b"session") self.path = settings.get("path", "/") self.domain = settings["domain"] self.max_age = settings.get("max_age", None) self.secure = settings.get("secure", False) self.httponly = settings.get("httponly", False) # Make sure if we have an encryption key that we are also able to # encrypt. if self.enc_key: use_encryption = encryption_available() if not use_encryption: raise CryptoError("Encryption key was given but encryption is " "not available.") else: use_encryption = False # Choose the correct class for creating a cookie and prepare it if use_encryption: CookieClass = functools.partial(EncryptedCookie, self.serializer, self.sig_key, self.hashalg, self.enc_key) else: CookieClass = functools.partial(SignedCookie, self.serializer, self.sig_key, self.hashalg) if cookie: # Load the cookie data and on error create a new cookie try: self._cookie = CookieClass(input=cookie) sess_id = self._get_session_id_from_cookie() log.debug("Loaded old cookie with session ID %s from input %s" % (sess_id, cookie)) except Cookie.CookieError as e: log.debug("Creating new cookie because of the following " "exception: %s" % e) self._cookie = CookieClass(input=None) except CryptoError as e: log.warning("Cryptographic Error '%s' when loading cookie " "'%s': %r" % (e.message, cookie, e)) self._cookie = CookieClass(input=None) except Exception as e: log.info("Error loading cookie '%s' because of exception '%r'" % (cookie, e)) self._cookie = CookieClass(input=None) else: log.debug("Starting new session because of empty cookie.") self._cookie = CookieClass(input=None) if self._get_session_id_from_cookie() is None: self.is_new = True
def authenced(request): """Encrypt and authenticate a testvalue and return a three-tuple (testval, ciphertext, tag).""" if not encryption_available(): pytest.skip("pycrypto not available") testval = request.param ciphertext, tag = encrypt_then_authenticate(testval, test_enc_key, test_sig_key, hashlib.sha256) return testval, ciphertext, tag
def configure(self, **settings): """ Configure sessions with default arguments. The settings passed in here will be used for all newly created sessions, unless superseded by the settings explicity passed to :meth:`sessionmaker.__call__`. The following configuration settings are available exclusively to the sessionmaker: :param backend: The name of the backend to be used. This setting is mandatory, but can also be passed individually on session creation. :param secret_file: If this is specified, a file is used to store keys for both encryption and signing of the cookie. This option conflicts with the ``signature_key`` and ``encryption_key`` options, so you can only use one of them. Defaults to a file called `secret` in the current working directory. :param enable_encryption: Only useful in conjunction with ``secret_file``, as it specifies to not only load a signature key but also an encryption key. This requires `PyCrypto`_. Defaults to no encryption. .. _PyCrypto: https://www.dlitz.net/software/pycrypto/ """ if hasattr(self, 'settings'): raise SessionConfigurationError("Session already configured.") self._check_settings_sanity(settings) self._init_keys(settings) assert 'signature_key' in settings self.settings = settings try: backend = self.settings['backend'] self.session_class = get_session_class(backend) except ValueError: raise SessionConfigurationError("Backend %s not found." % backend) except KeyError: raise SessionConfigurationError("No backend given, please " "specifiy a 'backend' setting.") # Check if we can encrypt: # This is just a failsafe check to throw up at configuration already if 'encryption_key' in self.settings and not encryption_available(): raise CryptoError("Encryption not available, install pycrypto.")
def test_encryption_available_recheck(): assert encryption_available() del crypto.conf["encryption_available"] with pytest.raises(KeyError): assert not encryption_available() assert encryption_available(recheck=True)
def test_encryption_available_fails(): oldval = crypto.conf["encryption_available"] crypto.conf["encryption_available"] = False assert not encryption_available() crypto.conf["encryption_available"] = oldval
def test_encryption_available(): assert encryption_available()