Exemple #1
0
    def test_check_token_invalid_timestamp_disabled_security(self):
        '''
		With disabled timestamp security, invalid timestamps should still
		succeed.
		'''
        now = datetime.datetime.utcnow().replace(tzinfo=utc.utc)
        nonce = utils._random_string()
        past = now - datetime.timedelta(seconds=settings.TIMESTAMP_DURATION +
                                        1)
        past_token = utils.make_token('user', 'secr3t', nonce, past)

        future = now + datetime.timedelta(seconds=settings.DRIFT_OFFSET + 1)
        nonce = utils._random_string()
        future_token = utils.make_token('user', 'secr3t', nonce, future)

        with mock.patch.object(settings, 'SECURITY_CHECK_TIMESTAMP', False):
            try:
                self.assertEqual(
                    utils.check_token(past_token, lambda x: 'secr3t'), 'user')
            except exceptions.InvalidTimestamp:
                self.fail(
                    'InvalidTimestamp raised with expired timestamp and ' +
                    'timestamp security disabled.')

            try:
                self.assertEqual(
                    utils.check_token(future_token, lambda x: 'secr3t'),
                    'user')
            except exceptions.InvalidTimestamp:
                self.fail(
                    'InvalidTimestamp raised with expired timestamp and ' +
                    'timestamp security disabled.')
Exemple #2
0
    def test_random_string_length(self):
        '''
		The length of a generated string should match what is specified or the
		default length.
		'''
        self.assertEqual(len(utils._random_string(10)), 10)
        self.assertEqual(len(utils._random_string()), settings.NONCE_LENGTH)
        self.assertEqual(len(utils._random_string(settings.NONCE_LENGTH + 1)),
                         settings.NONCE_LENGTH + 1)
Exemple #3
0
    def test_random_string_is_random(self):
        '''
		Strings generated in sequence should not clash.
		'''
        strings = [utils._random_string() for _ in range(25)]

        self.assertEqual(len(set(strings)), len(strings))
Exemple #4
0
    def test_check_token(self):
        '''
		Check a token that was just generated.
		'''
        now = datetime.datetime.utcnow().replace(tzinfo=utc.utc)
        nonce = utils._random_string()
        token = utils.make_token('user', 'secr3t', nonce, now)

        self.assertEqual(utils.check_token(token, lambda x: 'secr3t'), 'user')
Exemple #5
0
    def test_check_token_invalid_password(self):
        '''
		Check a valid token with an invalid password.
		'''
        now = datetime.datetime.utcnow().replace(tzinfo=utc.utc)
        nonce = utils._random_string()
        token = utils.make_token('user', 'wrong password', nonce, now)

        self.assertIsNone(utils.check_token(token, lambda x: 'secr3t'))
Exemple #6
0
    def test_check_token_long_nonce(self):
        '''
		Check a token with a long nonce - it should be rejected.
		'''
        now = datetime.datetime.utcnow().replace(tzinfo=utc.utc)
        nonce = utils._random_string() + 'a'
        token = utils.make_token('user', 'secr3t', nonce, now)

        with self.assertRaises(exceptions.InvalidNonce):
            utils.check_token(token, lambda x: 'secr3t')
Exemple #7
0
    def test_check_token_short_nonce(self):
        '''
		Check a token with a short nonce - it should be rejected.
		'''
        now = datetime.datetime.utcnow().replace(tzinfo=utc.utc)
        nonce = utils._random_string(length=settings.NONCE_LENGTH - 1)
        token = utils.make_token('user', 'secr3t', nonce, now)

        with self.assertRaises(exceptions.InvalidNonce):
            utils.check_token(token, lambda x: 'secr3t')
Exemple #8
0
    def test_random_string_chars(self):
        '''
		The characters in the string should only contain those in the specified
		list.
		'''
        allowed_chars = 'abcde'
        string = utils._random_string(allowed_chars=allowed_chars)

        for c in string:
            self.assertIn(c, allowed_chars)
Exemple #9
0
    def test_check_token_replay_attack(self):
        '''
		Check a token twice - a replay attack should be detected.
		'''
        now = datetime.datetime.utcnow().replace(tzinfo=utc.utc)
        nonce = utils._random_string()
        token = utils.make_token('user', 'secr3t', nonce, now)

        utils.check_token(token, lambda x: 'secr3t')
        with self.assertRaises(exceptions.InvalidNonce):
            utils.check_token(token, lambda x: 'secr3t')
Exemple #10
0
    def test_check_token_expired_timestamp(self):
        '''
		Check a token that has an expired timestamp. An error should be raised.
		'''
        ts = (datetime.datetime.utcnow().replace(tzinfo=utc.utc) -
              datetime.timedelta(seconds=settings.TIMESTAMP_DURATION + 1))
        nonce = utils._random_string()
        token = utils.make_token('user', 'secr3t', nonce, ts)

        with self.assertRaises(exceptions.InvalidTimestamp):
            utils.check_token(token, lambda x: 'secr3t')
Exemple #11
0
    def test_check_token_drift(self):
        '''
		Check a token that has a timestamp with drift. The user should still be
		authenticated.
		'''
        ts = (datetime.datetime.utcnow().replace(tzinfo=utc.utc) +
              datetime.timedelta(seconds=settings.DRIFT_OFFSET - 1))
        nonce = utils._random_string()
        token = utils.make_token('user', 'secr3t', nonce, ts)

        self.assertEqual(utils.check_token(token, lambda x: 'secr3t'), 'user')
Exemple #12
0
    def test_check_token_nonexistent_user(self):
        '''
		Check a valid token but with a user does not exist. An error should be
		raised.
		'''
        users = {'username': None}
        now = datetime.datetime.utcnow().replace(tzinfo=utc.utc)
        nonce = utils._random_string()
        token = utils.make_token('user', 'secr3t', nonce, now)

        with self.assertRaises(exceptions.UserException):
            utils.check_token(token, lambda x: users[x])
Exemple #13
0
    def test_check_token_future_timestamp(self):
        '''
		Check a token that has a timestamp in the future. An error should be
		raised.
		'''
        ts = (datetime.datetime.utcnow().replace(tzinfo=utc.utc) +
              datetime.timedelta(seconds=settings.DRIFT_OFFSET + 1))
        nonce = utils._random_string()
        token = utils.make_token('user', 'secr3t', nonce, ts)

        with self.assertRaises(exceptions.InvalidTimestamp):
            utils.check_token(token, lambda x: 'secr3t')
Exemple #14
0
    def test_check_token_invalid_timestamp_format(self):
        '''
		Check a token that has a timestamp in an invalid format.
		'''
        ts = datetime.datetime.utcnow().replace(tzinfo=utc.utc)
        nonce = utils._random_string()
        token = utils.make_token('user',
                                 'secr3t',
                                 nonce,
                                 ts,
                                 ts_format='prefix-{}-suffix'.format(
                                     settings.TIMESTAMP_FORMATS[0]))

        with self.assertRaises(exceptions.InvalidTimestamp):
            utils.check_token(token, lambda x: 'secr3t')
Exemple #15
0
    def test_check_token_prohibited_algorithms(self):
        '''
		Check a valid token with prohibited algorithms. An error should be raised.
		'''
        for algorithm in settings.PROHIBITED_DIGEST_ALGORITHMS:
            now = datetime.datetime.utcnow().replace(tzinfo=utc.utc)
            nonce = utils._random_string()
            token = utils.make_token('user',
                                     'secr3t',
                                     nonce,
                                     now,
                                     algorithm=algorithm.lower())

            with self.assertRaises(exceptions.AlgorithmProhibited):
                utils.check_token(token, lambda x: 'secr3t')
Exemple #16
0
    def test_check_token_alterntive_timestamp_format(self):
        '''
		Check a token that was just generated with a timestamp in a different
		format.
		'''
        for fmt in settings.TIMESTAMP_FORMATS[1:]:
            now = datetime.datetime.utcnow().replace(tzinfo=utc.utc)
            nonce = utils._random_string()
            token = utils.make_token('user',
                                     'secr3t',
                                     nonce,
                                     now,
                                     ts_format=fmt)

            self.assertEqual(utils.check_token(token, lambda x: 'secr3t'),
                             'user')
Exemple #17
0
    def test_check_token_alternative_algorithm(self):
        '''
		Check a valid token with an alternative algorithm.
		'''
        now = datetime.datetime.utcnow().replace(tzinfo=utc.utc)
        nonce = utils._random_string()
        token = utils.make_token('user',
                                 'secr3t',
                                 nonce,
                                 now,
                                 algorithm='sha512')

        with mock.patch.object(settings, 'ALLOWED_DIGEST_ALGORITHMS',
                               ['SHA256', 'SHA512']):
            self.assertEqual(utils.check_token(token, lambda x: 'secr3t'),
                             'user')
Exemple #18
0
    def test_check_token_replay_attack_disabled_security(self):
        '''
		Check a token twice, but with nonce security disabled. A replay attack
		should not be detected.
		'''
        now = datetime.datetime.utcnow().replace(tzinfo=utc.utc)
        nonce = utils._random_string()
        token = utils.make_token('user', 'secr3t', nonce, now)

        with mock.patch.object(settings, 'SECURITY_CHECK_NONCE', False):
            self.assertEqual(utils.check_token(token, lambda x: 'secr3t'),
                             'user')

            try:
                self.assertEqual(utils.check_token(token, lambda x: 'secr3t'),
                                 'user')
            except exceptions.InvalidNonce:
                self.fail('InvalidNonce raised with nonce security disabled.')
    def make_header_values(self,
                           user=None,
                           username=None,
                           timestamp=None,
                           digest=None,
                           b64_digest=None,
                           nonce=None,
                           b64_nonce=None,
                           digest_algorithm=None):
        '''
		Make the header values from the given parameters.

		:param user: (optional) user to authenticate with header
		:type user: django.contrib.auth.models.User

		:param username: (optional) username to provide in header
		:type username: str

		:param timestamp: (optional) timestamp to use in header
		:type timestamp: str

		:param digest: (optional) header digest
		:type digest: bytes

		:param b64_digest: (optional) header digest as base64
		:type b64_digest: bytes

		:param nonce: (optional) header nonce
		:type nonce: bytes

		:param b64_nonce: (optional) header nonce as base64
		:type b64_nonce: bytes

		:param digest_algorithm: (optional, default: sha256) digest algorithm to
			use. It must be supported by hashlib.
		:type digest_algorithm: str

		:return: WSSE authentication header parts
		:rtype: dict
		'''
        if user is None:
            user = self.user
        if username is None:
            username = user.username

        if timestamp is None:
            now = timezone.now()
            timestamp = now.strftime(settings.TIMESTAMP_FORMATS[0])

        if nonce is None:
            nonce = utils._random_string(length=settings.NONCE_LENGTH)

        if digest is None:
            digest = utils._b64_digest(nonce,
                                       timestamp,
                                       self.user_secret.secret,
                                       algorithm=digest_algorithm)

        if b64_nonce is None:
            b64_nonce = base64.b64encode(utils._to_bytes(nonce))
        if b64_digest is not None:
            digest = b64_digest

        header_values = {
            'Username': username,
            'PasswordDigest': utils._from_bytes(digest),
            'Nonce': utils._from_bytes(b64_nonce),
            'Created': timestamp
        }

        return header_values