def _create_ssh_forwarder(self, server, username, password): """ Create and set the :py:attr:`~.KingPhisherClientApplication._ssh_forwarder` attribute. :param tuple server: The server information as a host and port tuple. :param str username: The username to authenticate to the SSH server with. :param str password: The password to authenticate to the SSH server with. :rtype: int :return: The local port that is forwarded to the remote server or None if the connection failed. """ active_window = self.get_active_window() title_ssh_error = 'Failed To Connect To The SSH Service' server_remote_port = self.config['server_remote_port'] local_port = random.randint(2000, 6000) try: self._ssh_forwarder = SSHTCPForwarder(server, username, password, local_port, ('127.0.0.1', server_remote_port), preferred_private_key=self.config['ssh_preferred_key']) self._ssh_forwarder.start() time.sleep(0.5) self.logger.info('started ssh port forwarding') except paramiko.AuthenticationException: self.logger.warning('failed to authenticate to the remote ssh server') gui_utilities.show_dialog_error(title_ssh_error, active_window, 'The server responded that the credentials are invalid.') except socket.error as error: gui_utilities.show_dialog_exc_socket_error(error, active_window, title=title_ssh_error) except Exception as error: self.logger.warning('failed to connect to the remote ssh server', exc_info=True) gui_utilities.show_dialog_error(title_ssh_error, active_window, "An {0}.{1} error occurred.".format(error.__class__.__module__, error.__class__.__name__)) else: return local_port self.server_disconnect() return
def _create_ssh_forwarder(self, server, username, password, window=None): """ Create and set the :py:attr:`~.KingPhisherClientApplication._ssh_forwarder` attribute. :param tuple server: The server information as a host and port tuple. :param str username: The username to authenticate to the SSH server with. :param str password: The password to authenticate to the SSH server with. :param window: The GTK window to use as the parent for error dialogs. :type window: :py:class:`Gtk.Window` :rtype: int :return: The local port that is forwarded to the remote server or None if the connection failed. """ window = window or self.get_active_window() title_ssh_error = 'Failed To Connect To The SSH Service' server_remote_port = self.config['server_remote_port'] try: self._ssh_forwarder = ssh_forward.SSHTCPForwarder( server, username, password, ('127.0.0.1', server_remote_port), private_key=self.config.get('ssh_preferred_key'), missing_host_key_policy=ssh_host_key.MissingHostKeyPolicy( self)) self._ssh_forwarder.start() except ssh_forward.KingPhisherSSHKeyError as error: gui_utilities.show_dialog_error('SSH Key Configuration Error', window, error.message) except errors.KingPhisherAbortError as error: self.logger.info("ssh connection aborted ({0})".format( error.message)) except paramiko.PasswordRequiredException: gui_utilities.show_dialog_error( title_ssh_error, window, 'The specified SSH key requires a password.') except paramiko.AuthenticationException: self.logger.warning( 'failed to authenticate to the remote ssh server') gui_utilities.show_dialog_error( title_ssh_error, window, 'The server responded that the credentials are invalid.') except paramiko.SSHException as error: self.logger.warning("failed with ssh exception '{0}'".format( error.args[0])) except socket.error as error: gui_utilities.show_dialog_exc_socket_error(error, window, title=title_ssh_error) except Exception as error: self.logger.warning('failed to connect to the remote ssh server', exc_info=True) gui_utilities.show_dialog_error( title_ssh_error, window, "An {0}.{1} error occurred.".format(error.__class__.__module__, error.__class__.__name__)) else: return self._ssh_forwarder.local_server self.emit('server-disconnected') return
def _create_ssh_forwarder(self, server, username, password): """ Create and set the :py:attr:`~.KingPhisherClientApplication._ssh_forwarder` attribute. :param tuple server: The server information as a host and port tuple. :param str username: The username to authenticate to the SSH server with. :param str password: The password to authenticate to the SSH server with. :rtype: int :return: The local port that is forwarded to the remote server or None if the connection failed. """ active_window = self.get_active_window() title_ssh_error = 'Failed To Connect To The SSH Service' server_remote_port = self.config['server_remote_port'] try: self._ssh_forwarder = ssh_forward.SSHTCPForwarder( server, username, password, ('127.0.0.1', server_remote_port), private_key=self.config.get('ssh_preferred_key'), missing_host_key_policy=ssh_host_key.MissingHostKeyPolicy(self) ) self._ssh_forwarder.start() except ssh_forward.KingPhisherSSHKeyError as error: gui_utilities.show_dialog_error( 'SSH Key Configuration Error', active_window, error.message ) except errors.KingPhisherAbortError as error: self.logger.info("ssh connection aborted ({0})".format(error.message)) except paramiko.PasswordRequiredException: gui_utilities.show_dialog_error(title_ssh_error, active_window, 'The specified SSH key requires a password.') except paramiko.AuthenticationException: self.logger.warning('failed to authenticate to the remote ssh server') gui_utilities.show_dialog_error(title_ssh_error, active_window, 'The server responded that the credentials are invalid.') except paramiko.SSHException as error: self.logger.warning("failed with ssh exception '{0}'".format(error.args[0])) except socket.error as error: gui_utilities.show_dialog_exc_socket_error(error, active_window, title=title_ssh_error) except Exception as error: self.logger.warning('failed to connect to the remote ssh server', exc_info=True) gui_utilities.show_dialog_error(title_ssh_error, active_window, "An {0}.{1} error occurred.".format(error.__class__.__module__, error.__class__.__name__)) else: return self._ssh_forwarder.local_server self.emit('server-disconnected') return
def _create_ssh_forwarder(self, server, username, password): """ Create and set the :py:attr:`~.KingPhisherClient._ssh_forwarder` attribute. :param tuple server: The server information as a host and port tuple. :param str username: The username to authenticate to the SSH server with. :param str password: The password to authenticate to the SSH server with. :rtype: int :return: The local port that is forwarded to the remote server or None if the connection failed. """ title_ssh_error = 'Failed To Connect To The SSH Service' server_remote_port = self.config['server_remote_port'] local_port = random.randint(2000, 6000) try: self._ssh_forwarder = SSHTCPForwarder( server, username, password, local_port, ('127.0.0.1', server_remote_port), preferred_private_key=self.config['ssh_preferred_key']) self._ssh_forwarder.start() time.sleep(0.5) self.logger.info('started ssh port forwarding') except paramiko.AuthenticationException: self.logger.warning( 'failed to authenticate to the remote ssh server') gui_utilities.show_dialog_error( title_ssh_error, self, 'The server responded that the credentials are invalid.') except socket.error as error: gui_utilities.show_dialog_exc_socket_error(error, self, title=title_ssh_error) except Exception as error: self.logger.warning('failed to connect to the remote ssh server', exc_info=True) gui_utilities.show_dialog_error( title_ssh_error, self, "An {0}.{1} error occurred.".format(error.__class__.__module__, error.__class__.__name__)) else: return local_port self.server_disconnect() return
def server_connect(self, username, password, otp=None): # pylint: disable=too-many-locals server_version_info = None title_rpc_error = 'Failed To Connect To The King Phisher RPC Service' active_window = self.get_active_window() server = parse_server(self.config['server'], 22) if ipaddress.is_loopback(server[0]): local_server = ('localhost', self.config['server_remote_port']) self.logger.info("connecting to local king phisher instance") else: local_server = self._create_ssh_forwarder(server, username, password) if not local_server: return False, ConnectionErrorReason.ERROR_PORT_FORWARD rpc = client_rpc.KingPhisherRPCClient( local_server, use_ssl=self.config.get('server_use_ssl')) if self.config.get('rpc.serializer'): try: rpc.set_serializer(self.config['rpc.serializer']) except ValueError as error: self.logger.error( "failed to set the rpc serializer, error: '{0}'".format( error.message)) generic_message = 'Can not contact the RPC HTTP service, ensure that the ' generic_message += "King Phisher Server is currently running on port {0}.".format( int(self.config['server_remote_port'])) connection_failed = True try: server_version_info = rpc('version') if server_version_info is None: raise RuntimeError( 'no version information was retrieved from the server') except advancedhttpserver.RPCError as error: self.logger.warning( 'failed to connect to the remote rpc service due to http status: ' + str(error.status)) gui_utilities.show_dialog_error( title_rpc_error, active_window, "The server responded with HTTP status: {0}.".format( str(error.status))) except BadStatusLine as error: self.logger.warning( 'failed to connect to the remote rpc service due to http bad status line: ' + error.line) gui_utilities.show_dialog_error(title_rpc_error, active_window, generic_message) except socket.error as error: self.logger.debug( 'failed to connect to the remote rpc service due to a socket error', exc_info=True) gui_utilities.show_dialog_exc_socket_error(error, active_window) except ssl.CertificateError as error: self.logger.warning( 'failed to connect to the remote rpc service with a https certificate error: ' + error.message) gui_utilities.show_dialog_error( title_rpc_error, active_window, 'The server presented an invalid SSL certificate.') except Exception: self.logger.warning('failed to connect to the remote rpc service', exc_info=True) gui_utilities.show_dialog_error(title_rpc_error, active_window, generic_message) else: connection_failed = False if connection_failed: self.emit('server-disconnected') return False, ConnectionErrorReason.ERROR_CONNECTION server_rpc_api_version = server_version_info.get('rpc_api_version', -1) if isinstance(server_rpc_api_version, int): # compatibility with pre-0.2.0 version server_rpc_api_version = (server_rpc_api_version, 0) self.logger.info( "successfully connected to the king phisher server (version: {0} rpc api version: {1}.{2})" .format(server_version_info['version'], server_rpc_api_version[0], server_rpc_api_version[1])) error_text = None if server_rpc_api_version[0] < version.rpc_api_version.major or ( server_rpc_api_version[0] == version.rpc_api_version.major and server_rpc_api_version[1] < version.rpc_api_version.minor): error_text = 'The server is running an old and incompatible version.' error_text += '\nPlease update the remote server installation.' elif server_rpc_api_version[0] > version.rpc_api_version.major: error_text = 'The client is running an old and incompatible version.' error_text += '\nPlease update the local client installation.' if error_text: gui_utilities.show_dialog_error( 'The RPC API Versions Are Incompatible', active_window, error_text) self.emit('server-disconnected') return False, ConnectionErrorReason.ERROR_INCOMPATIBLE_VERSIONS login_result, login_reason = rpc.login(username, password, otp) if not login_result: self.logger.warning( 'failed to authenticate to the remote king phisher service, reason: ' + login_reason) self.emit('server-disconnected') return False, login_reason rpc.username = username self.logger.debug( 'successfully authenticated to the remote king phisher service') self._rpc_ping_event = GLib.timeout_add_seconds( parse_timespan('5m'), rpc.ping) self.rpc = rpc event_subscriber = server_events.ServerEventSubscriber(rpc) if not event_subscriber.is_connected: self.logger.error('failed to connect the server event socket') event_subscriber.reconnect = False event_subscriber.shutdown() return False, ConnectionErrorReason.ERROR_UNKNOWN self.server_events = event_subscriber self.emit('server-connected') return True, ConnectionErrorReason.SUCCESS
def server_connect(self, username, password, otp=None): # pylint: disable=too-many-locals server_version_info = None title_rpc_error = 'Failed To Connect To The King Phisher RPC Service' active_window = self.get_active_window() server = parse_server(self.config['server'], 22) if ipaddress.is_loopback(server[0]): local_server = ('localhost', self.config['server_remote_port']) self.logger.info("connecting to local king phisher instance") else: local_server = self._create_ssh_forwarder(server, username, password) if not local_server: return False, ConnectionErrorReason.ERROR_PORT_FORWARD rpc = client_rpc.KingPhisherRPCClient(local_server, use_ssl=self.config.get('server_use_ssl')) if self.config.get('rpc.serializer'): try: rpc.set_serializer(self.config['rpc.serializer']) except ValueError as error: self.logger.error("failed to set the rpc serializer, error: '{0}'".format(error.message)) generic_message = 'Can not contact the RPC HTTP service, ensure that the ' generic_message += "King Phisher Server is currently running on port {0}.".format(int(self.config['server_remote_port'])) connection_failed = True try: server_version_info = rpc('version') assert server_version_info is not None except AdvancedHTTPServerRPCError as error: self.logger.warning('failed to connect to the remote rpc service due to http status: ' + str(error.status)) gui_utilities.show_dialog_error(title_rpc_error, active_window, "The server responded with HTTP status: {0}.".format(str(error.status))) except BadStatusLine as error: self.logger.warning('failed to connect to the remote rpc service due to http bad status line: ' + error.line) gui_utilities.show_dialog_error(title_rpc_error, active_window, generic_message) except socket.error as error: gui_utilities.show_dialog_exc_socket_error(error, active_window) except ssl.CertificateError as error: self.logger.warning('failed to connect to the remote rpc service with a https certificate error: ' + error.message) gui_utilities.show_dialog_error(title_rpc_error, active_window, 'The server presented an invalid SSL certificate.') except Exception: self.logger.warning('failed to connect to the remote rpc service', exc_info=True) gui_utilities.show_dialog_error(title_rpc_error, active_window, generic_message) else: connection_failed = False if connection_failed: self.emit('server-disconnected') return False, ConnectionErrorReason.ERROR_CONNECTION server_rpc_api_version = server_version_info.get('rpc_api_version', -1) if isinstance(server_rpc_api_version, int): # compatibility with pre-0.2.0 version server_rpc_api_version = (server_rpc_api_version, 0) self.logger.info( "successfully connected to the king phisher server (version: {0} rpc api version: {1}.{2})".format( server_version_info['version'], server_rpc_api_version[0], server_rpc_api_version[1] ) ) error_text = None if server_rpc_api_version[0] < version.rpc_api_version.major or (server_rpc_api_version[0] == version.rpc_api_version.major and server_rpc_api_version[1] < version.rpc_api_version.minor): error_text = 'The server is running an old and incompatible version.' error_text += '\nPlease update the remote server installation.' elif server_rpc_api_version[0] > version.rpc_api_version.major: error_text = 'The client is running an old and incompatible version.' error_text += '\nPlease update the local client installation.' if error_text: gui_utilities.show_dialog_error('The RPC API Versions Are Incompatible', active_window, error_text) self.emit('server-disconnected') return False, ConnectionErrorReason.ERROR_INCOMPATIBLE_VERSIONS login_result, login_reason = rpc.login(username, password, otp) if not login_result: self.logger.warning('failed to authenticate to the remote king phisher service, reason: ' + login_reason) self.emit('server-disconnected') return False, login_reason rpc.username = username self.logger.debug('successfully authenticated to the remote king phisher service') self.rpc = rpc self.emit('server-connected') return True, ConnectionErrorReason.SUCCESS
def server_connect(self): server_version_info = None title_rpc_error = 'Failed To Connect To The King Phisher RPC Service' active_window = self.get_active_window() server = parse_server(self.config['server'], 22) username = self.config['server_username'] password = self.config['server_password'] if server[0] == 'localhost' or (utilities.is_valid_ip_address(server[0]) and ipaddress.ip_address(server[0]).is_loopback): local_port = self.config['server_remote_port'] self.logger.info("connecting to local king-phisher instance") else: local_port = self._create_ssh_forwarder(server, username, password) if not local_port: return self.rpc = client_rpc.KingPhisherRPCClient(('localhost', local_port), username=username, password=password, use_ssl=self.config.get('server_use_ssl')) if self.config.get('rpc.serializer'): try: self.rpc.set_serializer(self.config['rpc.serializer']) except ValueError as error: self.logger.error("failed to set the rpc serializer, error: '{0}'".format(error.message)) connection_failed = True try: assert self.rpc('client/initialize') server_version_info = self.rpc('version') assert server_version_info != None except AdvancedHTTPServerRPCError as err: if err.status == 401: self.logger.warning('failed to authenticate to the remote king phisher service') gui_utilities.show_dialog_error(title_rpc_error, active_window, 'The server responded that the credentials are invalid.') else: self.logger.warning('failed to connect to the remote rpc server with http status: ' + str(err.status)) gui_utilities.show_dialog_error(title_rpc_error, active_window, 'The server responded with HTTP status: ' + str(err.status)) except socket.error as error: gui_utilities.show_dialog_exc_socket_error(error, active_window) except Exception as error: self.logger.warning('failed to connect to the remote rpc service', exc_info=True) gui_utilities.show_dialog_error(title_rpc_error, active_window, 'Ensure that the King Phisher Server is currently running.') else: connection_failed = False finally: if connection_failed: self.rpc = None self.server_disconnect() return server_rpc_api_version = server_version_info.get('rpc_api_version', -1) if isinstance(server_rpc_api_version, int): # compatibility with pre-0.2.0 version server_rpc_api_version = (server_rpc_api_version, 0) self.logger.info("successfully connected to the king phisher server (version: {0} rpc api version: {1}.{2})".format(server_version_info['version'], server_rpc_api_version[0], server_rpc_api_version[1])) error_text = None if server_rpc_api_version[0] < version.rpc_api_version.major or (server_rpc_api_version[0] == version.rpc_api_version.major and server_rpc_api_version[1] < version.rpc_api_version.minor): error_text = 'The server is running an old and incompatible version.' error_text += '\nPlease update the remote server installation.' elif server_rpc_api_version[0] > version.rpc_api_version.major: error_text = 'The client is running an old and incompatible version.' error_text += '\nPlease update the local client installation.' if error_text: gui_utilities.show_dialog_error('The RPC API Versions Are Incompatible', active_window, error_text) self.server_disconnect() return self.emit('server-connected') return
def server_connect(self, username, password, otp=None, window=None): """ Initialize the connection to the King Phisher server. :param str username: The username to authenticate with. :param str password: The password to authenticate with. :param str otp: The optional one-time password to authenticate with. :param window: The GTK window to use as the parent for error dialogs. :type window: :py:class:`Gtk.Window` :rtype: tuple """ # pylint: disable=too-many-locals server_version_info = None title_rpc_error = 'Failed To Connect To The King Phisher RPC Service' window = window or self.get_active_window() server = parse_server(self.config['server'], 22) if ipaddress.is_loopback(server[0]): local_server = ('localhost', self.config['server_remote_port']) self.logger.info("connecting to local king phisher instance") else: local_server = self._create_ssh_forwarder(server, username, password, window=window) if not local_server: return False, ConnectionErrorReason.ERROR_PORT_FORWARD rpc = client_rpc.KingPhisherRPCClient( local_server, use_ssl=self.config.get('server_use_ssl')) if self.config.get('rpc.serializer'): try: rpc.set_serializer(self.config['rpc.serializer']) except ValueError as error: self.logger.error( "failed to set the rpc serializer, error: '{0}'".format( error.message)) generic_message = 'Can not contact the RPC HTTP service, ensure that the ' generic_message += "King Phisher Server is currently running on port {0}.".format( int(self.config['server_remote_port'])) connection_failed = True try: server_version_info = rpc('version') if server_version_info is None: rpc.shutdown() raise RuntimeError( 'no version information was retrieved from the server') except advancedhttpserver.RPCError as error: self.logger.warning( 'failed to connect to the remote rpc service due to http status: ' + str(error.status)) gui_utilities.show_dialog_error( title_rpc_error, window, "The server responded with HTTP status: {0}.".format( str(error.status))) except http.client.BadStatusLine as error: self.logger.warning( 'failed to connect to the remote rpc service due to http bad status line: ' + error.line) gui_utilities.show_dialog_error(title_rpc_error, window, generic_message) except socket.error as error: self.logger.debug( 'failed to connect to the remote rpc service due to a socket error', exc_info=True) gui_utilities.show_dialog_exc_socket_error(error, window) except ssl.CertificateError as error: self.logger.warning( 'failed to connect to the remote rpc service with a https certificate error: ' + error.message) gui_utilities.show_dialog_error( title_rpc_error, window, 'The server presented an invalid SSL certificate.') except Exception: self.logger.warning('failed to connect to the remote rpc service', exc_info=True) gui_utilities.show_dialog_error(title_rpc_error, window, generic_message) else: connection_failed = False if connection_failed: rpc.shutdown() self.emit('server-disconnected') return False, ConnectionErrorReason.ERROR_CONNECTION server_rpc_api_version = server_version_info.get('rpc_api_version', -1) if isinstance(server_rpc_api_version, int): # compatibility with pre-0.2.0 version server_rpc_api_version = (server_rpc_api_version, 0) self.logger.info( "successfully connected to the king phisher server (version: {0} rpc api version: {1}.{2})" .format(server_version_info['version'], server_rpc_api_version[0], server_rpc_api_version[1])) error_text = None if server_rpc_api_version[0] < version.rpc_api_version.major or ( server_rpc_api_version[0] == version.rpc_api_version.major and server_rpc_api_version[1] < version.rpc_api_version.minor): error_text = 'The server is running an old and incompatible version.' error_text += '\nPlease update the remote server installation.' elif server_rpc_api_version[0] > version.rpc_api_version.major: error_text = 'The client is running an old and incompatible version.' error_text += '\nPlease update the local client installation.' if error_text: gui_utilities.show_dialog_error( 'The RPC API Versions Are Incompatible', window, error_text) rpc.shutdown() self.emit('server-disconnected') return False, ConnectionErrorReason.ERROR_INCOMPATIBLE_VERSIONS login_result, login_reason = rpc.login(username, password, otp) if not login_result: self.logger.warning( 'failed to authenticate to the remote king phisher service, reason: ' + login_reason) rpc.shutdown() self.emit('server-disconnected') return False, login_reason rpc.username = username self.logger.debug( 'successfully authenticated to the remote king phisher service') server_str = self.config['server'] history = self.config['server.history'] if server_str in history: history.remove(server_str) history.insert(0, server_str) self.config['server.history'] = history event_subscriber = server_events.ServerEventSubscriber(rpc) if not event_subscriber.is_connected: event_subscriber.reconnect = False event_subscriber.shutdown() rpc.shutdown() self.emit('server-disconnected') return False, ConnectionErrorReason.ERROR_UNKNOWN self.rpc = rpc self.server_events = event_subscriber self._rpc_ping_event = GLib.timeout_add_seconds( parse_timespan('5m'), functools.partial(_rpc_ping, rpc)) user = self.rpc.graphql( """\ query getUser($name: String!) { db { user(name: $name) { id name } } }""", {'name': self.config['server_username']})['db']['user'] self.server_user = ServerUser(id=user['id'], name=user['name']) self.emit('server-connected') return True, ConnectionErrorReason.SUCCESS
def signal_login_dialog_response(self, dialog, response, glade_dialog): server_version_info = None title_rpc_error = 'Failed To Connect To The King Phisher RPC Service' if response == Gtk.ResponseType.CANCEL or response == Gtk.ResponseType.DELETE_EVENT: dialog.destroy() self.emit('exit') return True glade_dialog.objects_save_to_config() server = utilities.server_parse(self.config['server'], 22) username = self.config['server_username'] password = self.config['server_password'] if server[0] == 'localhost' or (utilities.is_valid_ip_address( server[0]) and ipaddress.ip_address(server[0]).is_loopback): local_port = self.config['server_remote_port'] self.logger.info("connecting to local king-phisher instance") else: local_port = self._create_ssh_forwarder(server, username, password) if not local_port: return self.rpc = KingPhisherRPCClient( ('localhost', local_port), username=username, password=password, use_ssl=self.config.get('server_use_ssl')) if self.config.get('rpc.serializer'): try: self.rpc.set_serializer(self.config['rpc.serializer']) except ValueError as error: self.logger.error( "failed to set the rpc serializer, error: '{0}'".format( error.message)) connection_failed = True try: assert self.rpc('client/initialize') server_version_info = self.rpc('version') assert server_version_info != None except AdvancedHTTPServerRPCError as err: if err.status == 401: self.logger.warning( 'failed to authenticate to the remote king phisher service' ) gui_utilities.show_dialog_error( title_rpc_error, self, 'The server responded that the credentials are invalid.') else: self.logger.warning( 'failed to connect to the remote rpc server with http status: ' + str(err.status)) gui_utilities.show_dialog_error( title_rpc_error, self, 'The server responded with HTTP status: ' + str(err.status)) except socket.error as error: gui_utilities.show_dialog_exc_socket_error(error, self) except Exception as error: self.logger.warning('failed to connect to the remote rpc service') gui_utilities.show_dialog_error( title_rpc_error, self, 'Ensure that the King Phisher Server is currently running.') else: connection_failed = False finally: if connection_failed: self.rpc = None self.server_disconnect() return server_rpc_api_version = server_version_info.get('rpc_api_version', -1) if isinstance(server_rpc_api_version, int): # compatibility with pre-0.2.0 version server_rpc_api_version = (server_rpc_api_version, 0) self.logger.info( "successfully connected to the king phisher server (version: {0} rpc api version: {1}.{2})" .format(server_version_info['version'], server_rpc_api_version[0], server_rpc_api_version[1])) self.server_local_port = local_port error_text = None if server_rpc_api_version[0] < version.rpc_api_version.major or ( server_rpc_api_version[0] == version.rpc_api_version.major and server_rpc_api_version[1] < version.rpc_api_version.minor): error_text = 'The server is running an old and incompatible version.' error_text += '\nPlease update the remote server installation.' elif server_rpc_api_version[0] > version.rpc_api_version.major: error_text = 'The client is running an old and incompatible version.' error_text += '\nPlease update the local client installation.' if error_text: gui_utilities.show_dialog_error( 'The RPC API Versions Are Incompatible', self, error_text) self.server_disconnect() return dialog.destroy() self.emit('server-connected') return
def server_connect(self, username, password, otp=None): # pylint: disable=too-many-locals server_version_info = None title_rpc_error = 'Failed To Connect To The King Phisher RPC Service' active_window = self.get_active_window() server = parse_server(self.config['server'], 22) if server[0] == 'localhost' or (utilities.is_valid_ip_address( server[0]) and ipaddress.ip_address(server[0]).is_loopback): local_server = ('localhost', self.config['server_remote_port']) self.logger.info("connecting to local king phisher instance") else: local_server = self._create_ssh_forwarder(server, username, password) if not local_server: return False, ConnectionErrorReason.ERROR_PORT_FORWARD rpc = client_rpc.KingPhisherRPCClient( local_server, use_ssl=self.config.get('server_use_ssl')) if self.config.get('rpc.serializer'): try: rpc.set_serializer(self.config['rpc.serializer']) except ValueError as error: self.logger.error( "failed to set the rpc serializer, error: '{0}'".format( error.message)) connection_failed = True try: server_version_info = rpc('version') assert server_version_info is not None except AdvancedHTTPServerRPCError as error: self.logger.warning( 'failed to connect to the remote rpc service with http status: ' + str(error.status)) gui_utilities.show_dialog_error( title_rpc_error, active_window, "The server responded with HTTP status: {0}.".format( str(error.status))) except socket.error as error: gui_utilities.show_dialog_exc_socket_error(error, active_window) except ssl.CertificateError as error: self.logger.warning( 'failed to connect to the remote rpc service with a https certificate error: ' + error.message) gui_utilities.show_dialog_error( title_rpc_error, active_window, 'The server presented an invalid SSL certificate.') except Exception: self.logger.warning('failed to connect to the remote rpc service', exc_info=True) gui_utilities.show_dialog_error( title_rpc_error, active_window, 'Ensure that the King Phisher Server is currently running.') else: connection_failed = False if connection_failed: self.server_disconnect() return False, ConnectionErrorReason.ERROR_CONNECTION server_rpc_api_version = server_version_info.get('rpc_api_version', -1) if isinstance(server_rpc_api_version, int): # compatibility with pre-0.2.0 version server_rpc_api_version = (server_rpc_api_version, 0) self.logger.info( "successfully connected to the king phisher server (version: {0} rpc api version: {1}.{2})" .format(server_version_info['version'], server_rpc_api_version[0], server_rpc_api_version[1])) error_text = None if server_rpc_api_version[0] < version.rpc_api_version.major or ( server_rpc_api_version[0] == version.rpc_api_version.major and server_rpc_api_version[1] < version.rpc_api_version.minor): error_text = 'The server is running an old and incompatible version.' error_text += '\nPlease update the remote server installation.' elif server_rpc_api_version[0] > version.rpc_api_version.major: error_text = 'The client is running an old and incompatible version.' error_text += '\nPlease update the local client installation.' if error_text: gui_utilities.show_dialog_error( 'The RPC API Versions Are Incompatible', active_window, error_text) self.server_disconnect() return False, ConnectionErrorReason.ERROR_INCOMPATIBLE_VERSIONS login_result, login_reason = rpc.login(username, password, otp) if not login_result: self.logger.warning( 'failed to authenticate to the remote king phisher service, reason: ' + login_reason) self.server_disconnect() return False, login_reason rpc.username = username self.logger.debug( 'successfully authenticated to the remote king phisher service') self.rpc = rpc self.emit('server-connected') return True, ConnectionErrorReason.SUCCESS
def server_connect(self, username, password, otp=None, window=None): """ Initialize the connection to the King Phisher server. :param str username: The username to authenticate with. :param str password: The password to authenticate with. :param str otp: The optional one-time password to authenticate with. :param window: The GTK window to use as the parent for error dialogs. :type window: :py:class:`Gtk.Window` :rtype: tuple """ # pylint: disable=too-many-locals server_version_info = None title_rpc_error = 'Failed To Connect To The King Phisher RPC Service' window = window or self.get_active_window() server = parse_server(self.config['server'], 22) if ipaddress.is_loopback(server[0]): local_server = ('localhost', self.config['server_remote_port']) self.logger.info("connecting to local king phisher instance") else: local_server = self._create_ssh_forwarder(server, username, password, window=window) if not local_server: return False, ConnectionErrorReason.ERROR_PORT_FORWARD rpc = client_rpc.KingPhisherRPCClient(local_server, use_ssl=self.config.get('server_use_ssl')) if self.config.get('rpc.serializer'): try: rpc.set_serializer(self.config['rpc.serializer']) except ValueError as error: self.logger.error("failed to set the rpc serializer, error: '{0}'".format(error.message)) generic_message = 'Can not contact the RPC HTTP service, ensure that the ' generic_message += "King Phisher Server is currently running on port {0}.".format(int(self.config['server_remote_port'])) connection_failed = True try: server_version_info = rpc('version') if server_version_info is None: raise RuntimeError('no version information was retrieved from the server') except advancedhttpserver.RPCError as error: self.logger.warning('failed to connect to the remote rpc service due to http status: ' + str(error.status)) gui_utilities.show_dialog_error(title_rpc_error, window, "The server responded with HTTP status: {0}.".format(str(error.status))) except http.client.BadStatusLine as error: self.logger.warning('failed to connect to the remote rpc service due to http bad status line: ' + error.line) gui_utilities.show_dialog_error(title_rpc_error, window, generic_message) except socket.error as error: self.logger.debug('failed to connect to the remote rpc service due to a socket error', exc_info=True) gui_utilities.show_dialog_exc_socket_error(error, window) except ssl.CertificateError as error: self.logger.warning('failed to connect to the remote rpc service with a https certificate error: ' + error.message) gui_utilities.show_dialog_error(title_rpc_error, window, 'The server presented an invalid SSL certificate.') except Exception: self.logger.warning('failed to connect to the remote rpc service', exc_info=True) gui_utilities.show_dialog_error(title_rpc_error, window, generic_message) else: connection_failed = False if connection_failed: self.emit('server-disconnected') return False, ConnectionErrorReason.ERROR_CONNECTION server_rpc_api_version = server_version_info.get('rpc_api_version', -1) if isinstance(server_rpc_api_version, int): # compatibility with pre-0.2.0 version server_rpc_api_version = (server_rpc_api_version, 0) self.logger.info( "successfully connected to the king phisher server (version: {0} rpc api version: {1}.{2})".format( server_version_info['version'], server_rpc_api_version[0], server_rpc_api_version[1] ) ) error_text = None if server_rpc_api_version[0] < version.rpc_api_version.major or (server_rpc_api_version[0] == version.rpc_api_version.major and server_rpc_api_version[1] < version.rpc_api_version.minor): error_text = 'The server is running an old and incompatible version.' error_text += '\nPlease update the remote server installation.' elif server_rpc_api_version[0] > version.rpc_api_version.major: error_text = 'The client is running an old and incompatible version.' error_text += '\nPlease update the local client installation.' if error_text: gui_utilities.show_dialog_error('The RPC API Versions Are Incompatible', window, error_text) self.emit('server-disconnected') return False, ConnectionErrorReason.ERROR_INCOMPATIBLE_VERSIONS login_result, login_reason = rpc.login(username, password, otp) if not login_result: self.logger.warning('failed to authenticate to the remote king phisher service, reason: ' + login_reason) self.emit('server-disconnected') return False, login_reason rpc.username = username self.logger.debug('successfully authenticated to the remote king phisher service') event_subscriber = server_events.ServerEventSubscriber(rpc) if not event_subscriber.is_connected: event_subscriber.reconnect = False event_subscriber.shutdown() return False, ConnectionErrorReason.ERROR_UNKNOWN self.rpc = rpc self.server_events = event_subscriber self._rpc_ping_event = GLib.timeout_add_seconds(parse_timespan('5m'), rpc.ping) user = self.rpc.graphql("""\ query getUser($name: String!) { db { user(name: $name) { id name } } }""", {'name': self.config['server_username']})['db']['user'] self.server_user = ServerUser(id=user['id'], name=user['name']) self.emit('server-connected') return True, ConnectionErrorReason.SUCCESS