Ejemplo n.º 1
0
def test_get_hsdirs_no_consensus():
    """
    `get_hsdirs` should raise an exception when we don't have a valid
    HSDir list from the consensus.
    """

    with pytest.raises(ValueError):
        consensus.get_hsdirs('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')
Ejemplo n.º 2
0
def test_get_hsdirs_edge_of_ring(monkeypatch):
    """Test that selection wraps around the edge of the HSDir ring"""

    monkeypatch.setattr(consensus, 'HSDIR_LIST', MOCK_HSDIR_LIST)

    # Descriptor ID before '666....''
    descriptor_id_base32 = "mzqaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
    responsible_hsdirs = consensus.get_hsdirs(descriptor_id_base32)

    assert (responsible_hsdirs == [
        "6666666666666666666666666666666666666666",
        "1111111111111111111111111111111111111111",
        "2222222222222222222222222222222222222222",
    ])
Ejemplo n.º 3
0
def test_get_hsdirs(monkeypatch):
    """Test for normal responsible HSDir selection"""

    monkeypatch.setattr(consensus, 'HSDIR_LIST', MOCK_HSDIR_LIST)

    # Descriptor ID before '222....''
    descriptor_id_base32 = "eiqaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
    responsible_hsdirs = consensus.get_hsdirs(descriptor_id_base32)

    assert (responsible_hsdirs == [
        "2222222222222222222222222222222222222222",
        "3333333333333333333333333333333333333333",
        "4444444444444444444444444444444444444444",
    ])
Ejemplo n.º 4
0
def test_get_hsdirs_no_repeat(monkeypatch):
    """Test that selection wraps around the edge of the HSDir ring"""

    SHORT_HSDIR_LIST = [
        "1111111111111111111111111111111111111111",
        "2222222222222222222222222222222222222222",
    ]
    monkeypatch.setattr(consensus, 'HSDIR_LIST', SHORT_HSDIR_LIST)

    # Descriptor ID before '111....''
    descriptor_id_base32 = "ceiaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
    responsible_hsdirs = consensus.get_hsdirs(descriptor_id_base32)

    assert (responsible_hsdirs == [
        "1111111111111111111111111111111111111111",
        "2222222222222222222222222222222222222222",
    ])
Ejemplo n.º 5
0
    def _publish_descriptor(self, deviation=0):
        """
        Create, sign and upload master descriptors for this service
        """

        # Retrieve the set of available introduction points
        intro_point_set = self._select_introduction_points()
        max_intro_points = config.MAX_INTRO_POINTS

        # Upload multiple unique descriptors which contain different
        # subsets of the available introduction points.
        # (https://github.com/DonnchaC/onionbalance/issues/16)
        distinct_descriptors = config.DISTINCT_DESCRIPTORS

        # If we have <= MAX_INTRO_POINTS we should choose the introduction
        # points now and use the same set in every descriptor. Using the
        # same set of introduction points will look more like a standard
        # Tor client.
        num_intro_points = len(intro_point_set)

        if num_intro_points <= max_intro_points:
            intro_points = intro_point_set.choose(num_intro_points)
            logger.debug("We have %d IPs, not using distinct descriptors.",
                         len(intro_point_set))
            distinct_descriptors = False

        for replica in range(0, config.REPLICAS):
            # Using distinct descriptors, choose a new set of intro points
            # for each descriptor and upload it to individual HSDirs.
            if distinct_descriptors:
                descriptor_id = util.calc_descriptor_id_b32(
                    self.onion_address,
                    time=time.time(),
                    replica=replica,
                    deviation=deviation,
                )
                responsible_hsdirs = consensus.get_hsdirs(descriptor_id)

                for hsdir in responsible_hsdirs:
                    intro_points = intro_point_set.choose(max_intro_points)
                    try:
                        signed_descriptor = (
                            descriptor.generate_service_descriptor(
                                self.service_key,
                                introduction_point_list=intro_points,
                                replica=replica,
                                deviation=deviation))
                    except ValueError as exc:
                        logger.warning("Error generating descriptor: %s", exc)
                        continue

                    # Signed descriptor was generated successfully, upload it
                    # to the respective HSDir
                    self._upload_descriptor(signed_descriptor,
                                            replica,
                                            hsdirs=hsdir)
                logger.info(
                    "Published distinct master descriptors for "
                    "service %s.onion under replica %d.", self.onion_address,
                    replica)

            else:
                # Not using distinct descriptors, upload one descriptor
                # under each replica and let Tor pick the HSDirs.
                try:
                    signed_descriptor = descriptor.generate_service_descriptor(
                        self.service_key,
                        introduction_point_list=intro_points,
                        replica=replica,
                        deviation=deviation)
                except ValueError as exc:
                    logger.warning("Error generating descriptor: %s", exc)
                    continue

                # Signed descriptor was generated successfully, upload it
                self._upload_descriptor(signed_descriptor, replica)
                logger.info(
                    "Published a descriptor for service %s.onion "
                    "under replica %d.", self.onion_address, replica)

        # It would be better to set last_uploaded when an upload succeeds and
        # not when an upload is just attempted. Unfortunately the HS_DESC #
        # UPLOADED event does not provide information about the service and
        # so it can't be used to determine when descriptor upload succeeds
        self.uploaded = datetime.datetime.utcnow()