示例#1
0
def test_process_challenge_req_good_api_version(
    alice, monkeypatch, client_version, backend_version, valid
):
    # Cast parameters
    client_version = ApiVersion(*client_version)
    backend_version = ApiVersion(*backend_version)

    ch = AuthenticatedClientHandshake(
        alice.organization_id, alice.device_id, alice.signing_key, alice.root_verify_key
    )
    req = {
        "handshake": "challenge",
        "challenge": b"1234567890",
        "supported_api_versions": [backend_version],
    }
    monkeypatch.setattr(ch, "SUPPORTED_API_VERSIONS", [client_version])

    if not valid:
        # Invalid versioning
        with pytest.raises(HandshakeAPIVersionError) as context:
            ch.process_challenge_req(packb(req))
        assert context.value.client_versions == [client_version]
        assert context.value.backend_versions == [backend_version]

    else:
        # Valid versioning
        ch.process_challenge_req(packb(req))
        assert ch.challenge_data["supported_api_versions"] == [backend_version]
        assert ch.backend_api_version == backend_version
        assert ch.client_api_version == client_version
def test_process_challenge_req_good_api_version(alice, monkeypatch,
                                                client_version,
                                                backend_version, valid):
    # Cast parameters
    client_version = ApiVersion(*client_version)
    backend_version = ApiVersion(*backend_version)

    ch = APIV1_AnonymousClientHandshake(alice.organization_id,
                                        alice.root_verify_key)
    req = {
        "handshake": "challenge",
        "challenge": b"1234567890",
        "supported_api_versions": [backend_version],
        "backend_timestamp": pendulum.now(),
        "ballpark_client_early_offset": BALLPARK_CLIENT_EARLY_OFFSET,
        "ballpark_client_late_offset": BALLPARK_CLIENT_LATE_OFFSET,
    }
    monkeypatch.setattr(ch, "SUPPORTED_API_VERSIONS", [client_version])

    # Invalid versioning
    if not valid:
        with pytest.raises(HandshakeAPIVersionError) as context:
            ch.process_challenge_req(packb(req))
        assert context.value.client_versions == [client_version]
        assert context.value.backend_versions == [backend_version]
        return

    # Valid versioning
    ch.process_challenge_req(packb(req))
    assert ch.SUPPORTED_API_VERSIONS == [client_version]
    assert ch.challenge_data["supported_api_versions"] == [backend_version]
    assert ch.backend_api_version == backend_version
    assert ch.client_api_version == client_version
示例#3
0
def test_handshake_challenge_schema_for_client_server_api_compatibility(
        mallory, alice, monkeypatch):
    ash = ServerHandshake()

    bch = AuthenticatedClientHandshake(mallory.organization_id,
                                       mallory.device_id, mallory.signing_key,
                                       mallory.root_verify_key)

    challenge = b"1234567890"

    # Backend API >= 2.5 and Client API < 2.5
    client_version = ApiVersion(2, 4)
    backend_version = ApiVersion(2, 5)

    answer = {
        "handshake": "answer",
        "type": HandshakeType.AUTHENTICATED.value,
        "client_api_version": client_version,
        "organization_id": str(alice.organization_id),
        "device_id": str(alice.device_id),
        "rvk": alice.root_verify_key.encode(),
        "answer": alice.signing_key.sign(challenge),
    }

    ash.build_challenge_req()
    ash.challenge = challenge

    ash.process_answer_req(packb(answer))
    result_req = ash.build_result_req(alice.verify_key)

    result = handshake_result_serializer.loads(result_req)
    assert result["result"] == "ok"

    # Backend API < 2.5 and Client API >= 2.5
    client_version = ApiVersion(2, 5)
    backend_version = ApiVersion(2, 4)

    req = {
        "handshake": "challenge",
        "challenge": challenge,
        "supported_api_versions": [backend_version],
        "backend_timestamp": pendulum.now(),
        "ballpark_client_early_offset": BALLPARK_CLIENT_EARLY_OFFSET,
        "ballpark_client_late_offset": BALLPARK_CLIENT_LATE_OFFSET,
    }

    monkeypatch.setattr(bch, "SUPPORTED_API_VERSIONS", [client_version])

    answer_req = bch.process_challenge_req(packb(req))

    answer = handshake_answer_serializer.loads(answer_req)
    assert mallory.verify_key.verify(answer["answer"]) == challenge
示例#4
0
async def test_authenticated_handshake_bad_versions(
    backend, server_factory, alice, mock_api_versions
):
    ch = APIV1_AuthenticatedClientHandshake(
        alice.organization_id, alice.device_id, alice.signing_key, alice.root_verify_key
    )

    async with server_factory(backend.handle_client) as server:
        stream = server.connection_factory()
        transport = await Transport.init_for_client(stream, server.addr.hostname)

        challenge_req = await transport.recv()
        answer_req = ch.process_challenge_req(challenge_req)

        # Alter answer
        answer_dict = unpackb(answer_req)
        answer_dict["client_api_version"] = ApiVersion(3, 22)
        answer_req = packb(answer_dict)

        await transport.send(answer_req)
        result_req = await transport.recv()

        with pytest.raises(InvalidMessageError) as context:
            ch.process_result_req(result_req)
        assert "bad_protocol" in str(context.value)
        assert "{1.22}" in str(context.value)
示例#5
0
async def test_handshake_incompatible_version(backend, server_factory):
    async with server_factory(backend.handle_client) as server:
        stream = server.connection_factory()
        transport = await Transport.init_for_client(stream,
                                                    server.addr.hostname)

        incompatible_version = ApiVersion(API_VERSION.version + 1, 0)
        await transport.recv()  # Get challenge
        req = {
            "handshake": "answer",
            "type": "anonymous",
            "client_api_version": incompatible_version,
            "organization_id": OrganizationID("Org"),
            "token": "whatever",
        }
        await transport.send(packb(req))
        result_req = await transport.recv()
        assert unpackb(result_req) == {
            "handshake":
            "result",
            "result":
            "bad_protocol",
            "help":
            "No overlap between client API versions {3.0} and backend API versions {"
            + str(API_VERSION) + ", 1.3}",
        }
async def test_authenticated_handshake_no_longer_supported(
        backend, server_factory, alice):
    async with server_factory(backend.handle_client) as server:
        stream = await server.connection_factory()
        transport = await Transport.init_for_client(stream, "127.0.0.1")

        challenge_req = await transport.recv()
        challenge = unpackb(challenge_req)["challenge"]
        answer = alice.signing_key.sign(challenge)
        answer_req = {
            "handshake": "answer",
            "client_api_version": ApiVersion(1, 3),
            "type": "AUTHENTICATED",
            "organization_id": str(alice.organization_id),
            "device_id": str(alice.device_id),
            "rvk": alice.root_verify_key.encode(),
            "answer": answer,
        }

        await transport.send(packb(answer_req))
        result_req = await transport.recv()
        assert unpackb(result_req) == {
            "handshake": "result",
            "result": "bad_protocol",
            "help": "{'type': ['Unsupported value: AUTHENTICATED']}",
        }
def mock_api_versions(monkeypatch):
    default_client_version = ApiVersion(1, 11)
    default_backend_version = ApiVersion(1, 22)

    def _mock_api_versions(client_versions=None, backend_versions=None):
        if client_versions is not None:
            monkeypatch.setattr(APIV1_AnonymousClientHandshake,
                                "SUPPORTED_API_VERSIONS", client_versions)
        if backend_versions is not None:
            monkeypatch.setattr(ServerHandshake, "SUPPORTED_API_VERSIONS",
                                backend_versions)

    _mock_api_versions.default_client_version = default_client_version
    _mock_api_versions.default_backend_version = default_backend_version
    _mock_api_versions(client_versions=[default_client_version],
                       backend_versions=[default_backend_version])
    return _mock_api_versions
def test_process_challenge_req_good_multiple_api_version(
    alice,
    monkeypatch,
    client_versions,
    backend_versions,
    expected_client_version,
    expected_backend_version,
):
    # Cast parameters
    client_versions = [ApiVersion(*args) for args in client_versions]
    backend_versions = [ApiVersion(*args) for args in backend_versions]
    if expected_client_version:
        expected_client_version = ApiVersion(*expected_client_version)
    if expected_backend_version:
        expected_backend_version = ApiVersion(*expected_backend_version)

    ch = APIV1_AnonymousClientHandshake(alice.organization_id,
                                        alice.root_verify_key)
    req = {
        "handshake": "challenge",
        "challenge": b"1234567890",
        "supported_api_versions": list(backend_versions),
        "backend_timestamp": pendulum.now(),
        "ballpark_client_early_offset": BALLPARK_CLIENT_EARLY_OFFSET,
        "ballpark_client_late_offset": BALLPARK_CLIENT_LATE_OFFSET,
    }
    monkeypatch.setattr(ch, "SUPPORTED_API_VERSIONS", client_versions)

    # Invalid versioning
    if expected_client_version is None:
        with pytest.raises(HandshakeAPIVersionError) as context:
            ch.process_challenge_req(packb(req))
        assert context.value.client_versions == client_versions
        assert context.value.backend_versions == backend_versions
        return

    # Valid versioning
    ch.process_challenge_req(packb(req))
    assert ch.SUPPORTED_API_VERSIONS == client_versions
    assert ch.challenge_data["supported_api_versions"] == list(
        backend_versions)
    assert ch.backend_api_version == expected_backend_version
    assert ch.client_api_version == expected_client_version
示例#9
0
def test_process_challenge_req_good_multiple_api_version(
    alice,
    monkeypatch,
    client_versions,
    backend_versions,
    expected_client_version,
    expected_backend_version,
):
    # Cast parameters
    client_versions = [ApiVersion(*args) for args in client_versions]
    backend_versions = [ApiVersion(*args) for args in backend_versions]
    if expected_client_version:
        expected_client_version = ApiVersion(*expected_client_version)
    if expected_backend_version:
        expected_backend_version = ApiVersion(*expected_backend_version)

    ch = APIV1_AuthenticatedClientHandshake(alice.organization_id,
                                            alice.device_id, alice.signing_key,
                                            alice.root_verify_key)
    req = {
        "handshake": "challenge",
        "challenge": b"1234567890",
        "supported_api_versions": list(backend_versions),
    }
    monkeypatch.setattr(ch, "SUPPORTED_API_VERSIONS", client_versions)

    # Invalid versioning
    if expected_client_version is None:
        with pytest.raises(HandshakeAPIVersionError) as context:
            ch.process_challenge_req(packb(req))
        assert context.value.client_versions == client_versions
        assert context.value.backend_versions == backend_versions
        return

    # Valid versioning
    ch.process_challenge_req(packb(req))
    assert ch.SUPPORTED_API_VERSIONS == client_versions
    assert ch.challenge_data["supported_api_versions"] == list(
        backend_versions)
    assert ch.backend_api_version == expected_backend_version
    assert ch.client_api_version == expected_client_version
示例#10
0
async def test_anonymous_handshake_invalid_format(backend, server_factory):
    async with server_factory(backend.handle_client) as server:
        stream = server.connection_factory()
        transport = await Transport.init_for_client(stream, server.addr.hostname)

        await transport.recv()  # Get challenge
        req = {
            "handshake": "foo",
            "type": "anonymous",
            "client_api_version": ApiVersion(1, 1),
            "organization_id": "zob",
        }
        await transport.send(packb(req))
        result_req = await transport.recv()
        assert unpackb(result_req) == {
            "handshake": "result",
            "result": "bad_protocol",
            "help": "{'handshake': ['Invalid value, should be `answer`']}",
        }
示例#11
0
async def test_administration_handshake_no_longer_supported(
        backend, server_factory):
    async with server_factory(backend.handle_client) as server:
        stream = await server.connection_factory()
        transport = await Transport.init_for_client(stream, "127.0.0.1")

        await transport.recv()
        answer_req = {
            "handshake": "answer",
            "client_api_version": ApiVersion(1, 3),
            "type": "ADMINISTRATION",
            "token": backend.config.administration_token,
        }

        await transport.send(packb(answer_req))
        result_req = await transport.recv()
        assert unpackb(result_req) == {
            "handshake": "result",
            "result": "bad_protocol",
            "help": "{'type': ['Unsupported value: ADMINISTRATION']}",
        }
示例#12
0
async def test_handshake_incompatible_version(backend, server_factory):
    async with server_factory(backend.handle_client) as server:
        stream = await server.connection_factory()
        transport = await Transport.init_for_client(stream, "127.0.0.1")

        incompatible_version = ApiVersion(API_VERSION.version + 1, 0)
        await transport.recv()  # Get challenge
        req = {
            "handshake": "answer",
            "type": "anonymous",
            "client_api_version": incompatible_version,
            "organization_id": "Org",
            "token": "whatever",
        }
        await transport.send(packb(req))
        result_req = await transport.recv()
        assert unpackb(result_req) == {
            "handshake":
            "result",
            "result":
            "bad_protocol",
            "help":
            f"No overlap between client API versions {{{incompatible_version}}} and backend API versions {{{', '.join(map(str, ServerHandshake.SUPPORTED_API_VERSIONS))}}}",
        }
示例#13
0
 def _deserialize(self, *args: object, **kwargs: object) -> ApiVersion:
     result = super()._deserialize(*args, **kwargs)
     return ApiVersion(*result)
示例#14
0
 def _deserialize(self, *args, **kwargs):
     result = super()._deserialize(*args, **kwargs)
     return ApiVersion(*result)