示例#1
0
    def setUp(self):

        self.bridges = copy.deepcopy(util.generateFakeBridges())

        self.fd, self.fname = tempfile.mkstemp(suffix=".sqlite",
                                               dir=os.getcwd())
        bridgedb.Storage.initializeDBLock()
        self.db = bridgedb.Storage.openDatabase(self.fname)
        bridgedb.Storage.setDBFilename(self.fname)

        key = 'fake-hmac-key'
        self.splitter = Bridges.BridgeSplitter(key)
        ringParams = Bridges.BridgeRingParameters(needPorts=[(443, 1)],
                                                  needFlags=[("Stable", 1)])
        self.https_distributor = HTTPSDistributor(4,
                                                  crypto.getHMAC(
                                                      key,
                                                      "HTTPS-IP-Dist-Key"),
                                                  None,
                                                  answerParameters=ringParams)
        self.moat_distributor = MoatDistributor(4,
                                                crypto.getHMAC(
                                                    key, "Moat-Dist-Key"),
                                                None,
                                                answerParameters=ringParams)
        self.unallocated_distributor = Bridges.UnallocatedHolder()

        self.splitter.addRing(self.https_distributor.hashring, "https", p=10)
        self.splitter.addRing(self.moat_distributor.hashring, "moat", p=10)
        self.splitter.addRing(self.unallocated_distributor,
                              "unallocated",
                              p=10)
        self.https_ring = self.splitter.ringsByName.get("https")
        self.moat_ring = self.splitter.ringsByName.get("moat")
        self.unallocated_ring = self.splitter.ringsByName.get("unallocated")
示例#2
0
文件: Main.py 项目: aagbsn/bridgedb
def load(cfg, splitter, clear=False):
    """Read all the bridge files from cfg, and pass them into a splitter
       object.
    """
    countryblock = Bridges.CountryBlock()
    if clear:
        logging.info("Clearing old bridges")
        splitter.clear()
        logging.info("Clearing old blocked bridges")
        countryblock.clear() 
    logging.info("Loading bridges")
    status = {}
    if hasattr(cfg, "STATUS_FILE"):
        f = open(cfg.STATUS_FILE, 'r')
        for ID, running, stable in Bridges.parseStatusFile(f):
            status[ID] = running, stable
        f.close()
    if hasattr(cfg, "COUNTRY_BLOCK_FILE"):
        f = open(cfg.COUNTRY_BLOCK_FILE, 'r')
        for fingerprint, countryCode in Bridges.parseCountryBlockFile(f):
            countryblock.insert(fingerprint, countryCode)
        f.close() 
    for fname in cfg.BRIDGE_FILES:
        f = open(fname, 'r')
        for bridge in Bridges.parseDescFile(f, cfg.BRIDGE_PURPOSE):
            s = status.get(bridge.getID())
            if s is not None:
                running, stable = s
                bridge.setStatus(running=running, stable=stable)
            bridge.setBlockingCountries(
                    countryblock.getBlockingCountries(bridge.fingerprint)) 
            splitter.insert(bridge)
        f.close()
示例#3
0
 def setUp(self):
     self.rings = [
         Bridges.BridgeRing('fake-hmac-key-1'),
         Bridges.BridgeRing('fake-hmac-key-2')
     ]
     self.splitter = Bridges.FixedBridgeSplitter('fake-hmac-key',
                                                 self.rings)
示例#4
0
def load(cfg, splitter, clear=False):
    """Read all the bridge files from cfg, and pass them into a splitter
       object.
    """
    countryblock = Bridges.CountryBlock()
    if clear:
        logging.info("Clearing old bridges")
        splitter.clear()
        logging.info("Clearing old blocked bridges")
        countryblock.clear()
    logging.info("Loading bridges")
    status = {}
    if hasattr(cfg, "STATUS_FILE"):
        f = open(cfg.STATUS_FILE, 'r')
        for ID, running, stable in Bridges.parseStatusFile(f):
            status[ID] = running, stable
        f.close()
    if hasattr(cfg, "COUNTRY_BLOCK_FILE"):
        f = open(cfg.COUNTRY_BLOCK_FILE, 'r')
        for fingerprint, countryCode in Bridges.parseCountryBlockFile(f):
            countryblock.insert(fingerprint, countryCode)
        f.close()
    for fname in cfg.BRIDGE_FILES:
        f = open(fname, 'r')
        for bridge in Bridges.parseDescFile(f, cfg.BRIDGE_PURPOSE):
            s = status.get(bridge.getID())
            if s is not None:
                running, stable = s
                bridge.setStatus(running=running, stable=stable)
            bridge.setBlockingCountries(
                countryblock.getBlockingCountries(bridge.fingerprint))
            splitter.insert(bridge)
        f.close()
示例#5
0
def createBridgeRings(cfg, proxyList, key):
    """Create the bridge distributors defined by the config file

    :type cfg:  :class:`Conf`
    :param cfg: The current configuration, including any in-memory settings
        (i.e. settings whose values were not obtained from the config file,
        but were set via a function somewhere)
    :type proxyList: :class:`~bridgedb.proxy.ProxySet`
    :param proxyList: The container for the IP addresses of any currently
        known open proxies.
    :param bytes key: Hashring master key
    :rtype: tuple
    :returns: A BridgeSplitter hashring, an
        :class:`~bridgedb.https.distributor.HTTPSDistributor` or None, and an
        :class:`~bridgedb.email.distributor.EmailDistributor` or None.
    """
    # Create a BridgeSplitter to assign the bridges to the different
    # distributors.
    hashring = Bridges.BridgeSplitter(crypto.getHMAC(key, "Hashring-Key"))
    logging.debug("Created hashring: %r" % hashring)

    # Create ring parameters.
    ringParams = Bridges.BridgeRingParameters(needPorts=cfg.FORCE_PORTS,
                                              needFlags=cfg.FORCE_FLAGS)

    emailDistributor = ipDistributor = None
    # As appropriate, create an IP-based distributor.
    if cfg.HTTPS_DIST and cfg.HTTPS_SHARE:
        logging.debug("Setting up HTTPS Distributor...")
        ipDistributor = HTTPSDistributor(cfg.N_IP_CLUSTERS,
                                         crypto.getHMAC(
                                             key, "HTTPS-IP-Dist-Key"),
                                         proxyList,
                                         answerParameters=ringParams)
        hashring.addRing(ipDistributor.hashring, "https", cfg.HTTPS_SHARE)

    # As appropriate, create an email-based distributor.
    if cfg.EMAIL_DIST and cfg.EMAIL_SHARE:
        logging.debug("Setting up Email Distributor...")
        emailDistributor = EmailDistributor(
            crypto.getHMAC(key, "Email-Dist-Key"),
            cfg.EMAIL_DOMAIN_MAP.copy(),
            cfg.EMAIL_DOMAIN_RULES.copy(),
            answerParameters=ringParams,
            whitelist=cfg.EMAIL_WHITELIST.copy())
        hashring.addRing(emailDistributor.hashring, "email", cfg.EMAIL_SHARE)

    # As appropriate, tell the hashring to leave some bridges unallocated.
    if cfg.RESERVED_SHARE:
        hashring.addRing(Bridges.UnallocatedHolder(), "unallocated",
                         cfg.RESERVED_SHARE)

    # Add pseudo distributors to hashring
    for pseudoRing in cfg.FILE_BUCKETS.keys():
        hashring.addPseudoRing(pseudoRing)

    return hashring, emailDistributor, ipDistributor
示例#6
0
文件: Main.py 项目: katmagic/BridgeDB
def load(cfg, splitter, clear=False):
    """Read all the bridge files from cfg, and pass them into a splitter
       object.
    """
    if clear:
        logging.info("Clearing old bridges")
        splitter.clear()
    logging.info("Loading bridges")
    status = {}
    if hasattr(cfg, "STATUS_FILE"):
        f = open(cfg.STATUS_FILE, 'r')
        for ID, running, stable in Bridges.parseStatusFile(f):
            status[ID] = running, stable
    for fname in cfg.BRIDGE_FILES:
        f = open(fname, 'r')
        for bridge in Bridges.parseDescFile(f, cfg.BRIDGE_PURPOSE):
            s = status.get(bridge.getID())
            if s is not None:
                running, stable = s
                bridge.setStatus(running=running, stable=stable)
            splitter.insert(bridge)
        f.close()
示例#7
0
文件: Main.py 项目: sysrqb/bridgedb
def loadProxyList(cfg):
    ipset = {}
    for fname in cfg.PROXY_LIST_FILES:
        f = open(fname, "r")
        for line in f:
            line = line.strip()
            if line.startswith("#"):
                continue
            elif Bridges.is_valid_ip(line):
                ipset[line] = True
            elif line:
                logging.info("Skipping line %r in %s: not an IP.", line, fname)
        f.close()
    return ipset
示例#8
0
def loadProxyList(cfg):
    ipset = {}
    for fname in cfg.PROXY_LIST_FILES:
        f = open(fname, 'r')
        for line in f:
            line = line.strip()
            if line.startswith("#"):
                continue
            elif Bridges.is_valid_ip(line):
                ipset[line] = True
            elif line:
                logging.info("Skipping line %r in %s: not an IP.", line, fname)
        f.close()
    return ipset
示例#9
0
    def test_getDescriptorDigests(self):
        sha1hash = hashlib.sha1()
        ei_digest = 'abcdefghijklmno'

        test = "this is a test line\nFollowed by another\n"
        test += "extra-info-digest %s\n" % ei_digest
        sha1hash.update(test)
        digest = sha1hash.hexdigest()
        test += "-----BEGIN SIGNATURE-----\n"
        test += "This is a test line that should be skipped\n"
        test += "-----END SIGNATURE-----\n"
        digests = Bridges.getDescriptorDigests(StringIO(test))
        self.failUnlessIn(digest, digests)
        self.failUnlessEqual(ei_digest, digests[digest])
示例#10
0
    def test_getExtraInfoDigests(self):
        sha1hash = hashlib.sha1()

        test = "Many words and line all together\n"
        test += "extra info is nothing like weather\n"
        test += "it's certain to come, like the key in a hum\n"
        test += "but sometimes without a transport and rum\n"
        content = test
        sha1hash.update(test)
        digest = sha1hash.hexdigest()
        test += "-----BEGIN SIGNATURE-----\n"
        test += "But the rum can't save the world like you\n"
        test += "-----END SIGNATURE-----\n"
        digests = Bridges.getExtraInfoDigests(StringIO(test))
        self.failUnlessIn(digest, digests)
        self.failUnlessEqual(content, digests[digest].read())
示例#11
0
文件: Main.py 项目: aagbsn/bridgedb
def startup(cfg):
    """Parse bridges,
    """
    # Expand any ~ characters in paths in the configuration.
    cfg.BRIDGE_FILES = [ os.path.expanduser(fn) for fn in cfg.BRIDGE_FILES ]
    for key in ("RUN_IN_DIR", "DB_FILE", "DB_LOG_FILE", "MASTER_KEY_FILE",
                "ASSIGNMENTS_FILE", "HTTPS_CERT_FILE", "HTTPS_KEY_FILE",
                "PIDFILE", "LOGFILE", "STATUS_FILE"):

        v = getattr(cfg, key, None)
        if v:
            setattr(cfg, key, os.path.expanduser(v))
    if hasattr(cfg, "PROXY_LIST_FILES"):
        cfg.PROXY_LIST_FILES = [
            os.path.expanduser(v) for v in cfg.PROXY_LIST_FILES ]
    else:
        cfg.PROXY_LIST_FILES = [ ]

    # Write the pidfile.
    if cfg.PIDFILE:
        f = open(cfg.PIDFILE, 'w')
        f.write("%s\n"%os.getpid())
        f.close()

    # Set up logging.
    configureLogging(cfg)

    #XXX import Server after logging is set up
    # Otherwise, python will create a default handler that logs to
    # the console and ignore further basicConfig calls
    import bridgedb.Server as Server

    # Load the master key, or create a new one.
    key = getKey(cfg.MASTER_KEY_FILE)

    # Initialize our DB file.
    db = bridgedb.Storage.Database(cfg.DB_FILE+".sqlite",
                                   cfg.DB_FILE)
    bridgedb.Storage.setGlobalDB(db)

    # Get a proxy list.
    proxyList = ProxyCategory()
    proxyList.replaceProxyList(loadProxyList(cfg))

    # Create a BridgeSplitter to assign the bridges to the different
    # distributors.
    splitter = Bridges.BridgeSplitter(Bridges.get_hmac(key, "Splitter-Key"))

    # Create ring parameters.
    forcePorts = getattr(cfg, "FORCE_PORTS")
    forceFlags = getattr(cfg, "FORCE_FLAGS")
    if not forcePorts: forcePorts = []
    if not forceFlags: forceFlags = []
    ringParams=Bridges.BridgeRingParameters(needPorts=forcePorts,
                                            needFlags=forceFlags)

    emailDistributor = ipDistributor = None
    # As appropriate, create an IP-based distributor.
    if cfg.HTTPS_DIST and cfg.HTTPS_SHARE:
        categories = []
        if proxyList.ipset:
            categories.append(proxyList)
        ipDistributor = Dist.IPBasedDistributor(
            Dist.uniformMap,
            cfg.N_IP_CLUSTERS,
            Bridges.get_hmac(key, "HTTPS-IP-Dist-Key"),
            categories,
            answerParameters=ringParams)
        splitter.addRing(ipDistributor, "https", cfg.HTTPS_SHARE)
        #webSchedule = Time.IntervalSchedule("day", 2)
        webSchedule = Time.NoSchedule()

    # As appropriate, create an email-based distributor.
    if cfg.EMAIL_DIST and cfg.EMAIL_SHARE:
        for d in cfg.EMAIL_DOMAINS:
            cfg.EMAIL_DOMAIN_MAP[d] = d
        emailDistributor = Dist.EmailBasedDistributor(
            Bridges.get_hmac(key, "Email-Dist-Key"),
            cfg.EMAIL_DOMAIN_MAP.copy(),
            cfg.EMAIL_DOMAIN_RULES.copy(),
            answerParameters=ringParams)
        splitter.addRing(emailDistributor, "email", cfg.EMAIL_SHARE)
        #emailSchedule = Time.IntervalSchedule("day", 1)
        emailSchedule = Time.NoSchedule()

    # As appropriate, tell the splitter to leave some bridges unallocated.
    if cfg.RESERVED_SHARE:
        splitter.addRing(Bridges.UnallocatedHolder(),
                         "unallocated",
                         cfg.RESERVED_SHARE)

    # Add pseudo distributors to splitter
    for p in cfg.FILE_BUCKETS.keys():
        splitter.addPseudoRing(p)

    # Make the parse-bridges function get re-called on SIGHUP.
    def reload():
        logging.info("Caught SIGHUP")
        load(cfg, splitter, clear=True)
        proxyList.replaceProxyList(loadProxyList(cfg))
        logging.info("%d bridges loaded", len(splitter))
        if emailDistributor:
            logging.info("%d for email", len(emailDistributor.ring))
        if ipDistributor:
            logging.info("%d for web:", len(ipDistributor.splitter))
            logging.info("  by location set: %s",
                         " ".join(str(len(r)) for r in ipDistributor.rings))
            logging.info("  by category set: %s",
                         " ".join(str(len(r)) for r in ipDistributor.categoryRings))
            logging.info("Here are all known bridges in the category section:")
            for r in ipDistributor.categoryRings:
                for name, b in r.bridges.items():
                    logging.info("%s" % b.getConfigLine(True))

        # Dump bridge pool assignments to disk.
        try:
            f = open(cfg.ASSIGNMENTS_FILE, 'a')
            f.write("bridge-pool-assignment %s\n" %
                    time.strftime("%Y-%m-%d %H:%M:%S"))
            splitter.dumpAssignments(f)
            f.close()
        except IOError:
            logging.info("I/O error while writing assignments")

    global _reloadFn
    _reloadFn = reload
    signal.signal(signal.SIGHUP, _handleSIGHUP)

    # And actually load it to start.
    reload()

    # Configure HTTP and/or HTTPS servers.
    if cfg.HTTPS_DIST and cfg.HTTPS_SHARE:
        Server.addWebServer(cfg, ipDistributor, webSchedule)

    # Configure Email servers.
    if cfg.EMAIL_DIST and cfg.EMAIL_SHARE:
        Server.addSMTPServer(cfg, emailDistributor, emailSchedule)

    # Actually run the servers.
    try:
        logging.info("Starting reactors.")
        Server.runServers()
    finally:
        db.close()
        if cfg.PIDFILE:
            os.unlink(cfg.PIDFILE)
示例#12
0
文件: Main.py 项目: sysrqb/bridgedb
def load(cfg, splitter, clear=False):
    """Read all the bridge files from cfg, and pass them into a splitter
       object.
    """
    if clear:
        logging.info("Clearing old bridges")
        splitter.clear()
    logging.info("Loading bridges")
    status = {}
    addresses = {}
    timestamps = {}
    if hasattr(cfg, "STATUS_FILE"):
        logging.info("Opening Network Status document %s", os.path.abspath(cfg.STATUS_FILE))
        f = open(cfg.STATUS_FILE, "r")
        for ID, running, stable, or_addresses, timestamp in Bridges.parseStatusFile(f):
            status[ID] = running, stable
            addresses[ID] = or_addresses
            if ID in timestamps.keys():
                timestamps[ID].append(timestamp)
            else:
                timestamps[ID] = [timestamp]
            # transports[ID] = transports
        logging.debug("Closing status document")
        f.close()
    bridges = {}
    db = bridgedb.Storage.getDB()
    for fname in cfg.BRIDGE_FILES:
        logging.info("Opening cached Descriptor document %s", fname)
        logging.debug("Parsing document for purpose=%s", cfg.BRIDGE_PURPOSE)
        f = open(fname, "r")
        for bridge in Bridges.parseDescFile(f, cfg.BRIDGE_PURPOSE):
            if bridge.getID() in bridges:
                logging.warn("Parsed bridge that we've already added. Skipping.")
                logging.debug("  Bridge: %s" % bridge.getID())
                continue
            else:
                bridges[bridge.getID()] = bridge
                s = status.get(bridge.getID())
                if s is not None:
                    running, stable = s
                    bridge.setStatus(running=running, stable=stable)
                bridge.or_addresses = addresses.get(bridge.getID())
                splitter.insert(bridge)
                # add or update BridgeHistory entries into the database
                # XXX: what do we do with all these or_addresses?
                # The bridge stability metrics are only concerned with a single ip:port
                # So for now, we will only consider the bridges primary IP:port
                if bridge.getID() in timestamps.keys():
                    ts = timestamps[bridge.getID()][:]
                    ts.sort()
                    for timestamp in ts:
                        bridgedb.Stability.addOrUpdateBridgeHistory(bridge, timestamp)
        logging.debug("Closing descriptor document")
        f.close()
    # read pluggable transports from extra-info document
    # XXX: should read from networkstatus after bridge-authority
    # does a reachability test
    if hasattr(cfg, "EXTRA_INFO_FILE"):
        logging.info("Opening Extra Info document %s", os.path.abspath(cfg.EXTRA_INFO_FILE))
        f = open(cfg.EXTRA_INFO_FILE, "r")
        for transport in Bridges.parseExtraInfoFile(f):
            ID, method_name, address, port, argdict = transport
            if bridges[ID].running:
                logging.debug("  Appending transport to running bridge")
                bridges[ID].transports.append(
                    Bridges.PluggableTransport(bridges[ID], method_name, address, port, argdict)
                )
                assert bridges[ID].transports, "We added a transport but it disappeared!"
        logging.debug("Closing extra-info document")
        f.close()
    if hasattr(cfg, "COUNTRY_BLOCK_FILE"):
        logging.info("Opening Blocking Countries file %s", os.path.abspath(cfg.COUNTRY_BLOCK_FILE))
        f = open(cfg.COUNTRY_BLOCK_FILE, "r")
        for ID, address, portlist, countries in Bridges.parseCountryBlockFile(f):
            if ID in bridges.keys() and bridges[ID].running:
                for port in portlist:
                    logging.debug(":.( Tears! %s blocked %s %s:%s", countries, bridges[ID].fingerprint, address, port)
                    try:
                        bridges[ID].blockingCountries["%s:%s" % (address, port)].update(countries)
                    except KeyError:
                        bridges[ID].blockingCountries["%s:%s" % (address, port)] = set(countries)
        logging.debug("Closing blocking-countries document")
        f.close()

    bridges = None
示例#13
0
 def setUp(self):
     self.ring = Bridges.BridgeRing('fake-hmac-key')
示例#14
0
def startup(cfg):
    """Parse bridges,
    """
    # Expand any ~ characters in paths in the configuration.
    cfg.BRIDGE_FILES = [os.path.expanduser(fn) for fn in cfg.BRIDGE_FILES]
    for key in ("RUN_IN_DIR", "DB_FILE", "DB_LOG_FILE", "MASTER_KEY_FILE",
                "ASSIGNMENTS_FILE", "HTTPS_CERT_FILE", "HTTPS_KEY_FILE",
                "PIDFILE", "LOGFILE", "STATUS_FILE"):

        v = getattr(cfg, key, None)
        if v:
            setattr(cfg, key, os.path.expanduser(v))
    if hasattr(cfg, "PROXY_LIST_FILES"):
        cfg.PROXY_LIST_FILES = [
            os.path.expanduser(v) for v in cfg.PROXY_LIST_FILES
        ]
    else:
        cfg.PROXY_LIST_FILES = []

    # Write the pidfile.
    if cfg.PIDFILE:
        f = open(cfg.PIDFILE, 'w')
        f.write("%s\n" % os.getpid())
        f.close()

    # Set up logging.
    configureLogging(cfg)

    #XXX import Server after logging is set up
    # Otherwise, python will create a default handler that logs to
    # the console and ignore further basicConfig calls
    import bridgedb.Server as Server

    # Load the master key, or create a new one.
    key = getKey(cfg.MASTER_KEY_FILE)

    # Initialize our DB file.
    db = bridgedb.Storage.Database(cfg.DB_FILE + ".sqlite", cfg.DB_FILE)
    bridgedb.Storage.setGlobalDB(db)

    # Get a proxy list.
    proxyList = ProxyCategory()
    proxyList.replaceProxyList(loadProxyList(cfg))

    # Create a BridgeSplitter to assign the bridges to the different
    # distributors.
    splitter = Bridges.BridgeSplitter(Bridges.get_hmac(key, "Splitter-Key"))

    # Create ring parameters.
    forcePorts = getattr(cfg, "FORCE_PORTS")
    forceFlags = getattr(cfg, "FORCE_FLAGS")
    if not forcePorts: forcePorts = []
    if not forceFlags: forceFlags = []
    ringParams = Bridges.BridgeRingParameters(needPorts=forcePorts,
                                              needFlags=forceFlags)

    emailDistributor = ipDistributor = None
    # As appropriate, create an IP-based distributor.
    if cfg.HTTPS_DIST and cfg.HTTPS_SHARE:
        categories = []
        if proxyList.ipset:
            categories.append(proxyList)
        ipDistributor = Dist.IPBasedDistributor(Dist.uniformMap,
                                                cfg.N_IP_CLUSTERS,
                                                Bridges.get_hmac(
                                                    key, "HTTPS-IP-Dist-Key"),
                                                categories,
                                                answerParameters=ringParams)
        splitter.addRing(ipDistributor, "https", cfg.HTTPS_SHARE)
        #webSchedule = Time.IntervalSchedule("day", 2)
        webSchedule = Time.NoSchedule()

    # As appropriate, create an email-based distributor.
    if cfg.EMAIL_DIST and cfg.EMAIL_SHARE:
        for d in cfg.EMAIL_DOMAINS:
            cfg.EMAIL_DOMAIN_MAP[d] = d
        emailDistributor = Dist.EmailBasedDistributor(
            Bridges.get_hmac(key, "Email-Dist-Key"),
            cfg.EMAIL_DOMAIN_MAP.copy(),
            cfg.EMAIL_DOMAIN_RULES.copy(),
            answerParameters=ringParams)
        splitter.addRing(emailDistributor, "email", cfg.EMAIL_SHARE)
        #emailSchedule = Time.IntervalSchedule("day", 1)
        emailSchedule = Time.NoSchedule()

    # As appropriate, tell the splitter to leave some bridges unallocated.
    if cfg.RESERVED_SHARE:
        splitter.addRing(Bridges.UnallocatedHolder(), "unallocated",
                         cfg.RESERVED_SHARE)

    # Add pseudo distributors to splitter
    for p in cfg.FILE_BUCKETS.keys():
        splitter.addPseudoRing(p)

    # Make the parse-bridges function get re-called on SIGHUP.
    def reload():
        logging.info("Caught SIGHUP")
        load(cfg, splitter, clear=True)
        proxyList.replaceProxyList(loadProxyList(cfg))
        logging.info("%d bridges loaded", len(splitter))
        if emailDistributor:
            logging.info("%d for email", len(emailDistributor.ring))
        if ipDistributor:
            logging.info("%d for web:", len(ipDistributor.splitter))
            logging.info("  by location set: %s",
                         " ".join(str(len(r)) for r in ipDistributor.rings))
            logging.info(
                "  by category set: %s",
                " ".join(str(len(r)) for r in ipDistributor.categoryRings))
            logging.info("Here are all known bridges in the category section:")
            for r in ipDistributor.categoryRings:
                for name, b in r.bridges.items():
                    logging.info("%s" % b.getConfigLine(True))

        # Dump bridge pool assignments to disk.
        try:
            f = open(cfg.ASSIGNMENTS_FILE, 'a')
            f.write("bridge-pool-assignment %s\n" %
                    time.strftime("%Y-%m-%d %H:%M:%S"))
            splitter.dumpAssignments(f)
            f.close()
        except IOError:
            logging.info("I/O error while writing assignments")

    global _reloadFn
    _reloadFn = reload
    signal.signal(signal.SIGHUP, _handleSIGHUP)

    # And actually load it to start.
    reload()

    # Configure HTTP and/or HTTPS servers.
    if cfg.HTTPS_DIST and cfg.HTTPS_SHARE:
        Server.addWebServer(cfg, ipDistributor, webSchedule)

    # Configure Email servers.
    if cfg.EMAIL_DIST and cfg.EMAIL_SHARE:
        Server.addSMTPServer(cfg, emailDistributor, emailSchedule)

    # Actually run the servers.
    try:
        logging.info("Starting reactors.")
        Server.runServers()
    finally:
        db.close()
        if cfg.PIDFILE:
            os.unlink(cfg.PIDFILE)
示例#15
0
def load(state, splitter, clear=False):
    """Read and parse all descriptors, and load into a bridge splitter.

    Read all the appropriate bridge files from the saved
    :class:`~bridgedb.persistent.State`, parse and validate them, and then
    store them into our ``state.splitter`` instance. The ``state`` will be
    saved again at the end of this function.

    :type splitter: :class:`BridgeSplitter <bridgedb.Bridges.BridgeHolder>`
    :param splitter: A class which provides a mechanism for HMACing
        Bridges in order to assign them to hashrings.
    :param boolean clear: If True, clear all previous bridges from the
        splitter before parsing for new ones.
    """
    if not state:
        logging.fatal("bridgedb.Main.load() could not retrieve state!")
        sys.exit(2)

    if clear:
        logging.info("Clearing old bridges...")
        splitter.clear()

    logging.info("Loading bridges...")

    bridges = {}
    status = {}
    addresses = {}
    timestamps = {}
    bridges = {}
    desc_digests = {}
    ei_digests = {}

    logging.info("Opening network status file: %s" % state.STATUS_FILE)
    f = open(state.STATUS_FILE, 'r')
    for (ID, nickname, desc_digest, running, stable,
         ORaddr, ORport, or_addresses,
         timestamp) in Bridges.parseStatusFile(f):
        bridge = Bridges.Bridge(nickname, ORaddr, ORport, id_digest=ID,
                                or_addresses=or_addresses)
        bridge.assertOK()
        bridge.setStatus(running, stable)
        bridge.setDescriptorDigest(desc_digest)
        bridges[ID] = bridge

        if ID in timestamps.keys():
            timestamps[ID].append(timestamp)
        else:
            timestamps[ID] = [timestamp]
    logging.debug("Closing network status file")
    f.close()

    for fname in state.BRIDGE_FILES:
        logging.info("Opening bridge-server-descriptor file: '%s'" % fname)
        f = open(fname, 'r')
        desc_digests.update(Bridges.getDescriptorDigests(f))
        if state.COLLECT_TIMESTAMPS:
            for bridge in bridges.values():
                if bridge.getID() in timestamps.keys():
                    ts = timestamps[bridge.getID()][:]
                    ts.sort()
                    for timestamp in ts:
                        logging.debug(
                           "Adding/updating timestamps in BridgeHistory for "\
                           "'%s' in database: %s"
                           % (bridge.fingerprint, timestamp))
                        bridgedb.Stability.addOrUpdateBridgeHistory(
                           bridge, timestamp)
        logging.debug("Closing bridge-server-descriptor file: '%s'" % fname)
        f.close()

    for ID in bridges.keys():
        bridge = bridges[ID]
        if bridge.desc_digest in desc_digests:
            bridge.setVerified()
            bridge.setExtraInfoDigest(desc_digests[bridge.desc_digest])
        # We attempt to insert all bridges. If the bridge is not
        # running, then it is skipped during the insertion process.
        splitter.insert(bridge)

    # read pluggable transports from extra-info document
    # XXX: should read from networkstatus after bridge-authority
    # does a reachability test
    for filename in state.EXTRA_INFO_FILES:
        logging.info("Opening extra-info file: '%s'" % filename)
        f = open(filename, 'r')
        for transport in Bridges.parseExtraInfoFile(f):
            ID, method_name, address, port, argdict = transport
            try:
                if bridges[ID].running:
                    logging.info("Adding %s transport to running bridge"
                                 % method_name)
                    bridgePT = Bridges.PluggableTransport(
                        bridges[ID], method_name, address, port, argdict)
                    bridges[ID].transports.append(bridgePT)
                    if not bridgePT in bridges[ID].transports:
                        logging.critical(
                            "Added a transport, but it disappeared!",
                            "\tTransport: %r" % bridgePT)
            except KeyError as error:
                logging.error("Could not find bridge with fingerprint '%s'."
                              % Bridges.toHex(ID))
        logging.debug("Closing extra-info file: '%s'" % filename)
        f.close()

    if state.COUNTRY_BLOCK_FILE:
        logging.info("Opening Blocking Countries file %s"
                     % state.COUNTRY_BLOCK_FILE)
        f = open(state.COUNTRY_BLOCK_FILE)
        # Identity digest, primary OR address, portlist, country codes
        for ID, addr, portlist, cc in Bridges.parseCountryBlockFile(f):
            if ID in bridges.keys() and bridges[ID].running:
                for port in portlist:
                    addrport = "{0}:{1}".format(addr, port)
                    logging.debug(":'( Tears! %s blocked bridge %s at %s"
                                  % (cc, bridges[ID].fingerprint, addrport))
                    try:
                        bridges[ID].blockingCountries[addrport].update(cc)
                    except KeyError:
                        bridges[ID].blockingCountries[addrport] = set(cc)
        logging.debug("Closing blocking-countries document")
        f.close()

    def updateBridgeHistory(bridges, timestamps):
        if not hasattr(state, 'config'):
            logging.info("updateBridgeHistory(): Config file not set "\
                "in State file.")
            return
        if state.COLLECT_TIMESTAMPS:
            logging.debug("Beginning bridge stability calculations")
            for bridge in bridges.values():
                if bridge.getID() in timestamps.keys():
                    ts = timestamps[bridge.getID()][:]
                    ts.sort()
                    for timestamp in ts:
                        logging.debug(
                            "Updating BridgeHistory timestamps for %s: %s"
                            % (bridge.fingerprint, timestamp))
                        bridgedb.Stability.addOrUpdateBridgeHistory(
                            bridge, timestamp)
            logging.debug("Stability calculations complete")

    reactor.callInThread(updateBridgeHistory, bridges, timestamps)

    bridges = None
    state.save()
    return
示例#16
0
def load(cfg, splitter, clear=False):
    """Read all the bridge files from cfg, and pass them into a splitter
       object.
    """
    if clear:
        logging.info("Clearing old bridges")
        splitter.clear()
    logging.info("Loading bridges")
    status = {}
    addresses = {}
    timestamps = {}
    if hasattr(cfg, "STATUS_FILE"):
        logging.info("Opening Network Status document %s",
                     os.path.abspath(cfg.STATUS_FILE))
        f = open(cfg.STATUS_FILE, 'r')
        for ID, running, stable, or_addresses, timestamp in Bridges.parseStatusFile(
                f):
            status[ID] = running, stable
            addresses[ID] = or_addresses
            if ID in timestamps.keys(): timestamps[ID].append(timestamp)
            else: timestamps[ID] = [timestamp]
            #transports[ID] = transports
        logging.debug("Closing status document")
        f.close()
    bridges = {}
    db = bridgedb.Storage.getDB()
    for fname in cfg.BRIDGE_FILES:
        logging.info("Opening cached Descriptor document %s", fname)
        logging.debug("Parsing document for purpose=%s", cfg.BRIDGE_PURPOSE)
        f = open(fname, 'r')
        for bridge in Bridges.parseDescFile(f, cfg.BRIDGE_PURPOSE):
            if bridge.getID() in bridges:
                logging.warn(
                    "Parsed bridge that we've already added. Skipping.")
                logging.debug("  Bridge: %s" % bridge.getID())
                continue
            else:
                bridges[bridge.getID()] = bridge
                s = status.get(bridge.getID())
                if s is not None:
                    running, stable = s
                    bridge.setStatus(running=running, stable=stable)
                bridge.or_addresses = addresses.get(bridge.getID())
                splitter.insert(bridge)
                # add or update BridgeHistory entries into the database
                # XXX: what do we do with all these or_addresses?
                # The bridge stability metrics are only concerned with a single ip:port
                # So for now, we will only consider the bridges primary IP:port
                if bridge.getID() in timestamps.keys():
                    ts = timestamps[bridge.getID()][:]
                    ts.sort()
                    for timestamp in ts:
                        bridgedb.Stability.addOrUpdateBridgeHistory(
                            bridge, timestamp)
        logging.debug("Closing descriptor document")
        f.close()
    # read pluggable transports from extra-info document
    # XXX: should read from networkstatus after bridge-authority
    # does a reachability test
    if hasattr(cfg, "EXTRA_INFO_FILE"):
        logging.info("Opening Extra Info document %s",
                     os.path.abspath(cfg.EXTRA_INFO_FILE))
        f = open(cfg.EXTRA_INFO_FILE, 'r')
        for transport in Bridges.parseExtraInfoFile(f):
            ID, method_name, address, port, argdict = transport
            if bridges[ID].running:
                logging.debug("  Appending transport to running bridge")
                bridges[ID].transports.append(
                    Bridges.PluggableTransport(bridges[ID], method_name,
                                               address, port, argdict))
                assert bridges[
                    ID].transports, "We added a transport but it disappeared!"
        logging.debug("Closing extra-info document")
        f.close()
    if hasattr(cfg, "COUNTRY_BLOCK_FILE"):
        logging.info("Opening Blocking Countries file %s",
                     os.path.abspath(cfg.COUNTRY_BLOCK_FILE))
        f = open(cfg.COUNTRY_BLOCK_FILE, 'r')
        for ID, address, portlist, countries in Bridges.parseCountryBlockFile(
                f):
            if ID in bridges.keys() and bridges[ID].running:
                for port in portlist:
                    logging.debug(":.( Tears! %s blocked %s %s:%s", countries,
                                  bridges[ID].fingerprint, address, port)
                    try:
                        bridges[ID].blockingCountries["%s:%s" % \
                                (address, port)].update(countries)
                    except KeyError:
                        bridges[ID].blockingCountries["%s:%s" % \
                                (address, port)] = set(countries)
        logging.debug("Closing blocking-countries document")
        f.close()

    bridges = None