def setUp(self): find.data_path_append('data/server') web_root = os.path.join(os.getcwd(), 'data', 'server', 'king_phisher') config = smoke_zephyr.configuration.Configuration( find.find_data_file('server_config.yml')) config.set('server.address.host', '127.0.0.1') config.set('server.address.port', 0) config.set('server.addresses', []) config.set('server.database', 'sqlite://') config.set( 'server.geoip.database', os.environ.get('KING_PHISHER_TEST_GEOIP_DB', './GeoLite2-City.mmdb')) config.set('server.web_root', web_root) config.set('server.rest_api.enabled', True) config.set('server.rest_api.token', rest_api.generate_token()) self.config = config self.plugin_manager = plugins.ServerPluginManager(config) self.server = build.server_from_config( config, handler_klass=KingPhisherRequestHandlerTest, plugin_manager=self.plugin_manager) config.set('server.address.port', self.server.sub_servers[0].server_port) self.assertIsInstance(self.server, server.KingPhisherServer) self.server_thread = threading.Thread(target=self.server.serve_forever) self.server_thread.daemon = True self.server_thread.start() self.assertTrue(self.server_thread.is_alive()) self.shutdown_requested = False self.rpc = client_rpc.KingPhisherRPCClient( ('localhost', self.config.get('server.address.port'))) self.rpc.login(username='******', password='******')
def build_king_phisher_server(config, ServerClass=None, HandlerClass=None): """ Build a server from a provided configuration instance. If *ServerClass* or *HandlerClass* is specified, then the object must inherit from the corresponding KingPhisherServer base class. :param config: Configuration to retrieve settings from. :type config: :py:class:`smoke_zephyr.configuration.Configuration` :param ServerClass: Alternative server class to use. :type ServerClass: :py:class:`.KingPhisherServer` :param HandlerClass: Alternative handler class to use. :type HandlerClass: :py:class:`.KingPhisherRequestHandler` :return: A configured server instance. :rtype: :py:class:`.KingPhisherServer` """ logger = logging.getLogger('KingPhisher.Server.build') ServerClass = (ServerClass or KingPhisherServer) HandlerClass = (HandlerClass or KingPhisherRequestHandler) # set config defaults if not config.has_option('server.secret_id'): config.set('server.secret_id', make_uid()) address = (config.get('server.address.host'), config.get('server.address.port')) ssl_certfile = None ssl_keyfile = None if config.has_option('server.ssl_cert'): ssl_certfile = config.get('server.ssl_cert') ssl_keyfile = config.get_if_exists('server.ssl_key') try: server = ServerClass(config, HandlerClass, address=address, ssl_certfile=ssl_certfile, ssl_keyfile=ssl_keyfile) except socket.error as error: error_number, error_message = error.args if error_number == 98: logger.critical( "failed to bind server to address {0}:{1} (socket error #98)". format(*address)) raise errors.KingPhisherError("socket error #{0} ({1})".format( (error_number or 'NOT-SET'), error_message)) if config.has_option('server.server_header'): server.server_version = config.get('server.server_header') if not config.get_if_exists('server.rest_api.token'): config.set('server.rest_api.token', rest_api.generate_token()) if config.get('server.rest_api.enabled'): logger.info('rest api initialized with token: ' + config.get('server.rest_api.token')) return server
def build_king_phisher_server(config, ServerClass=None, HandlerClass=None): """ Build a server from a provided configuration instance. If *ServerClass* or *HandlerClass* is specified, then the object must inherit from the corresponding KingPhisherServer base class. :param config: Configuration to retrieve settings from. :type config: :py:class:`smoke_zephyr.configuration.Configuration` :param ServerClass: Alternative server class to use. :type ServerClass: :py:class:`.KingPhisherServer` :param HandlerClass: Alternative handler class to use. :type HandlerClass: :py:class:`.KingPhisherRequestHandler` :return: A configured server instance. :rtype: :py:class:`.KingPhisherServer` """ logger = logging.getLogger("KingPhisher.Server.build") ServerClass = ServerClass or KingPhisherServer HandlerClass = HandlerClass or KingPhisherRequestHandler # set config defaults if not config.has_option("server.secret_id"): config.set("server.secret_id", make_uid()) address = (config.get("server.address.host"), config.get("server.address.port")) ssl_certfile = None ssl_keyfile = None if config.has_option("server.ssl_cert"): ssl_certfile = config.get("server.ssl_cert") if not os.access(ssl_certfile, os.R_OK): logger.critical("setting server.ssl_cert file '{0}' not found".format(ssl_certfile)) raise errors.KingPhisherError("invalid ssl configuration, missing file") if config.has_option("server.ssl_key"): ssl_keyfile = config.get("server.ssl_key") if not os.access(ssl_keyfile, os.R_OK): logger.critical("setting server.ssl_key file '{0}' not found".format(ssl_keyfile)) raise errors.KingPhisherError("invalid ssl configuration, missing file") try: server = ServerClass(config, HandlerClass, address=address, ssl_certfile=ssl_certfile, ssl_keyfile=ssl_keyfile) except socket.error as error: error_number, error_message = error.args if error_number == 98: logger.critical("failed to bind server to address {0}:{1} (socket error #98)".format(*address)) raise errors.KingPhisherError("socket error #{0} ({1})".format((error_number or "NOT-SET"), error_message)) if config.has_option("server.server_header"): server.server_version = config.get("server.server_header") if not config.get_if_exists("server.rest_api.token"): config.set("server.rest_api.token", rest_api.generate_token()) if config.get("server.rest_api.enabled"): logger.info("rest api initialized with token: " + config.get("server.rest_api.token")) return server
def setUp(self): find.data_path_append('data/server') web_root = os.path.join(os.getcwd(), 'data', 'server', 'king_phisher') config = smoke_zephyr.configuration.Configuration(find.find_data_file('server_config.yml')) config.set('server.address.port', 0) config.set('server.database', 'sqlite://') config.set('server.geoip.database', os.environ.get('KING_PHISHER_TEST_GEOIP_DB', './GeoLite2-City.mmdb')) config.set('server.web_root', web_root) config.set('server.rest_api.enabled', True) config.set('server.rest_api.token', rest_api.generate_token()) self.config = config self.server = build_king_phisher_server(config, HandlerClass=KingPhisherRequestHandlerTest) config.set('server.address.port', self.server.http_server.server_port) self.assertIsInstance(self.server, KingPhisherServer) self.server_thread = threading.Thread(target=self.server.serve_forever) self.server_thread.daemon = True self.server_thread.start() self.assertTrue(self.server_thread.is_alive()) self.shutdown_requested = False self.rpc = client_rpc.KingPhisherRPCClient(('localhost', self.config.get('server.address.port')), username='******', password='******')
def setUp(self): find.data_path_append('data/server') web_root = os.path.join(os.getcwd(), 'data', 'server', 'king_phisher') server_address = {'host': '127.0.0.1', 'port': 0, 'ssl': False} config = configuration.Configuration.from_file(find.data_file('server_config.yml')) config.set('server.addresses', [server_address]) config.set('server.database', 'sqlite://') config.set('server.geoip.database', os.environ.get('KING_PHISHER_TEST_GEOIP_DB', './GeoLite2-City.mmdb')) config.set('server.web_root', web_root) config.set('server.rest_api.enabled', True) config.set('server.rest_api.token', rest_api.generate_token()) self.config = config self.plugin_manager = plugins.ServerPluginManager(config) self.server = build.server_from_config(config, handler_klass=KingPhisherRequestHandlerTest, plugin_manager=self.plugin_manager) server_address['port'] = self.server.sub_servers[0].server_port self.assertIsInstance(self.server, server.KingPhisherServer) self.server_thread = threading.Thread(target=self.server.serve_forever) self.server_thread.daemon = True self.server_thread.start() self.assertTrue(self.server_thread.is_alive()) self.shutdown_requested = False self.rpc = client_rpc.KingPhisherRPCClient(('localhost', server_address['port'])) self.rpc.login(username='******', password='******')
def __init__(self, config, plugin_manager, handler_klass, *args, **kwargs): """ :param config: Configuration to retrieve settings from. :type config: :py:class:`smoke_zephyr.configuration.Configuration` """ # additional mime types to be treated as html because they're probably cloned pages handler_klass.extensions_map.update({ '': 'text/html', '.asp': 'text/html', '.aspx': 'text/html', '.cfm': 'text/html', '.cgi': 'text/html', '.do': 'text/html', '.jsp': 'text/html', '.nsf': 'text/html', '.php': 'text/html', '.srf': 'text/html' }) super(KingPhisherServer, self).__init__(handler_klass, *args, **kwargs) self.logger = logging.getLogger('KingPhisher.Server') self.config = config """A :py:class:`~smoke_zephyr.configuration.Configuration` instance used as the main King Phisher server configuration.""" self.plugin_manager = plugin_manager self.serve_files = True self.serve_files_root = config.get('server.web_root') self.serve_files_list_directories = False self.serve_robots_txt = True self.database_engine = db_manager.init_database( config.get('server.database'), extra_init=True) self.throttle_semaphore = threading.Semaphore() self.session_manager = aaa.AuthenticatedSessionManager( timeout=config.get_if_exists('server.authentication.cache_timeout', '30m')) self.forked_authenticator = aaa.ForkedAuthenticator( cache_timeout=config.get_if_exists( 'server.authentication.cache_timeout', '10m'), required_group=config.get_if_exists('server.authentication.group'), pam_service=config.get_if_exists( 'server.authentication.pam_service', 'sshd')) self.job_manager = job.JobManager() """A :py:class:`~smoke_zephyr.job.JobManager` instance for scheduling tasks.""" self.job_manager.start() loader = jinja2.FileSystemLoader(config.get('server.web_root')) global_vars = {} if config.has_section('server.page_variables'): global_vars = config.get('server.page_variables') global_vars['embed_youtube_video'] = pages.embed_youtube_video global_vars['make_csrf_page'] = pages.make_csrf_page global_vars['make_redirect_page'] = pages.make_redirect_page self.template_env = templates.TemplateEnvironmentBase( loader=loader, global_vars=global_vars) for http_server in self.sub_servers: http_server.config = config http_server.plugin_manager = plugin_manager http_server.throttle_semaphore = self.throttle_semaphore http_server.session_manager = self.session_manager http_server.forked_authenticator = self.forked_authenticator http_server.job_manager = self.job_manager http_server.template_env = self.template_env http_server.kp_shutdown = self.shutdown if not config.has_option('server.secret_id'): config.set('server.secret_id', rest_api.generate_token()) if not config.get_if_exists('server.rest_api.token'): config.set('server.rest_api.token', rest_api.generate_token()) if config.get('server.rest_api.enabled'): self.logger.info('rest api initialized with token: ' + config.get('server.rest_api.token')) self.__geoip_db = geoip.init_database( config.get('server.geoip.database')) self.__is_shutdown = threading.Event() self.__is_shutdown.clear() self.__shutdown_lock = threading.Lock() plugin_manager.server = self
def __init__(self, config, plugin_manager, handler_klass, *args, **kwargs): """ :param config: Configuration to retrieve settings from. :type config: :py:class:`smoke_zephyr.configuration.Configuration` """ # additional mime types to be treated as html because they're probably cloned pages handler_klass.extensions_map.update({ '': 'text/html', '.asp': 'text/html', '.aspx': 'text/html', '.cfm': 'text/html', '.cgi': 'text/html', '.do': 'text/html', '.jsp': 'text/html', '.nsf': 'text/html', '.php': 'text/html', '.srf': 'text/html' }) super(KingPhisherServer, self).__init__(handler_klass, *args, **kwargs) self.logger = logging.getLogger('KingPhisher.Server') self.config = config """A :py:class:`~smoke_zephyr.configuration.Configuration` instance used as the main King Phisher server configuration.""" self.headers = collections.OrderedDict() """A :py:class:`~collections.OrderedDict` containing additional headers specified from the server configuration to include in responses.""" self.plugin_manager = plugin_manager self.serve_files = True self.serve_files_root = config.get('server.web_root') self.serve_files_list_directories = False self.serve_robots_txt = True self.database_engine = db_manager.init_database(config.get('server.database'), extra_init=True) self.throttle_semaphore = threading.BoundedSemaphore() self.session_manager = aaa.AuthenticatedSessionManager( timeout=config.get_if_exists('server.authentication.session_timeout', '30m') ) self.forked_authenticator = aaa.ForkedAuthenticator( cache_timeout=config.get_if_exists('server.authentication.cache_timeout', '10m'), required_group=config.get_if_exists('server.authentication.group'), pam_service=config.get_if_exists('server.authentication.pam_service', 'sshd') ) self.job_manager = smoke_zephyr.job.JobManager(logger_name='KingPhisher.Server.JobManager') """A :py:class:`~smoke_zephyr.job.JobManager` instance for scheduling tasks.""" self.job_manager.start() maintenance_interval = 900 # 15 minutes self._maintenance_job = self.job_manager.job_add(self._maintenance, parameters=(maintenance_interval,), seconds=maintenance_interval) loader = jinja2.FileSystemLoader(config.get('server.web_root')) global_vars = {} if config.has_section('server.page_variables'): global_vars = config.get('server.page_variables') global_vars.update(template_extras.functions) self.template_env = templates.TemplateEnvironmentBase(loader=loader, global_vars=global_vars) self.ws_manager = web_sockets.WebSocketsManager(config, self.job_manager) self.tables_api = {} self._init_tables_api() for http_server in self.sub_servers: http_server.add_sni_cert = self.add_sni_cert http_server.config = config http_server.forked_authenticator = self.forked_authenticator http_server.get_sni_certs = lambda: self.sni_certs http_server.headers = self.headers http_server.job_manager = self.job_manager http_server.kp_shutdown = self.shutdown http_server.plugin_manager = plugin_manager http_server.remove_sni_cert = self.remove_sni_cert http_server.session_manager = self.session_manager http_server.tables_api = self.tables_api http_server.template_env = self.template_env http_server.throttle_semaphore = self.throttle_semaphore http_server.ws_manager = self.ws_manager if not config.has_option('server.secret_id'): test_id = rest_api.generate_token() config.set('server.secret_id', test_id) self.logger.debug('server request test id initialized with value: ' + test_id) if not config.get_if_exists('server.rest_api.token'): config.set('server.rest_api.token', rest_api.generate_token()) if config.get('server.rest_api.enabled'): self.logger.info('rest api token initialized with value: ' + config.get('server.rest_api.token')) self.__geoip_db = geoip.init_database(config.get('server.geoip.database')) self.__is_shutdown = threading.Event() self.__is_shutdown.clear() self.__shutdown_lock = threading.Lock() plugin_manager.server = weakref.proxy(self) headers = self.config.get_if_exists('server.headers', []) for header in headers: if ': ' not in header: self.logger.warning("header '{0}' is invalid and will not be included".format(header)) continue header, value = header.split(': ', 1) header = header.strip() self.headers[header] = value self.logger.info("including {0} custom http headers".format(len(self.headers)))
def __init__(self, config, plugin_manager, handler_klass, *args, **kwargs): """ :param config: Configuration to retrieve settings from. :type config: :py:class:`smoke_zephyr.configuration.Configuration` """ # additional mime types to be treated as html because they're probably cloned pages handler_klass.extensions_map.update({ '': 'text/html', '.asp': 'text/html', '.aspx': 'text/html', '.cfm': 'text/html', '.cgi': 'text/html', '.do': 'text/html', '.jsp': 'text/html', '.nsf': 'text/html', '.php': 'text/html', '.srf': 'text/html' }) super(KingPhisherServer, self).__init__(handler_klass, *args, **kwargs) self.logger = logging.getLogger('KingPhisher.Server') self.config = config """A :py:class:`~smoke_zephyr.configuration.Configuration` instance used as the main King Phisher server configuration.""" self.plugin_manager = plugin_manager self.serve_files = True self.serve_files_root = config.get('server.web_root') self.serve_files_list_directories = False self.serve_robots_txt = True self.database_engine = db_manager.init_database(config.get('server.database'), extra_init=True) self.throttle_semaphore = threading.Semaphore() self.session_manager = aaa.AuthenticatedSessionManager( timeout=config.get_if_exists('server.authentication.cache_timeout', '30m') ) self.forked_authenticator = aaa.ForkedAuthenticator( cache_timeout=config.get_if_exists('server.authentication.cache_timeout', '10m'), required_group=config.get_if_exists('server.authentication.group'), pam_service=config.get_if_exists('server.authentication.pam_service', 'sshd') ) self.job_manager = job.JobManager() """A :py:class:`~smoke_zephyr.job.JobManager` instance for scheduling tasks.""" self.job_manager.start() loader = jinja2.FileSystemLoader(config.get('server.web_root')) global_vars = {} if config.has_section('server.page_variables'): global_vars = config.get('server.page_variables') global_vars['embed_youtube_video'] = pages.embed_youtube_video global_vars['make_csrf_page'] = pages.make_csrf_page global_vars['make_redirect_page'] = pages.make_redirect_page self.template_env = templates.TemplateEnvironmentBase(loader=loader, global_vars=global_vars) for http_server in self.sub_servers: http_server.config = config http_server.plugin_manager = plugin_manager http_server.throttle_semaphore = self.throttle_semaphore http_server.session_manager = self.session_manager http_server.forked_authenticator = self.forked_authenticator http_server.job_manager = self.job_manager http_server.template_env = self.template_env http_server.kp_shutdown = self.shutdown if not config.has_option('server.secret_id'): config.set('server.secret_id', rest_api.generate_token()) if not config.get_if_exists('server.rest_api.token'): config.set('server.rest_api.token', rest_api.generate_token()) if config.get('server.rest_api.enabled'): self.logger.info('rest api initialized with token: ' + config.get('server.rest_api.token')) self.__geoip_db = geoip.init_database(config.get('server.geoip.database')) self.__is_shutdown = threading.Event() self.__is_shutdown.clear() self.__shutdown_lock = threading.Lock() plugin_manager.server = self
def __init__(self, config, plugin_manager, handler_klass, *args, **kwargs): """ :param config: Configuration to retrieve settings from. :type config: :py:class:`smoke_zephyr.configuration.Configuration` """ # additional mime types to be treated as html because they're probably cloned pages handler_klass.extensions_map.update({ '': 'text/html', '.asp': 'text/html', '.aspx': 'text/html', '.cfm': 'text/html', '.cgi': 'text/html', '.do': 'text/html', '.jsp': 'text/html', '.nsf': 'text/html', '.php': 'text/html', '.srf': 'text/html' }) super(KingPhisherServer, self).__init__(handler_klass, *args, **kwargs) self.logger = logging.getLogger('KingPhisher.Server') self.config = config """A :py:class:`~smoke_zephyr.configuration.Configuration` instance used as the main King Phisher server configuration.""" self.headers = collections.OrderedDict() """A :py:class:`~collections.OrderedDict` containing additional headers specified from the server configuration to include in responses.""" self.plugin_manager = plugin_manager self.serve_files = True self.serve_files_root = config.get('server.web_root') self.serve_files_list_directories = False self.serve_robots_txt = True self.database_engine = db_manager.init_database(config.get('server.database'), extra_init=True) self.throttle_semaphore = threading.BoundedSemaphore() self.session_manager = aaa.AuthenticatedSessionManager( timeout=config.get_if_exists('server.authentication.cache_timeout', '30m') ) self.forked_authenticator = aaa.ForkedAuthenticator( cache_timeout=config.get_if_exists('server.authentication.cache_timeout', '10m'), required_group=config.get_if_exists('server.authentication.group'), pam_service=config.get_if_exists('server.authentication.pam_service', 'sshd') ) self.job_manager = smoke_zephyr.job.JobManager(logger_name='KingPhisher.Server.JobManager') """A :py:class:`~smoke_zephyr.job.JobManager` instance for scheduling tasks.""" self.job_manager.start() loader = jinja2.FileSystemLoader(config.get('server.web_root')) global_vars = {} if config.has_section('server.page_variables'): global_vars = config.get('server.page_variables') global_vars.update(pages.EXPORTED_FUNCTIONS) self.template_env = templates.TemplateEnvironmentBase(loader=loader, global_vars=global_vars) self.ws_manager = web_sockets.WebSocketsManager(config, self.job_manager) for http_server in self.sub_servers: http_server.config = config http_server.plugin_manager = plugin_manager http_server.throttle_semaphore = self.throttle_semaphore http_server.session_manager = self.session_manager http_server.forked_authenticator = self.forked_authenticator http_server.job_manager = self.job_manager http_server.template_env = self.template_env http_server.kp_shutdown = self.shutdown http_server.ws_manager = self.ws_manager http_server.headers = self.headers if not config.has_option('server.secret_id'): config.set('server.secret_id', rest_api.generate_token()) if not config.get_if_exists('server.rest_api.token'): config.set('server.rest_api.token', rest_api.generate_token()) if config.get('server.rest_api.enabled'): self.logger.info('rest api initialized with token: ' + config.get('server.rest_api.token')) self.__geoip_db = geoip.init_database(config.get('server.geoip.database')) self.__is_shutdown = threading.Event() self.__is_shutdown.clear() self.__shutdown_lock = threading.Lock() plugin_manager.server = weakref.proxy(self) headers = self.config.get_if_exists('server.headers', []) for header in headers: if ': ' not in header: self.logger.warning("header '{0}' is invalid and will not be included".format(header)) continue header, value = header.split(': ', 1) header = header.strip() self.headers[header] = value self.logger.info("including {0} custom http headers".format(len(self.headers)))