예제 #1
0
def test_serializer_loads_bad_data():
    class BirdSchema(BaseSchema):
        flying = fields.Boolean(required=True)

    serializer = MsgpackSerializer(BirdSchema)
    for raw in (packb(0), packb([]), packb({}), b"dummy"):
        with pytest.raises(SerdeError):
            serializer.loads(raw)
예제 #2
0
    async def _client_handler(stream):

        # General exception handling
        try:

            # Stream handling
            try:

                unpacker = Unpacker()
                async for raw in stream:
                    unpacker.feed(raw)
                    for cmd in unpacker:
                        cmd = cmd_req_serializer.load(cmd)
                        rep = await cmd_handler(cmd)
                        raw_rep = cmd_rep_serializer.dumps(rep)
                        logger.info("Command processed",
                                    cmd=cmd["cmd"],
                                    rep_status=rep["status"])
                        await stream.send_all(raw_rep)

            except SerdeError as exc:
                await stream.send_all(
                    packb({
                        "status": "invalid_format",
                        "reason": str(exc)
                    }))

            finally:
                await stream.aclose()

        except trio.BrokenResourceError:
            pass  # Peer has closed the connection while we were sending a response

        except Exception:
            logger.exception("Unexpected crash")
예제 #3
0
def test_supports_legacy_is_admin_field(alice):
    # Manually craft a local user in legacy format
    raw_legacy_local_user = {
        "organization_addr": alice.organization_addr.to_url(),
        "device_id": str(alice.device_id),
        "signing_key": alice.signing_key.encode(),
        "private_key": alice.private_key.encode(),
        "is_admin": True,
        "user_manifest_id": UUID(alice.user_manifest_id.hex),
        "user_manifest_key": bytes(alice.user_manifest_key.secret),
        "local_symkey": bytes(alice.local_symkey.secret),
    }
    dumped_legacy_local_user = packb(raw_legacy_local_user)

    # Make sure the legacy format can be loaded
    legacy_local_user = LocalDevice.load(dumped_legacy_local_user)
    assert legacy_local_user == alice

    # Manually decode new format to check it is compatible with legacy
    dumped_local_user = alice.dump()
    raw_local_user = unpackb(dumped_local_user)
    assert raw_local_user == {
        **raw_legacy_local_user,
        "profile": alice.profile.value,
        "human_handle": None,
        "device_label": None,
    }
예제 #4
0
def test_list_devices_support_key_file(config_dir, type):
    if type == "password":
        data_extra = {"type": "password", "salt": b"12345"}
        available_device_extra = {"type": DeviceFileType.PASSWORD}

    elif type == "smartcard":
        data_extra = {
            "type": "smartcard",
            "encrypted_key": b"12345",
            "certificate_id": "42",
            "certificate_sha1": b"12345",
        }
        available_device_extra = {"type": DeviceFileType.SMARTCARD}

    # Device information
    user_id = uuid4().hex
    device_name = uuid4().hex
    organization_id = "Org"
    rvk_hash = (uuid4().hex)[:10]
    device_id = f"{user_id}@{device_name}"
    slug = f"{rvk_hash}#{organization_id}#{device_id}"
    human_label = "Billy Mc BillFace"
    human_email = "*****@*****.**"
    device_label = "My device"

    # Craft file data
    key_file_data = packb({
        "ciphertext":
        b"whatever",
        "human_handle": (human_email.encode(), human_label.encode()),
        "device_label":
        device_label,
        "device_id":
        device_id,
        "organization_id":
        organization_id,
        "slug":
        slug,
        **data_extra,
    })

    key_file_path = get_devices_dir(config_dir) / "device.keys"
    key_file_path.parent.mkdir(parents=True)
    key_file_path.write_bytes(key_file_data)

    devices = list_available_devices(config_dir)
    expected_device = AvailableDevice(
        key_file_path=key_file_path,
        organization_id=OrganizationID(organization_id),
        device_id=DeviceID(device_id),
        human_handle=HumanHandle(human_email, human_label),
        device_label=DeviceLabel(device_label),
        slug=slug,
        **available_device_extra,
    )
    assert devices == [expected_device]
    assert get_key_file(config_dir, expected_device) == key_file_path
예제 #5
0
파일: http.py 프로젝트: Scille/parsec-cloud
 def build_msgpack(
         cls,
         status_code: int,
         data: dict,
         headers: Optional[Dict[bytes, bytes]] = None) -> "HTTPResponse":
     headers = headers or {}
     headers[b"content-type"] = b"application/msgpack"
     return cls.build(status_code=status_code,
                      headers=headers,
                      data=packb(data))
예제 #6
0
async def send_signal(conn, signal, **kwargs):
    # PostgreSQL's NOTIFY only accept string as payload, hence we must
    # use base64 on our payload...
    raw_data = b64encode(packb({
        "__signal__": signal,
        **kwargs
    })).decode("ascii")
    await conn.execute("SELECT pg_notify($1, $2)", "app_notification",
                       raw_data)
    logger.debug("notif sent", signal=signal, kwargs=kwargs)
예제 #7
0
async def send_signal(conn, signal, **kwargs):
    # PostgreSQL's NOTIFY only accept string as payload, hence we must
    # use base64 on our payload...

    # Add UUID to ensure the payload is unique given it seems Postgresql can
    # drop duplicated NOTIFY (same channel/payload)
    # see: https://github.com/Scille/parsec-cloud/issues/199
    raw_data = b64encode(packb({"__id__": uuid4().hex, "__signal__": signal, **kwargs})).decode(
        "ascii"
    )
    await conn.execute("SELECT pg_notify($1, $2)", "app_notification", raw_data)
    logger.debug("notif sent", signal=signal, kwargs=kwargs)
예제 #8
0
def test_list_devices_support_legacy_file_with_meaningful_name(config_dir):
    # Legacy path might exceed the 256 characters limit in some cases (see issue #1356)
    # So we use the `\\?\` workaround: https://stackoverflow.com/a/57502760/2846140
    if sys.platform == "win32":
        config_dir = Path("\\\\?\\" + str(config_dir.resolve()))

    # Device information
    user_id = uuid4().hex
    device_name = uuid4().hex
    organization_id = "Org"
    rvk_hash = (uuid4().hex)[:10]
    device_id = f"{user_id}@{device_name}"
    slug = f"{rvk_hash}#{organization_id}#{device_id}"
    human_label = "Billy Mc BillFace"
    human_email = "*****@*****.**"
    device_label = "My device"

    # Craft file data without the user_id, organization_id and slug fields
    key_file_data = packb({
        "type":
        "password",
        "salt":
        b"12345",
        "ciphertext":
        b"whatever",
        "human_handle": (human_email.encode(), human_label.encode()),
        "device_label":
        device_label,
    })

    key_file_path = get_devices_dir(config_dir) / slug / f"{slug}.keys"
    key_file_path.parent.mkdir(parents=True)
    key_file_path.write_bytes(key_file_data)

    devices = list_available_devices(config_dir)
    expected_device = AvailableDevice(
        key_file_path=key_file_path,
        organization_id=OrganizationID(organization_id),
        device_id=DeviceID(device_id),
        human_handle=HumanHandle(human_email, human_label),
        device_label=DeviceLabel(device_label),
        slug=slug,
        type=DeviceFileType.PASSWORD,
    )
    assert devices == [expected_device]
    assert get_key_file(config_dir, expected_device) == key_file_path
def test_list_devices_support_legacy_file_without_labels(config_dir):
    # Craft file data without the labels fields
    key_file_data = packb({
        "type": "password",
        "salt": b"12345",
        "ciphertext": b"whatever"
    })
    slug = "9d84fbd57a#Org#Zack@PC1"
    key_file_path = get_devices_dir(config_dir) / slug / f"{slug}.keys"
    key_file_path.parent.mkdir(parents=True)
    key_file_path.write_bytes(key_file_data)

    devices = list_available_devices(config_dir)
    expected_device = AvailableDevice(
        key_file_path=key_file_path,
        organization_id=OrganizationID("Org"),
        device_id=DeviceID("Zack@PC1"),
        human_handle=None,
        device_label=None,
    )
    assert devices == [expected_device]
예제 #10
0
def test_user_certificate_supports_legacy_is_admin_field(alice, bob):
    now = pendulum_now()
    certif = UserCertificateContent(
        author=bob.device_id,
        timestamp=now,
        user_id=alice.user_id,
        human_handle=None,
        public_key=alice.public_key,
        profile=alice.profile,
    )

    # Manually craft a certificate in legacy format
    raw_legacy_certif = {
        "type": "user_certificate",
        "author": bob.device_id,
        "timestamp": now,
        "user_id": alice.user_id,
        "public_key": alice.public_key.encode(),
        "is_admin": True,
    }
    dumped_legacy_certif = bob.signing_key.sign(
        zlib.compress(packb(raw_legacy_certif)))

    # Make sure the legacy format can be loaded
    legacy_certif = UserCertificateContent.verify_and_load(
        dumped_legacy_certif,
        author_verify_key=bob.verify_key,
        expected_author=bob.device_id,
        expected_user=alice.user_id,
        expected_human_handle=None,
    )
    assert legacy_certif == certif

    # Manually decode new format to check it is compatible with legacy
    dumped_certif = certif.dump_and_sign(bob.signing_key)
    raw_certif = unpackb(zlib.decompress(bob.verify_key.verify(dumped_certif)))
    assert raw_certif == {
        **raw_legacy_certif, "profile": alice.profile.value,
        "human_handle": None
    }
예제 #11
0
def test_pack_uuid():
    data = {"uuid": uuid.uuid4()}
    packed = packb(data)
    unpacked = unpackb(packed)
    assert unpacked == data
    assert isinstance(unpacked["uuid"], uuid.UUID)
예제 #12
0
def test_pack_datetime():
    data = {"date": pendulum.now()}
    packed = packb(data)
    unpacked = unpackb(packed)
    assert unpacked == data
    assert isinstance(unpacked["date"], pendulum.DateTime)