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
def test_good_anonymous_handshake(coolorg, check_rvk):
    sh = ServerHandshake()

    if check_rvk:
        ch = APIV1_AnonymousClientHandshake(coolorg.organization_id,
                                            coolorg.root_verify_key)
    else:
        ch = APIV1_AnonymousClientHandshake(coolorg.organization_id)
    assert sh.state == "stalled"

    challenge_req = sh.build_challenge_req()
    assert sh.state == "challenge"

    answer_req = ch.process_challenge_req(challenge_req)

    sh.process_answer_req(answer_req)
    assert sh.state == "answer"
    assert sh.answer_type == APIV1_HandshakeType.ANONYMOUS
    if check_rvk:
        assert sh.answer_data == {
            "client_api_version": API_V1_VERSION,
            "organization_id": coolorg.organization_id,
            "rvk": coolorg.root_verify_key,
        }
    else:
        assert sh.answer_data == {
            "client_api_version": API_V1_VERSION,
            "organization_id": coolorg.organization_id,
            "rvk": None,
        }
    result_req = sh.build_result_req()
    assert sh.state == "result"

    ch.process_result_req(result_req)
    assert sh.client_api_version == API_V1_VERSION
Example #3
0
def test_good_handshake(alice):
    sh = ServerHandshake()

    ch = APIV1_AuthenticatedClientHandshake(alice.organization_id,
                                            alice.device_id, alice.signing_key,
                                            alice.root_verify_key)
    assert sh.state == "stalled"

    challenge_req = sh.build_challenge_req()
    assert sh.state == "challenge"

    answer_req = ch.process_challenge_req(challenge_req)

    sh.process_answer_req(answer_req)
    assert sh.state == "answer"
    assert sh.answer_type == APIV1_HandshakeType.AUTHENTICATED
    assert sh.answer_data == {
        "answer": ANY,
        "client_api_version": API_V1_VERSION,
        "organization_id": alice.organization_id,
        "device_id": alice.device_id,
        "rvk": alice.root_verify_key,
    }
    result_req = sh.build_result_req(alice.verify_key)
    assert sh.state == "result"

    ch.process_result_req(result_req)
    assert sh.client_api_version == API_V1_VERSION
Example #4
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_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))
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_good_administration_handshake():
    admin_token = "Xx" * 16
    sh = ServerHandshake()

    ch = APIV1_AdministrationClientHandshake(admin_token)
    assert sh.state == "stalled"

    challenge_req = sh.build_challenge_req()
    assert sh.state == "challenge"

    answer_req = ch.process_challenge_req(challenge_req)

    sh.process_answer_req(answer_req)
    assert sh.state == "answer"
    assert sh.answer_type == APIV1_HandshakeType.ADMINISTRATION
    assert sh.answer_data == {"client_api_version": API_V1_VERSION, "token": admin_token}
    result_req = sh.build_result_req()
    assert sh.state == "result"

    ch.process_result_req(result_req)
    assert sh.client_api_version == API_V1_VERSION