示例#1
0
    def test_check_auth_invalid_update_mntner_wrong_password_current_db_object(
            self, prepare_mocks):
        mock_dq, mock_dh = prepare_mocks

        # Make the crypt password invalid in the version from the mock database
        mock_dh.execute_query = lambda query: [{
            'object_text':
            SAMPLE_MNTNER.replace('CRYPT-PW', 'FAILED')
        }]

        reference_validator = ReferenceValidator(mock_dh)
        auth_validator = AuthValidator(mock_dh)

        # This password is valid for the new object, but invalid for the current version in the DB
        result_mntner = parse_update_requests(
            SAMPLE_MNTNER + 'password: crypt-password', mock_dh,
            auth_validator, reference_validator)[0]
        auth_validator.pre_approve([result_mntner])
        assert not result_mntner._check_auth()
        assert result_mntner.error_messages == [
            'Authorisation for mntner TEST-MNT failed: must by authenticated by one of: TEST-MNT, '
            'OTHER1-MNT, OTHER2-MNT'
        ]
        assert flatten_mock_calls(mock_dq) == [
            ['sources', (['TEST'], ), {}],
            ['object_classes', (['mntner'], ), {}],
            ['rpsl_pk', ('TEST-MNT', ), {}],
            ['sources', (['TEST'], ), {}],
            ['object_classes', (['mntner'], ), {}],
            ['rpsl_pks', (['TEST-MNT', 'OTHER1-MNT', 'OTHER2-MNT'], ), {}],
            ['sources', (['TEST'], ), {}],
            ['object_classes', (['mntner'], ), {}],
            ['rpsl_pks', (['TEST-MNT', 'OTHER1-MNT', 'OTHER2-MNT'], ), {}],
        ]
示例#2
0
    def test_check_auth_invalid_update_mntner_submits_new_object_with_dummy_hash_multiple_passwords(
            self, prepare_mocks):
        mock_dq, mock_dh = prepare_mocks

        mock_dh.execute_query = lambda query: [{'object_text': SAMPLE_MNTNER}]

        reference_validator = ReferenceValidator(mock_dh)
        auth_validator = AuthValidator(mock_dh)

        # Submit the mntner with dummy password values as would be returned by queries,
        # but multiple password attributes, which means we wouldn't know which password to set.
        data = SAMPLE_MNTNER.replace('LEuuhsBJNFV0Q',
                                     PASSWORD_HASH_DUMMY_VALUE)
        data = data.replace('$1$fgW84Y9r$kKEn9MUq8PChNKpQhO6BM.',
                            PASSWORD_HASH_DUMMY_VALUE)
        result_mntner = parse_change_requests(
            data + 'password: md5-password\npassword: other-password', mock_dh,
            auth_validator, reference_validator)[0]
        auth_validator.pre_approve([result_mntner])
        result_mntner._check_auth()
        assert not result_mntner.is_valid()
        assert result_mntner.error_messages == [
            'Object submitted with dummy hash values, but multiple or no passwords submitted. '
            'Either submit only full hashes, or a single password.'
        ]
示例#3
0
    def test_check_auth_invalid_create_mntner_referencing_self_with_dummy_passwords(
            self, prepare_mocks):
        mock_dq, mock_dh = prepare_mocks

        mock_dh.execute_query = lambda query: []

        reference_validator = ReferenceValidator(mock_dh)
        auth_validator = AuthValidator(mock_dh)

        # Submit the mntner with dummy password values as would be returned by queries.
        # This should not be allowed in new objects.
        data = SAMPLE_MNTNER.replace('LEuuhsBJNFV0Q',
                                     PASSWORD_HASH_DUMMY_VALUE)
        data = data.replace('$1$fgW84Y9r$kKEn9MUq8PChNKpQhO6BM.',
                            PASSWORD_HASH_DUMMY_VALUE)
        result_mntner = parse_update_requests(
            data + 'password: crypt-password', mock_dh, auth_validator,
            reference_validator)[0]
        auth_validator.pre_approve([result_mntner])

        assert not result_mntner._check_auth()
        assert result_mntner.error_messages == [
            'Authorisation failed for the auth methods on this mntner object.'
        ]
        assert flatten_mock_calls(mock_dq) == [
            ['sources', (['TEST'], ), {}],
            ['object_classes', (['mntner'], ), {}],
            ['rpsl_pk', ('TEST-MNT', ), {}],
        ]
示例#4
0
    def test_non_authorative_source(self, prepare_mocks):
        mock_dq, mock_dh = prepare_mocks

        mock_dh.execute_query = lambda query: []

        auth_validator = AuthValidator(mock_dh)
        result = parse_change_requests(SAMPLE_MNTNER.replace('TEST', 'TEST2'),
                                       mock_dh, auth_validator, None)[0]

        assert result.status == UpdateRequestStatus.ERROR_NON_AUTHORITIVE
        assert not result.is_valid()
        assert result.error_messages == [
            'This instance is not authoritative for source TEST2'
        ]
示例#5
0
    def test_check_auth_valid_update_mntner_submits_new_object_with_all_dummy_hash_values(
            self, prepare_mocks):
        mock_dq, mock_dh = prepare_mocks

        mock_dh.execute_query = lambda query: [{'object_text': SAMPLE_MNTNER}]

        reference_validator = ReferenceValidator(mock_dh)
        auth_validator = AuthValidator(mock_dh)

        # Submit the mntner with dummy password values as would be returned by queries,
        # but a password attribute that is valid for the current DB object.
        data = SAMPLE_MNTNER.replace('LEuuhsBJNFV0Q',
                                     PASSWORD_HASH_DUMMY_VALUE)
        data = data.replace('$1$fgW84Y9r$kKEn9MUq8PChNKpQhO6BM.',
                            PASSWORD_HASH_DUMMY_VALUE)
        result_mntner = parse_change_requests(
            data + 'password: crypt-password', mock_dh, auth_validator,
            reference_validator)[0]
        auth_validator.pre_approve([result_mntner])
        assert result_mntner._check_auth()
        assert not result_mntner.error_messages
        assert result_mntner.info_messages == [
            'As you submitted dummy hash values, all password hashes on this object '
            'were replaced with a new MD5-PW hash of the password you provided for '
            'authentication.'
        ]

        auth_pgp, auth_hash = splitline_unicodesafe(
            result_mntner.rpsl_obj_new.parsed_data['auth'])
        assert auth_pgp == 'PGPKey-80F238C6'
        assert auth_hash.startswith('MD5-PW ')
        assert md5_crypt.verify('crypt-password', auth_hash[7:])
        assert auth_hash in result_mntner.rpsl_obj_new.render_rpsl_text()
        assert flatten_mock_calls(mock_dq) == [
            ['sources', (['TEST'], ), {}],
            ['object_classes', (['mntner'], ), {}],
            ['rpsl_pk', ('TEST-MNT', ), {}],
            ['sources', (['TEST'], ), {}],
            ['object_classes', (['mntner'], ), {}],
            ['rpsl_pks', ({'OTHER1-MNT', 'OTHER2-MNT', 'TEST-MNT'}, ), {}],
            ['sources', (['TEST'], ), {}],
            ['object_classes', (['mntner'], ), {}],
            ['rpsl_pks', ({'OTHER1-MNT', 'OTHER2-MNT'}, ), {}],
        ]
示例#6
0
    def test_check_auth_invalid_update_mntner_submits_new_object_with_mixed_dummy_hash_real_hash(
            self, prepare_mocks):
        mock_dq, mock_dh = prepare_mocks

        mock_dh.execute_query = lambda query: [{'object_text': SAMPLE_MNTNER}]

        reference_validator = ReferenceValidator(mock_dh)
        auth_validator = AuthValidator(mock_dh)

        # Submit the mntner with dummy password values as would be returned by queries,
        # but a password attribute that is valid for the current DB object.
        data = SAMPLE_MNTNER.replace('LEuuhsBJNFV0Q',
                                     PASSWORD_HASH_DUMMY_VALUE)
        result_mntner = parse_change_requests(data + 'password: md5-password',
                                              mock_dh, auth_validator,
                                              reference_validator)[0]
        auth_validator.pre_approve([result_mntner])
        assert not result_mntner.is_valid()
        assert result_mntner.error_messages == [
            'Either all password auth hashes in a submitted mntner must be dummy objects, or none.',
        ]
示例#7
0
IRRD_ROOT_PATH = str(Path(__file__).resolve().parents[2])
sys.path.append(IRRD_ROOT_PATH)

AS_SET_REFERRING_OTHER_SET = """as-set:         AS-TESTREF
descr:          description
members:        AS-SETTEST, AS65540
tech-c:         PERSON-TEST
admin-c:        PERSON-TEST
notify:         [email protected]
mnt-by:         TEST-MNT
changed:        2017-05-19T12:22:08Z
source:         TEST
remarks:        remark
"""

SAMPLE_MNTNER_CLEAN = SAMPLE_MNTNER.replace(
    'mnt-by:         OTHER1-MNT,OTHER2-MNT\n', '')
LARGE_UPDATE = '\n\n'.join([
    SAMPLE_AS_BLOCK,
    SAMPLE_AS_SET,
    SAMPLE_AUT_NUM,
    SAMPLE_AUT_NUM.replace('aut-num:        as065537', 'aut-num: as65538'),
    SAMPLE_AUT_NUM.replace('aut-num:        as065537', 'aut-num: as65539'),
    SAMPLE_AUT_NUM.replace('aut-num:        as065537', 'aut-num: as65540'),
    SAMPLE_DOMAIN,
    SAMPLE_FILTER_SET,
    SAMPLE_INET_RTR,
    SAMPLE_INET6NUM,
    SAMPLE_INETNUM,
    SAMPLE_KEY_CERT,
    SAMPLE_MNTNER_CLEAN,
    SAMPLE_PEERING_SET,
示例#8
0
from irrd.storage.database_handler import DatabaseHandler
from irrd.utils.rpsl_samples import (SAMPLE_AS_SET, SAMPLE_FILTER_SET,
                                     SAMPLE_MNTNER, SAMPLE_MNTNER_CRYPT,
                                     SAMPLE_MNTNER_MD5, SAMPLE_PERSON,
                                     SAMPLE_ROUTE, SAMPLE_ROUTE6)
from irrd.utils.test_utils import flatten_mock_calls
from irrd.utils.text import remove_auth_hashes

from irrd.storage.queries import RPSLDatabaseSuspendedQuery
from irrd.updates.parser_state import UpdateRequestType
from ..validators import AuthValidator, RulesValidator

VALID_PW = 'override-password'
INVALID_PW = 'not-override-password'
VALID_PW_HASH = '$1$J6KycItM$MbPaBU6iFSGFV299Rk7Di0'
MNTNER_OBJ_CRYPT_PW = SAMPLE_MNTNER.replace('MD5', '')
MNTNER_OBJ_MD5_PW = SAMPLE_MNTNER.replace('CRYPT', '')


class TestAuthValidator:
    @pytest.fixture()
    def prepare_mocks(self, monkeypatch, config_override):
        mock_dh = Mock()
        mock_dq = Mock()
        monkeypatch.setattr('irrd.updates.validators.RPSLDatabaseQuery',
                            lambda: mock_dq)

        config_override({
            'auth': {
                'password_hashers': {
                    'crypt-pw': 'enabled'