def __init__(self, cache=None, notaries_file=None, quorum_percentage=75, quorum_duration=86400, stale_limit=86400): """Check a Perspectives Checker instance quorum_percentage is percentage of notaries needed for quorum quorum_duration is seconds of quorum needed stale_limit: any response without a seen key fresher than this limit is ignored inside this limit. I.e. a notary with a stale response does not count towards quorum inside this period. """ self.logger = logging.getLogger("Perspectives.Checker") self.logger.debug("Perspective Checker class initializing") self.cache = cache if cache is not None \ else ServiceCache() # Age at which entry in cache is stale and ignored self.cache_stale_age = 24 * 3600 if notaries_file: self.logger.debug("Reading notaries from %s" % notaries_file) self.notaries = Notaries.from_file(notaries_file) else: self.logger.debug("Using default notaries") self.notaries = Notaries.default() self.quorum = int(len(self.notaries) * quorum_percentage / 100) self.logger.debug( "%d notaries, quorum is %d (%d%%)" % (len(self.notaries), self.quorum, quorum_percentage)) self.quorum_duration = quorum_duration self.stale_limit = stale_limit self.logger.debug("Perspective instance initialized")
def __init__(self, cache=None, notaries_file=None, quorum_percentage=75, quorum_duration=86400, stale_limit=86400): """Check a Perspectives Checker instance quorum_percentage is percentage of notaries needed for quorum quorum_duration is seconds of quorum needed stale_limit: any response without a seen key fresher than this limit is ignored inside this limit. I.e. a notary with a stale response does not count towards quorum inside this period. """ self.logger = logging.getLogger("Perspectives.Checker") self.logger.debug("Perspective Checker class initializing") self.cache = cache if cache is not None \ else ServiceCache() # Age at which entry in cache is stale and ignored self.cache_stale_age = 24 * 3600 if notaries_file: self.logger.debug("Reading notaries from %s" % notaries_file) self.notaries = Notaries.from_file(notaries_file) else: self.logger.debug("Using default notaries") self.notaries = Notaries.default() self.quorum = int(len(self.notaries) * quorum_percentage / 100) self.logger.debug("%d notaries, quorum is %d (%d%%)" % (len(self.notaries), self.quorum, quorum_percentage)) self.quorum_duration = quorum_duration self.stale_limit = stale_limit self.logger.debug("Perspective instance initialized")
def parse_stream(self, stream): """Return Notaries described in stream. Expected format for the stream is a Convergence JSON bundle.""" notaries = Notaries() d = json.load(stream) if d["version"] != 1: raise ValueError("Unrecognized Convergence bundle version: %d" % d["version"]) for host_dict in d["hosts"]: notary = self._parse_notary(host_dict) notaries.append(notary) return notaries
def _load_notaries(self): from Perspectives import Notaries return Notaries.from_file("./http_notary_list.txt")
def main(argv=None): # Do argv default this way, as doing it in the functional # declaration sets it at compile time. if argv is None: argv = sys.argv # Set up out output via logging module output = logging.getLogger("main") output.setLevel(logging.DEBUG) output_handler = logging.StreamHandler(sys.stdout) # Default is sys.stderr # Set up formatter to just print message without preamble output_handler.setFormatter(logging.Formatter("%(message)s")) output.addHandler(output_handler) # Set up logging for Perspectives code as well perspectives_logger = logging.getLogger("Perspectives") perspectives_logger.setLevel(logging.DEBUG) perspectives_logger.addHandler(output_handler) # Argument parsing parser = argparse.ArgumentParser( description=__doc__, formatter_class=argparse.ArgumentDefaultsHelpFormatter # printed with -h/--help ) # Only allow one of debug/quiet mode verbosity_group = parser.add_mutually_exclusive_group() verbosity_group.add_argument( "-d", "--debug", action="store_const", const=logging.DEBUG, dest="output_level", default=logging.INFO, help="print debugging", ) verbosity_group.add_argument( "-q", "--quiet", action="store_const", const=logging.WARNING, dest="output_level", help="run quietly" ) parser.add_argument("--version", action="version", version="%(prog)s 1.0") parser.add_argument( "-n", "--num_notaries", type=int, default=0, help="specify number of notaries to query (0=All)", metavar="num" ) parser.add_argument( "-N", "--notaries-file", type=str, default="./http_notary_list.txt", help="specify notaries file", metavar="filename", ) parser.add_argument( "-p", "--port", dest="service_port", type=int, default=443, help="specify service port", metavar="port" ) parser.add_argument( "-t", "--type", dest="service_type", type=int, default=ServiceType.SSL, help="specify service type", metavar="type", ) parser.add_argument( "-x", "--xml", dest="output_xml", action="store_const", const=True, default=False, help="output raw XML" ) parser.add_argument("service_hostname", metavar="hostname", type=str, nargs=1, help="host about which to query") parser.add_argument( "service_fingerprint", metavar="fingerprint", type=str, nargs="?", default=None, help="test fingerprint against responses", ) args = parser.parse_args() output_handler.setLevel(args.output_level) service = Service(args.service_hostname[0], args.service_port, args.service_type) if args.service_fingerprint is not None: output.debug("Checking provided fingerprint against responses...") checker = Checker(notaries_file=args.notaries_file) fp = Fingerprint.from_string(args.service_fingerprint) checker.check_seen_fingerprint(service, fp) output.debug("Check successful.") responses = checker.responses else: notaries = Notaries.from_file(args.notaries_file) output.debug("Read configuration for %s notaries from configuration %s" % (len(notaries), args.notaries_file)) responses = notaries.query(service, num=args.num_notaries) if responses and len(responses): for response in responses: if args.output_xml: output.info(response.xml) else: output.info(response) else: output.info("Failed to obtain any responses") return 0
def _load_notaries(self): """Load notaries and return Notaries instance""" from Perspectives import Notaries return Notaries.from_file("./http_notary_list.txt")