Example #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 = APIV1_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])

    # 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
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
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
Example #4
0
async def check_forbidden_cmds(backend_sock, cmds):
    for cmd in cmds:
        await backend_sock.send(packb({"cmd": cmd}))
        rep = await backend_sock.recv()
        assert unpackb(rep) == {
            "status": "unknown_command",
            "reason": "Unknown command"
        }
Example #5
0
async def test_non_admin_has_limited_access(alice_backend_sock):
    for cmd in (ADMINISTRATION_CMDS | ANONYMOUS_CMDS) - AUTHENTICATED_CMDS:
        await alice_backend_sock.send(packb({"cmd": cmd}))
        rep = await alice_backend_sock.recv()
        assert unpackb(rep) == {
            "status": "unknown_command",
            "reason": "Unknown command"
        }
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
Example #7
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
def test_process_answer_req_bad_format(req, alice):
    for key, good_value in [
        ("organization_id", str(alice.organization_id)),
        ("device_id", str(alice.device_id)),
        ("rvk", alice.root_verify_key.encode()),
    ]:
        if req.get(key) == "<good>":
            req[key] = good_value
    req["client_api_version"] = API_V1_VERSION
    sh = ServerHandshake()
    sh.build_challenge_req()
    with pytest.raises(InvalidMessageError):
        sh.process_answer_req(packb(req))
Example #9
0
def test_build_result_req_bad_challenge(alice):
    sh = ServerHandshake()
    sh.build_challenge_req()
    answer = {
        "handshake": "answer",
        "type": "authenticated",
        "client_api_version": API_V1_VERSION,
        "organization_id": alice.organization_id,
        "device_id": alice.device_id,
        "rvk": alice.root_verify_key.encode(),
        "answer": alice.signing_key.sign(sh.challenge + b"-dummy"),
    }
    sh.process_answer_req(packb(answer))
    with pytest.raises(HandshakeFailedChallenge):
        sh.build_result_req(alice.verify_key)
def test_build_bad_outcomes(alice, method, expected_result):
    sh = ServerHandshake()
    sh.build_challenge_req()
    answer = {
        "handshake": "answer",
        "type": "authenticated",
        "client_api_version": API_V1_VERSION,
        "organization_id": alice.organization_id,
        "device_id": alice.device_id,
        "rvk": alice.root_verify_key.encode(),
        "answer": alice.signing_key.sign(sh.challenge),
    }
    sh.process_answer_req(packb(answer))
    req = getattr(sh, method)()
    assert unpackb(req) == {"handshake": "result", "result": expected_result, "help": ANY}
def test_build_bad_outcomes(alice, method, expected_result):
    sh = ServerHandshake()
    sh.build_challenge_req()
    answer = {
        "handshake": "answer",
        "type": APIV1_HandshakeType.ANONYMOUS.value,
        "client_api_version": API_V1_VERSION,
        "organization_id": str(alice.organization_id),
        "answer": alice.signing_key.sign(sh.challenge),
    }
    sh.process_answer_req(packb(answer))
    req = getattr(sh, method)()
    assert unpackb(req) == {
        "handshake": "result",
        "result": expected_result,
        "help": ANY
    }
def test_process_result_req_bad_outcome(result, exc_cls):
    ch = BaseClientHandshake()
    with pytest.raises(exc_cls):
        ch.process_result_req(packb({"handshake": "result", "result": result}))
def test_process_result_req_bad_format(req):
    ch = BaseClientHandshake()
    with pytest.raises(InvalidMessageError):
        ch.process_result_req(packb(req))
def test_process_challenge_req_bad_format(alice, req):
    ch = APIV1_AnonymousClientHandshake(alice.organization_id,
                                        alice.root_verify_key)
    with pytest.raises(InvalidMessageError):
        ch.process_challenge_req(packb(req))
Example #15
0
def test_process_challenge_req_bad_format(alice, req):
    ch = APIV1_AuthenticatedClientHandshake(alice.organization_id,
                                            alice.device_id, alice.signing_key,
                                            alice.root_verify_key)
    with pytest.raises(InvalidMessageError):
        ch.process_challenge_req(packb(req))
Example #16
0
async def test_connect_as_anonymous(anonymous_backend_sock):
    await anonymous_backend_sock.send(packb({"cmd": "ping", "ping": "foo"}))
    rep = await anonymous_backend_sock.recv()
    assert unpackb(rep) == {"status": "ok", "pong": "foo"}