Пример #1
0
    def from_file(cls, file_path, password=None, encoding='utf-8'):
        """
		Load the signing key from the specified file. If *password* is
		specified, the file is assumed to have been encrypted using OpenSSL
		with ``aes-256-cbc`` as the cipher and ``sha256`` as the message
		digest. This uses :py:func:`.openssl_decrypt_data` internally for
		decrypting the data.

		:param str file_path: The path to the file to load.
		:param str password: An optional password to use for decrypting the file.
		:param str encoding: The encoding of the data.
		:return: A tuple of the key's ID, and the new :py:class:`.SigningKey` instance.
		:rtype: tuple
		"""
        with open(file_path, 'rb') as file_h:
            file_data = file_h.read()
        if password:
            file_data = openssl_decrypt_data(file_data,
                                             password,
                                             encoding=encoding)

        file_data = file_data.decode(encoding)
        file_data = serializers.JSON.loads(file_data)
        utilities.validate_json_schema(file_data, 'king-phisher.security.key')
        return cls.from_dict(file_data['signing-key'],
                             encoding=file_data.pop('encoding', 'base64'),
                             id=file_data['id'])
Пример #2
0
 def _load_key_store(self, file_name):
     file_path = find.data_file(file_name)
     if not file_path:
         return 0
     with open(file_path, 'r') as file_h:
         key_store = serializers.JSON.load(file_h)
     utilities.validate_json_schema(key_store, 'king-phisher.security')
     key_store = key_store['keys']
     loaded = 0
     for key_idx, key in enumerate(key_store, 1):
         identifier = key['id']
         if identifier in self.keys:
             self.logger.warning(
                 "skipping loading {0}:{1} due to a duplicate id".format(
                     file_name, key_idx))
             continue
         verifying_key = key['verifying-key']
         key['verifying-key'] = VerifyingKey.from_dict(
             verifying_key,
             encoding=verifying_key.pop('encoding', 'base64'))
         self.keys[identifier] = key
         self.logger.debug("loaded key id: {0} from: {1}".format(
             identifier, file_path))
         loaded += 1
     return loaded
Пример #3
0
    def __init__(self, data, keys=None):
        """
		:param dict data: The formatted catalog data.
		:param keys: The keys to use for verifying remote data.
		:type keys: :py:class:`~king_phisher.security_keys.SecurityKeys`
		"""
        utilities.validate_json_schema(data, 'king-phisher.catalog')

        self.security_keys = keys or security_keys.SecurityKeys()
        """The :py:class:`~king_phisher.security_keys.SecurityKeys` used for verifying remote data."""
        self.created = dateutil.parser.parse(data['created'])
        """The timestamp of when the remote data was generated."""
        self.maintainers = tuple(maintainer['id']
                                 for maintainer in data['maintainers'])
        """
		A tuple containing the maintainers of the catalog and repositories.
		These are also the key identities that should be present for verifying
		the remote data.
		"""
        self.repositories = tuple(
            Repository(repo, keys=self.security_keys)
            for repo in data['repositories'])
        """A tuple of the :py:class:`.Repository` objects included in this catalog."""
        self.logger.info("initialized catalog with {0:,} repositories".format(
            len(self.repositories)))
Пример #4
0
	def test_schema(self):
		file_path = find.data_file('security.json')
		self.assertIsNotNone(file_path, msg='failed to find the security.json file')
		with open(file_path, 'r') as file_h:
			key_store = serializers.JSON.load(file_h)
		try:
			utilities.validate_json_schema(key_store, 'king-phisher.security')
		except jsonschema.ValidationError:
			self.fail('the security.json file failed validation')
Пример #5
0
    def __init__(self, data, keys=None):
        """
		:param dict data: The formatted repository data.
		:param keys: The keys to use for verifying remote data.
		:type keys: :py:class:`~king_phisher.security_keys.SecurityKeys`
		"""
        self.security_keys = keys or security_keys.SecurityKeys()
        """The :py:class:`~king_phisher.security_keys.SecurityKeys` used for verifying remote data."""

        self._req_sess = requests.Session()
        self._req_sess.mount('file://', requests_file.FileAdapter())
        self.description = data.get('description')
        self.homepage = data.get('homepage')
        """The URL of the homepage for this repository if it was specified."""
        self.id = data['id']
        """The unique identifier of this repository."""
        self.title = data['title']
        """The title string of this repository."""
        self.url_base = data['url-base']
        """The base URL string of files included in this repository."""
        self.collections = utilities.FreezableDict()
        """The dictionary of the different collection types included in this repository."""
        if 'collections-include' in data:
            # include-files is reversed so the dictionary can get .update()'ed and the first seen will be the value kept
            for include in reversed(data['collections-include']):
                include_data = self._fetch_json(include)
                utilities.validate_json_schema(
                    include_data, 'king-phisher.catalog.collections')
                include_data = include_data['collections']
                for collection_type in include.get('types', COLLECTION_TYPES):
                    collection = include_data.get(collection_type)
                    if collection is None:
                        continue
                    self._add_collection_data(collection_type, collection)
        if 'collections' in data:
            for collection_type in COLLECTION_TYPES:
                collection = data['collections'].get(collection_type)
                if collection is None:
                    continue
                self._add_collection_data(collection_type, collection)
        item_count = sum(
            len(collection) for collection in self.collections.values())
        self.logger.debug(
            "initialized catalog repository with {0} collection types and {1} total items"
            .format(len(self.collections), item_count))
        for collection_type, collection in self.collections.items():
            collection.freeze()
            self.collections[collection_type] = Collection(
                self, collection_type, collection)
        self.collections.freeze()
Пример #6
0
def _load_metadata(path):
	file_path, serializer = _find_metadata(path)
	if file_path is None:
		logger.info('found no metadata file for path: ' + path)
		return
	with open(file_path, 'r') as file_h:
		metadata = serializer.load(file_h)
	# manually set the version to a string so the input format is more forgiving
	if isinstance(metadata.get('version'), (float, int)):
		metadata['version'] = str(metadata['version'])
	try:
		utilities.validate_json_schema(metadata, 'king-phisher.template.site.metadata')
	except jsonschema.exceptions.ValidationError:
		logger.error("template metadata file: {0} failed to pass schema validation".format(file_path), exc_info=True)
		return None
	return metadata
Пример #7
0
def _load_metadata(path):
	file_path, loader = _find_metadata(path)
	if file_path is None:
		logger.info('found no metadata file for path: ' + path)
		return
	with open(file_path, 'r') as file_h:
		metadata = loader(file_h)
	# manually set the version to a string so the input format is more forgiving
	if isinstance(metadata.get('version'), (float, int)):
		metadata['version'] = str(metadata['version'])
	try:
		utilities.validate_json_schema(metadata, 'king-phisher.template.site.metadata')
	except jsonschema.exceptions.ValidationError:
		logger.error("template metadata file: {0} failed to pass schema validation".format(file_path), exc_info=True)
		return None
	metadata['pages'] = [utilities.make_webrelpath(path) for path in metadata['pages']]
	return metadata
Пример #8
0
	def __init__(self, data, keys=None):
		"""
		:param dict data: The formatted repository data.
		:param keys: The keys to use for verifying remote data.
		:type keys: :py:class:`~king_phisher.security_keys.SecurityKeys`
		"""
		self.security_keys = keys or security_keys.SecurityKeys()
		"""The :py:class:`~king_phisher.security_keys.SecurityKeys` used for verifying remote data."""

		self._req_sess = requests.Session()
		self._req_sess.mount('file://', requests_file.FileAdapter())
		self.description = data.get('description')
		self.homepage = data.get('homepage')
		"""The URL of the homepage for this repository if it was specified."""
		self.id = data['id']
		"""The unique identifier of this repository."""
		self.title = data['title']
		"""The title string of this repository."""
		self.url_base = data['url-base']
		"""The base URL string of files included in this repository."""
		self.collections = utilities.FreezableDict()
		"""The dictionary of the different collection types included in this repository."""
		if 'collections-include' in data:
			# include-files is reversed so the dictionary can get .update()'ed and the first seen will be the value kept
			for include in reversed(data['collections-include']):
				include_data = self._fetch_json(include)
				utilities.validate_json_schema(include_data, 'king-phisher.catalog.collections')
				include_data = include_data['collections']
				for collection_type in include.get('types', COLLECTION_TYPES):
					collection = include_data.get(collection_type)
					if collection is None:
						continue
					self._add_collection_data(collection_type, collection)
		if 'collections' in data:
			for collection_type in COLLECTION_TYPES:
				collection = data['collections'].get(collection_type)
				if collection is None:
					continue
				self._add_collection_data(collection_type, collection)
		item_count = sum(len(collection) for collection in self.collections.values())
		self.logger.debug("initialized catalog repository with {0} collection types and {1} total items".format(len(self.collections), item_count))
		for collection_type, collection in self.collections.items():
			collection.freeze()
			self.collections[collection_type] = Collection(self, collection_type, collection)
		self.collections.freeze()
Пример #9
0
	def _load_key_store(self, file_name):
		file_path = find.data_file(file_name)
		if not file_path:
			return 0
		with open(file_path, 'r') as file_h:
			key_store = serializers.JSON.load(file_h)
		utilities.validate_json_schema(key_store, 'king-phisher.security')
		key_store = key_store['keys']
		loaded = 0
		for key_idx, key in enumerate(key_store, 1):
			identifier = key['id']
			if identifier in self.keys:
				self.logger.warning("skipping loading {0}:{1} due to a duplicate id".format(file_name, key_idx))
				continue
			verifying_key = key['verifying-key']
			key['verifying-key'] = VerifyingKey.from_dict(verifying_key, encoding=verifying_key.pop('encoding', 'base64'))
			self.keys[identifier] = key
			self.logger.debug("loaded key id: {0} from: {1}".format(identifier, file_path))
			loaded += 1
		return loaded
Пример #10
0
	def __init__(self, data, keys=None):
		"""
		:param dict data: The formatted catalog data.
		:param keys: The keys to use for verifying remote data.
		:type keys: :py:class:`~king_phisher.security_keys.SecurityKeys`
		"""
		utilities.validate_json_schema(data, 'king-phisher.catalog')

		self.security_keys = keys or security_keys.SecurityKeys()
		"""The :py:class:`~king_phisher.security_keys.SecurityKeys` used for verifying remote data."""
		self.created = dateutil.parser.parse(data['created'])
		"""The timestamp of when the remote data was generated."""
		self.maintainers = tuple(maintainer['id'] for maintainer in data['maintainers'])
		"""
		A tuple containing the maintainers of the catalog and repositories.
		These are also the key identities that should be present for verifying
		the remote data.
		"""
		self.repositories = tuple(Repository(repo, keys=self.security_keys) for repo in data['repositories'])
		"""A tuple of the :py:class:`.Repository` objects included in this catalog."""
		self.logger.info("initialized catalog with {0:,} repositories".format(len(self.repositories)))
Пример #11
0
	def from_file(cls, file_path, password=None, encoding='utf-8'):
		"""
		Load the signing key from the specified file. If *password* is
		specified, the file is assumed to have been encrypted using OpenSSL
		with ``aes-256-cbc`` as the cipher and ``sha256`` as the message
		digest. This uses :py:func:`.openssl_decrypt_data` internally for
		decrypting the data.

		:param str file_path: The path to the file to load.
		:param str password: An optional password to use for decrypting the file.
		:param str encoding: The encoding of the data.
		:return: A tuple of the key's ID, and the new :py:class:`.SigningKey` instance.
		:rtype: tuple
		"""
		with open(file_path, 'rb') as file_h:
			file_data = file_h.read()
		if password:
			file_data = openssl_decrypt_data(file_data, password, encoding=encoding)

		file_data = file_data.decode(encoding)
		file_data = serializers.JSON.loads(file_data)
		utilities.validate_json_schema(file_data, 'king-phisher.security.key')
		return cls.from_dict(file_data['signing-key'], encoding=file_data.pop('encoding', 'base64'), id=file_data['id'])
Пример #12
0
	def from_url(cls, url, keys=None, encoding='utf-8'):
		"""
		Initialize a new :py:class:`.Catalog` object from a resource at the
		specified URL. The resulting data is validated against a schema file
		with :py:func:`~king_phisher.utilities.validate_json_schema` before
		being passed to :py:meth:`~.__init__`.

		:param str url: The URL to the catalog data to load.
		:param keys: The keys to use for verifying remote data.
		:type keys: :py:class:`~king_phisher.security_keys.SecurityKeys`
		:param str encoding: The encoding of the catalog data.
		:return: The new catalog instance.
		:rtype: :py:class:`.Catalog`
		"""
		keys = keys or security_keys.SecurityKeys()
		req_sess = requests.Session()
		req_sess.mount('file://', requests_file.FileAdapter())
		cls.logger.debug('fetching catalog from: ' + url)
		resp = req_sess.get(url)
		data = resp.content.decode(encoding)
		data = serializers.JSON.loads(data)
		utilities.validate_json_schema(data, 'king-phisher.catalog')
		keys.verify_dict(data, signature_encoding='base64')
		return cls(data, keys=keys)
Пример #13
0
    def from_url(cls, url, keys=None, encoding='utf-8'):
        """
		Initialize a new :py:class:`.Catalog` object from a resource at the
		specified URL. The resulting data is validated against a schema file
		with :py:func:`~king_phisher.utilities.validate_json_schema` before
		being passed to :py:meth:`~.__init__`.

		:param str url: The URL to the catalog data to load.
		:param keys: The keys to use for verifying remote data.
		:type keys: :py:class:`~king_phisher.security_keys.SecurityKeys`
		:param str encoding: The encoding of the catalog data.
		:return: The new catalog instance.
		:rtype: :py:class:`.Catalog`
		"""
        keys = keys or security_keys.SecurityKeys()
        req_sess = requests.Session()
        req_sess.mount('file://', requests_file.FileAdapter())
        cls.logger.debug('fetching catalog from: ' + url)
        resp = req_sess.get(url)
        data = resp.content.decode(encoding)
        data = serializers.JSON.loads(data)
        utilities.validate_json_schema(data, 'king-phisher.catalog')
        keys.verify_dict(data, signature_encoding='base64')
        return cls(data, keys=keys)