コード例 #1
0
    def signal_renderer_toggled_enable(self, _, path):
        pm = self.application.plugin_manager
        named_row = self._named_model(*self._model[path])
        if named_row.type != _ROW_TYPE_PLUGIN:
            return
        if named_row.id not in pm.loaded_plugins:
            return

        if named_row.id in self._module_errors:
            gui_utilities.show_dialog_error(
                'Can Not Enable Plugin', self.window,
                'Can not enable a plugin which failed to load.')
            return
        if named_row.enabled:
            self._disable_plugin(path)
        else:
            if not pm.loaded_plugins[named_row.id].is_compatible:
                gui_utilities.show_dialog_error(
                    'Incompatible Plugin', self.window,
                    'This plugin is not compatible.')
                return
            if not pm.enable(named_row.id):
                return
            self._set_model_item(path, 'enabled', True)
            self.config['plugins.enabled'].append(named_row.id)
コード例 #2
0
	def do_message_data_import(self, target_file, dest_dir):
		config_tab = self.tabs.get('config')
		config_prefix = config_tab.config_prefix
		try:
			message_data = export.message_data_from_kpm(target_file, dest_dir)
		except KingPhisherInputValidationError as error:
			gui_utilities.show_dialog_error('Import Error', self.parent, error.message.capitalize() + '.')
			return False

		config_keys = set(key for key in self.config.keys() if key.startswith(config_prefix))
		config_types = dict(zip(config_keys, [type(self.config[key]) for key in config_keys]))
		for key, value in message_data.items():
			key = config_prefix + key
			if not key in config_keys:
				continue
			self.config[key] = value
			config_keys.remove(key)
		for unset_key in config_keys:
			config_type = config_types[unset_key]
			if not config_type in (bool, dict, int, list, str, tuple):
				continue
			self.config[unset_key] = config_type()

		# set missing defaults for backwards compatibility
		if not self.config.get('mailer.message_type'):
			self.config['mailer.message_type'] = 'email'
		if not self.config.get('mailer.target_type'):
			self.config['mailer.target_type'] = 'file'

		config_tab.objects_load_from_config()
		return True
コード例 #3
0
	def delete_campaign(self):
		if not gui_utilities.show_dialog_yes_no('Delete This Campaign?', self, 'This action is irreversible. All campaign data will be lost.'):
			return
		self.rpc('campaign/delete', self.config['campaign_id'])
		if not self.show_campaign_selection():
			gui_utilities.show_dialog_error('A Campaign Must Be Selected', self, 'Now exiting')
			self.client_quit()
コード例 #4
0
ファイル: extras.py プロジェクト: securestate/king-phisher
    def run_quick_save(self, current_name=None):
        """
		Display a dialog which asks the user where a file should be saved. The
		value of target_path in the returned dictionary is an absolute path.

		:param set current_name: The name of the file to save.
		:return: A dictionary with target_uri and target_path keys representing the path choosen.
		:rtype: dict
		"""
        self.set_action(Gtk.FileChooserAction.SAVE)
        self.add_button(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL)
        self.add_button(Gtk.STOCK_SAVE, Gtk.ResponseType.ACCEPT)
        self.set_do_overwrite_confirmation(True)
        if current_name:
            self.set_current_name(current_name)
        self.show_all()
        response = self.run()
        if response == Gtk.ResponseType.CANCEL:
            return None
        target_path = self.get_filename()
        if os.path.isfile(target_path):
            if not os.access(target_path, os.W_OK):
                gui_utilities.show_dialog_error("Can not write to the selected file", self.parent)
                return None
        elif not os.access(os.path.dirname(target_path), os.W_OK):
            gui_utilities.show_dialog_error("Can not create the selected file", self.parent)
            return None
        target_uri = self.get_uri()
        return {"target_uri": target_uri, "target_path": target_path}
コード例 #5
0
    def _save_editor_file(self):
        """
		Handles the save file action for the editor instance when button is pressed or when tabs are changed
		"""
        if not self.editor:
            self.editor_tab_save_button.set_sensitive(False)
            self.notebook.set_current_page(0)
            self.notebook.set_show_tabs(False)
            return

        buffer_contents = self.editor.sourceview_buffer.get_text(
            self.editor.sourceview_buffer.get_start_iter(),
            self.editor.sourceview_buffer.get_end_iter(), False)
        if buffer_contents == self.editor.file_contents:
            logger.debug('editor found nothing to save')
            self.editor_tab_save_button.set_sensitive(False)
            return

        buffer_contents = buffer_contents.encode('utf-8')

        try:
            self.editor.directory.write_file(self.editor.file_path,
                                             buffer_contents)
            self.editor.file_contents = buffer_contents
            logger.info("saved editor contents to {} file path {}".format(
                self.editor.file_location, self.editor.file_path))
        except IOError:
            logger.warning("could not write to {} file: {}".format(
                self.editor.file_location, self.editor.file_path))
            self.editor_tab_save_button.set_sensitive(False)
            gui_utilities.show_dialog_error(
                'Permission Denied', self.application.get_active_window(),
                "Cannot write to {} file".format(self.editor.file_location))
            return
        self.editor_tab_save_button.set_sensitive(False)
コード例 #6
0
	def prompt_and_generate(self):
		active_window = self.application.get_active_window()
		dialog_txt = 'Would you like to submit anonymized data to SecureState for research purposes?'
		if not gui_utilities.show_dialog_yes_no('Submit Phishing Data', active_window, dialog_txt):
			return

		get_stats = StatsGenerator(self.application.rpc)
		stats = get_stats.generate_stats()
		stats = stats.encode('utf-8')
		stats = bz2.compress(stats)
		stats = base64.b64encode(stats)
		stats = stats.decode('utf-8')
		stats = '\n'.join(textwrap.wrap(stats, width=80))

		try:
			response = requests.post(
				'https://forms.hubspot.com/uploads/form/v2/147369/f374545b-987f-44ce-82e5-889293a0e6b3',
				data={
					'email': '*****@*****.**',
					'statistics': stats
				}
			)
			assert response.ok
		except (AssertionError, requests.exceptions.RequestException):
			self.logger.error('failed to submit data', exc_info=True)
			gui_utilities.show_dialog_error('Error Submitting Data', active_window, 'An Error occurred while submitting the data.')
			return
		gui_utilities.show_dialog_info('Submitted Data', active_window, 'Successfully submitted anonymized phishing data.\nThank you for your support!')
		self.config['last_date'] = datetime.datetime.utcnow()
コード例 #7
0
 def interact(self):
     self._highlight_campaign(self.config.get('campaign_name'))
     self.dialog.show_all()
     response = self.dialog.run()
     old_campaign_id = self.config.get('campaign_id')
     old_campaign_name = self.config.get('campaign_name')
     while response != Gtk.ResponseType.CANCEL:
         treeview = self.gobjects['treeview_campaigns']
         selection = treeview.get_selection()
         (model, tree_iter) = selection.get_selected()
         if tree_iter:
             break
         gui_utilities.show_dialog_error(
             'No Campaign Selected', self.dialog,
             'Either select a campaign or create a new one.')
         response = self.dialog.run()
     if response == Gtk.ResponseType.APPLY:
         campaign_id = model.get_value(tree_iter, 0)
         self.config['campaign_id'] = campaign_id
         campaign_name = model.get_value(tree_iter, 1)
         self.config['campaign_name'] = campaign_name
         if not (campaign_id == old_campaign_id
                 and campaign_name == old_campaign_name):
             self.application.emit('campaign-set', campaign_id)
     self.dialog.destroy()
     return response
コード例 #8
0
    def _queue_file_transfer(self, task_cls, src_path, dst_path):
        """
		Handles the file transfer by stopping bad transfers, creating tasks for
		transfers, and placing them in the queue.

		:param task_cls: The type of task the transfer will be.
		:param str src_path: The source path to be uploaded or downloaded.
		:param str dst_path: The destination path to be created and data transferred into.
		"""
        if issubclass(task_cls, tasks.DownloadTask):
            if not os.access(os.path.dirname(dst_path), os.W_OK):
                gui_utilities.show_dialog_error(
                    'Permission Denied', self.application.get_active_window(),
                    'Cannot write to the destination folder.')
                return
            local_path, remote_path = self.local.get_abspath(
                dst_path), self.remote.get_abspath(src_path)
        elif issubclass(task_cls, tasks.UploadTask):
            if not os.access(src_path, os.R_OK):
                gui_utilities.show_dialog_error(
                    'Permission Denied', self.application.get_active_window(),
                    'Cannot read the source file.')
                return
            local_path, remote_path = self.local.get_abspath(
                src_path), self.remote.get_abspath(dst_path)
        file_task = task_cls(local_path, remote_path)
        if isinstance(file_task, tasks.UploadTask):
            file_size = self.local.get_file_size(local_path)
        elif isinstance(file_task, tasks.DownloadTask):
            file_size = self.remote.get_file_size(remote_path)
        file_task.size = file_size
        self.queue.put(file_task)
        self.status_display.sync_view(file_task)
コード例 #9
0
	def make_preview(self, _):
		mailer_tab = self.application.main_tabs['mailer']
		config_tab = mailer_tab.tabs['config']
		config_tab.objects_save_to_config()
		input_path = self.application.config['mailer.attachment_file']
		if not (os.path.isfile(input_path) and os.access(input_path, os.R_OK)):
			gui_utilities.show_dialog_error(
				'PDF Build Error',
				self.application.get_active_window(),
				'Attachment path is invalid or is not readable.'
			)
			return

		dialog = extras.FileChooserDialog('Save Generated PDF File', self.application.get_active_window())
		response = dialog.run_quick_save('PDF Preview.pdf')
		dialog.destroy()
		if response is None:
			return

		output_path = response['target_path']
		if not self.process_attachment_file(input_path, output_path):
			return
		gui_utilities.show_dialog_info(
			'PDF Created',
			self.application.get_active_window(),
			'Successfully created the PDF file.'
		)
コード例 #10
0
    def prompt_and_generate(self):
        active_window = self.application.get_active_window()
        dialog_txt = 'Would you like to submit anonymized data to SecureState for research purposes?'
        if not gui_utilities.show_dialog_yes_no('Submit Phishing Data',
                                                active_window, dialog_txt):
            return

        get_stats = StatsGenerator(self.application.rpc)
        stats = get_stats.generate_stats()
        stats = stats.encode('utf-8')
        stats = bz2.compress(stats)
        stats = base64.b64encode(stats)
        stats = stats.decode('utf-8')
        stats = '\n'.join(textwrap.wrap(stats, width=80))

        try:
            response = requests.post(
                'https://forms.hubspot.com/uploads/form/v2/147369/f374545b-987f-44ce-82e5-889293a0e6b3',
                data={
                    'email': '*****@*****.**',
                    'statistics': stats
                })
            assert response.ok
        except (AssertionError, requests.exceptions.RequestException):
            self.logger.error('failed to submit data', exc_info=True)
            gui_utilities.show_dialog_error(
                'Error Submitting Data', active_window,
                'An Error occurred while submitting the data.')
            return
        gui_utilities.show_dialog_info(
            'Submitted Data', active_window,
            'Successfully submitted anonymized phishing data.\nThank you for your support!'
        )
        self.config['last_date'] = datetime.datetime.utcnow()
コード例 #11
0
 def interact(self):
     self._highlight_campaign(self.config.get('campaign_name'))
     self.dialog.show_all()
     response = self.dialog.run()
     old_campaign_id = self.config.get('campaign_id')
     while response != Gtk.ResponseType.CANCEL:
         treeview = self.gobjects['treeview_campaigns']
         selection = treeview.get_selection()
         (model, tree_iter) = selection.get_selected()
         if tree_iter:
             break
         gui_utilities.show_dialog_error(
             'No Campaign Selected', self.dialog,
             'Either select a campaign or create a new one.')
         response = self.dialog.run()
     if response == Gtk.ResponseType.APPLY:
         named_row = _ModelNamedRow(*model[tree_iter])
         if old_campaign_id is not None and named_row.id != str(
                 old_campaign_id):
             self.config['campaign_id'] = named_row.id
             self.config['campaign_name'] = named_row.name
             self.application.emit('campaign-set', old_campaign_id,
                                   named_row.id)
     self.dialog.destroy()
     return response
コード例 #12
0
	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
コード例 #13
0
 def signal_login_dialog_response(self, dialog, response):
     if response == Gtk.ResponseType.CANCEL or response == Gtk.ResponseType.DELETE_EVENT:
         dialog.destroy()
         self.application.emit('exit')
         return True
     self.login_dialog.objects_save_to_config()
     username = self.config['server_username']
     password = self.config['server_password']
     otp = self.config['server_one_time_password']
     if not otp:
         otp = None
     _, reason = self.application.server_connect(username, password, otp)
     if reason == ConnectionErrorReason.ERROR_INVALID_OTP:
         revealer = self.login_dialog.gobjects[
             'revealer_server_one_time_password']
         if revealer.get_child_revealed():
             gui_utilities.show_dialog_error(
                 'Login Failed', self,
                 'A valid one time password (OTP) token is required.')
         else:
             revealer.set_reveal_child(True)
         entry = self.login_dialog.gobjects[
             'entry_server_one_time_password']
         entry.grab_focus()
     elif reason == ConnectionErrorReason.ERROR_INVALID_CREDENTIALS:
         gui_utilities.show_dialog_error(
             'Login Failed', self,
             'The provided credentials are incorrect.')
コード例 #14
0
	def make_preview(self, _):
		input_path = self.application.config['mailer.attachment_file']
		if not os.path.isfile(input_path) and os.access(input_path, os.R_OK):
			gui_utilities.show_dialog_error(
				'PDF Build Error',
				self.application.get_active_window(),
				'An invalid attachment file is specified.'
			)
			return

		dialog = extras.FileChooserDialog('Save Generated PDF File', self.application.get_active_window())
		response = dialog.run_quick_save('preview.pdf')
		dialog.destroy()
		if response is None:
			return

		output_path = response['target_path']
		if not self.process_attachment_file(input_path, output_path):
			gui_utilities.show_dialog_error(
				'PDF Build Error',
				self.application.get_active_window(),
				'Failed to create the PDF file.'
			)
			return
		gui_utilities.show_dialog_info(
			'PDF Created',
			self.application.get_active_window(),
			'Successfully created the PDF file.'
		)
コード例 #15
0
	def signal_menu_activate_create_folder(self, _):
		selection = self.treeview.get_selection()
		model, treeiter = selection.get_selected()
		if treeiter:
			if not self.get_is_folder(model[treeiter][2]):
				logger.warning('cannot create a directory under a file')
				gui_utilities.show_dialog_error(
					'Plugin Error',
					self.application.get_active_window(),
					'Cannot create a directory under a file.'
				)
				return
		if treeiter is None:
			current = self._tv_model.append(treeiter, [' ', None, None, None, None, None, None])
			self.rename(current)
			return
		treeiter = self._treeiter_sort_to_model(treeiter)
		path = self._tv_model.get_path(treeiter)
		if not self.treeview.row_expanded(path):
			self.treeview.expand_row(path, False)
		if self._tv_model.iter_children(treeiter) is None:
			# If no children, one dummy node must be created to make row expandable and the other to be used as a placemark for new folder
			self._tv_model.append(treeiter, [None, None, None, None, None, None, None])
			current = self._tv_model.append(treeiter, [' ', None, None, None, None, None, None])
			self.treeview.expand_row(path, False)
		else:
			current = self._tv_model.append(treeiter, [' ', None, None, None, None, None, None])
		self.rename(current)
コード例 #16
0
	def _queue_file_transfer(self, task_cls, src_path, dst_path):
		"""
		Handles the file transfer by stopping bad transfers, creating tasks for
		transfers, and placing them in the queue.

		:param task_cls: The type of task the transfer will be.
		:param str src_path: The source path to be uploaded or downloaded.
		:param str dst_path: The destination path to be created and data transferred into.
		"""
		if issubclass(task_cls, tasks.DownloadTask):
			if not os.access(os.path.dirname(dst_path), os.W_OK):
				gui_utilities.show_dialog_error(
					'Permission Denied',
					self.application.get_active_window(),
					'Cannot write to the destination folder.'
				)
				return
			local_path, remote_path = self.local.get_abspath(dst_path), self.remote.get_abspath(src_path)
		elif issubclass(task_cls, tasks.UploadTask):
			if not os.access(src_path, os.R_OK):
				gui_utilities.show_dialog_error(
					'Permission Denied',
					self.application.get_active_window(),
					'Cannot read the source file.'
				)
				return
			local_path, remote_path = self.local.get_abspath(src_path), self.remote.get_abspath(dst_path)
		file_task = task_cls(local_path, remote_path)
		if isinstance(file_task, tasks.UploadTask):
			file_size = self.local.get_file_size(local_path)
		elif isinstance(file_task, tasks.DownloadTask):
			file_size = self.remote.get_file_size(remote_path)
		file_task.size = file_size
		self.queue.put(file_task)
		self.status_display.sync_view(file_task)
コード例 #17
0
	def initialize(self):
		self._color = None
		try:
			self._blink1 = blink1.Blink1()
			self._blink1_off()
		except usb.core.USBError as error:
			gui_utilities.show_dialog_error(
				'Connection Error',
				self.application.get_active_window(),
				'Unable to connect to the Blink(1) device.'
			)
			return False
		except blink1.BlinkConnectionFailed:
			gui_utilities.show_dialog_error(
				'Connection Error',
				self.application.get_active_window(),
				'Unable to find the Blink(1) device.'
			)
			return False
		self._gsrc_id = None
		if self.application.server_events is None:
			self.signal_connect('server-connected', lambda app: self._connect_server_events())
		else:
			self._connect_server_events()
		return True
コード例 #18
0
ファイル: extras.py プロジェクト: vysecurity/king-phisher
    def run_quick_save(self, current_name=None):
        """
		Display a dialog which asks the user where a file should be saved. The
		value of target_path in the returned dictionary is an absolute path.

		:param set current_name: The name of the file to save.
		:return: A dictionary with target_uri and target_path keys representing the path choosen.
		:rtype: dict
		"""
        self.set_action(Gtk.FileChooserAction.SAVE)
        self.add_button(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL)
        self.add_button(Gtk.STOCK_SAVE, Gtk.ResponseType.ACCEPT)
        self.set_do_overwrite_confirmation(True)
        if current_name:
            self.set_current_name(current_name)
        self.show_all()
        response = self.run()
        if response == Gtk.ResponseType.CANCEL:
            return None
        target_path = self.get_filename()
        if os.path.isfile(target_path):
            if not os.access(target_path, os.W_OK):
                gui_utilities.show_dialog_error(
                    'Can not write to the selected file', self.parent)
                return None
        elif not os.access(os.path.dirname(target_path), os.W_OK):
            gui_utilities.show_dialog_error('Can not create the selected file',
                                            self.parent)
            return None
        target_uri = self.get_uri()
        return {'target_uri': target_uri, 'target_path': target_path}
コード例 #19
0
 def signal_menu_activate_create_folder(self, _):
     selection = self.treeview.get_selection()
     model, treeiter = selection.get_selected()
     if treeiter:
         if not self.get_is_folder(model[treeiter][2]):
             logger.warning('cannot create a directory under a file')
             gui_utilities.show_dialog_error(
                 'Plugin Error', self.application.get_active_window(),
                 'Cannot create a directory under a file.')
             return
     if treeiter is None:
         current = self._tv_model.append(
             treeiter, [' ', None, None, None, None, None, None])
         self.rename(current)
         return
     treeiter = self._treeiter_sort_to_model(treeiter)
     path = self._tv_model.get_path(treeiter)
     if not self.treeview.row_expanded(path):
         self.treeview.expand_row(path, False)
     if self._tv_model.iter_children(treeiter) is None:
         # If no children, one dummy node must be created to make row expandable and the other to be used as a placemark for new folder
         self._tv_model.append(treeiter,
                               [None, None, None, None, None, None, None])
         current = self._tv_model.append(
             treeiter, [' ', None, None, None, None, None, None])
         self.treeview.expand_row(path, False)
     else:
         current = self._tv_model.append(
             treeiter, [' ', None, None, None, None, None, None])
     self.rename(current)
コード例 #20
0
 def interact(self):
     self._highlight_campaign(self.config.get('campaign_name'))
     self.dialog.show_all()
     response = self.dialog.run()
     old_campaign_id = self.config.get('campaign_id')
     old_campaign_name = self.config.get('campaign_name')
     while response != Gtk.ResponseType.CANCEL:
         treeview = self.gobjects['treeview_campaigns']
         selection = treeview.get_selection()
         (model, tree_iter) = selection.get_selected()
         if tree_iter:
             break
         gui_utilities.show_dialog_error(
             'No Campaign Selected', self.dialog,
             'Either select a campaign or create a new one.')
         response = self.dialog.run()
     if response == Gtk.ResponseType.APPLY:
         campaign_id = model.get_value(tree_iter, 0)
         self.config['campaign_id'] = campaign_id
         campaign_name = model.get_value(tree_iter, 1)
         self.config['campaign_name'] = campaign_name
         if not (campaign_id == old_campaign_id
                 and campaign_name == old_campaign_name):
             self.application.emit('campaign-set', campaign_id)
     self.dialog.destroy()
     return response
コード例 #21
0
	def stop_remote_service(self):
		if not gui_utilities.show_dialog_yes_no('Stop The Remote King Phisher Service?', self, 'This will stop the remote King Phisher service and\nnew incoming requests will not be processed.'):
			return
		self.rpc('shutdown')
		self.logger.info('the remote king phisher service has been stopped')
		gui_utilities.show_dialog_error('The Remote Service Has Been Stopped', self, 'Now exiting')
		self.client_quit()
		return
コード例 #22
0
	def sender_start_failure(self, message=None, text=None):
		if text:
			self.text_insert(text)
		self.gobjects['button_mail_sender_stop'].set_sensitive(False)
		self.gobjects['button_mail_sender_start'].set_sensitive(True)
		if message:
			gui_utilities.show_dialog_error(message, self.parent)
		self.sender_thread = None
コード例 #23
0
	def _plugin_enable(self, model_row):
		named_row = _ModelNamedRow(*model_row)
		pm = self.application.plugin_manager
		if not pm.loaded_plugins[named_row.id].is_compatible:
			gui_utilities.show_dialog_error('Incompatible Plugin', self.window, 'This plugin is not compatible.')
			return
		if not pm.enable(named_row.id):
			return
		self._set_model_item(model_row.path, 'enabled', True)
		self.config['plugins.enabled'].append(named_row.id)
コード例 #24
0
	def change_cwd(self, new_dir):
		"""
		Changes current working directory to given parameter.

		:param str new_dir: The directory to change the CWD to.
		:return: The absolute path of the new working directory if it was changed.
		:rtype: str
		"""
		if not self.path_mod.isabs(new_dir):
			new_dir = self.get_abspath(new_dir)
		if new_dir == self.cwd:
			return
		logger.debug("{} is trying to change current working directory to {}".format(self.location, new_dir))
		try:
			self._chdir(new_dir)
		except OSError:
			logger.warning("user does not have permissions to read {}".format(new_dir))
			gui_utilities.show_dialog_error(
				'Plugin Error',
				self.application.get_active_window(),
				"You do not have permissions to access {}.".format(new_dir)
			)
			return

		self._tv_model.clear()
		try:
			self.load_dirs(new_dir)
		except OSError:
			logger.warning("user does not have permissions to read {}".format(new_dir))
			if self.cwd:
				self.load_dirs(self.cwd)
				gui_utilities.show_dialog_error(
					'Plugin Error',
					self.application.get_active_window(),
					"You do not have permissions to access {}.".format(new_dir)
				)
			else:
				logger.warning(self.location + " has no current working directory, using the root directory")
				self.default_directory = self.root_directory
				self.change_cwd(self.default_directory)
			return

		self.cwd = new_dir
		# clear and rebuild the model
		self._wdcb_model.clear()
		self._wdcb_model.append((self.root_directory,))
		if self.default_directory != self.root_directory:
			self._wdcb_model.append((self.default_directory,))
		if new_dir not in self.wd_history and gui_utilities.gtk_list_store_search(self._wdcb_model, new_dir) is None:
			self.wd_history.appendleft(new_dir)
		for directory in self.wd_history:
			self._wdcb_model.append((directory,))
		active_iter = gui_utilities.gtk_list_store_search(self._wdcb_model, new_dir)
		self.wdcb_dropdown.set_active_iter(active_iter)
		return new_dir
コード例 #25
0
ファイル: campaign.py プロジェクト: xy-sec/king-phisher
 def __async_rpc_cb_issue_cert_error(self, error, message=None):
     self._set_page_complete(True, page='Web Server URL')
     self.gobjects['button_url_ssl_issue_certificate'].set_sensitive(True)
     _set_icon(self.gobjects['image_url_ssl_status'], 'gtk-dialog-warning')
     label = self.gobjects['label_url_ssl_status']
     label.set_text(
         'An error occurred while requesting a certificate for the specified hostname'
     )
     gui_utilities.show_dialog_error(
         'Operation Error', self.application.get_active_window(), message
         or "Unknown error: {!r}".format(error))
コード例 #26
0
ファイル: plugin_manager.py プロジェクト: qsdj/king-phisher
 def _plugin_enable(self, model_row):
     named_row = _ModelNamedRow(*model_row)
     pm = self.application.plugin_manager
     if not pm.loaded_plugins[named_row.id].is_compatible:
         gui_utilities.show_dialog_error('Incompatible Plugin', self.window,
                                         'This plugin is not compatible.')
         return
     if not pm.enable(named_row.id):
         return
     self._set_model_item(model_row.path, 'enabled', True)
     self.config['plugins.enabled'].append(named_row.id)
コード例 #27
0
 def signal_menu_activate_set_working_directory(self, _):
     model, treeiter = self.treeview.get_selection().get_selected()
     if not treeiter:
         return
     if not self.get_is_folder(model[treeiter][2]):
         logger.warning('cannot set a file as an active working directory')
         gui_utilities.show_dialog_error(
             'Plugin Error', self.application.get_active_window(),
             'Cannot set a file the working directory.')
         return
     self.change_cwd(model[treeiter][2])
コード例 #28
0
ファイル: mail.py プロジェクト: collin123/king-phisher
    def import_message_data(self):
        """
		Process a previously exported message archive file and restore the
		message data, settings, and applicable files from it.
		"""
        config_tab = self.tabs.get("config")
        if not config_tab:
            self.logger.warning("attempted to import message data while the config tab was unavailable")
            return
        config_prefix = config_tab.config_prefix
        config_tab.objects_save_to_config()
        dialog = extras.FileChooserDialog("Import Message Configuration", self.parent)
        dialog.quick_add_filter("King Phisher Message Files", "*.kpm")
        dialog.quick_add_filter("All Files", "*")
        response = dialog.run_quick_open()
        dialog.destroy()
        if not response:
            return
        target_file = response["target_path"]

        dialog = extras.FileChooserDialog("Destination Directory", self.parent)
        response = dialog.run_quick_select_directory()
        dialog.destroy()
        if not response:
            return
        dest_dir = response["target_path"]
        try:
            message_data = export.message_data_from_kpm(target_file, dest_dir)
        except KingPhisherInputValidationError as error:
            gui_utilities.show_dialog_error("Import Error", self.parent, error.message.capitalize() + ".")
            return

        config_keys = set(key for key in self.config.keys() if key.startswith(config_prefix))
        config_types = dict(zip(config_keys, [type(self.config[key]) for key in config_keys]))
        for key, value in message_data.items():
            key = config_prefix + key
            if not key in config_keys:
                continue
            self.config[key] = value
            config_keys.remove(key)
        for unset_key in config_keys:
            config_type = config_types[unset_key]
            if not config_type in (bool, dict, int, list, str, tuple):
                continue
            self.config[unset_key] = config_type()

            # set missing defaults for backwards compatibility
        if not self.config.get("mailer.message_type"):
            self.config["mailer.message_type"] = "email"
        if not self.config.get("mailer.target_type"):
            self.config["mailer.target_type"] = "file"

        config_tab.objects_load_from_config()
        gui_utilities.show_dialog_info("Success", self.parent, "Successfully imported the message.")
コード例 #29
0
 def wrapper(self, *args, **kwargs):
     try:
         function(self, *args, **kwargs)
     except (IOError, OSError) as error:
         logger.error('an exception occurred during an operation',
                      exc_info=True)
         err_message = "An error occured: {0}".format(error)
         gui_utilities.show_dialog_error(
             'Error', self.application.get_active_window(), err_message)
         return False
     return True
コード例 #30
0
	def do_campaign_delete(self, campaign_id):
		"""
		Delete the campaign on the server. A confirmation dialog will be
		displayed before the operation is performed. If the campaign is deleted
		and a new campaign is not selected with
		:py:meth:`.show_campaign_selection`, the client will quit.
		"""
		self.rpc('db/table/delete', 'campaigns', campaign_id)
		if campaign_id == self.config['campaign_id'] and not self.show_campaign_selection():
			gui_utilities.show_dialog_error('Now Exiting', self.get_active_window(), 'A campaign must be selected.')
			self.quit()
コード例 #31
0
	def do_campaign_delete(self, campaign_id):
		"""
		Delete the campaign on the server. A confirmation dialog will be
		displayed before the operation is performed. If the campaign is deleted
		and a new campaign is not selected with
		:py:meth:`.show_campaign_selection`, the client will quit.
		"""
		self.rpc('db/table/delete', 'campaigns', campaign_id)
		if campaign_id == self.config['campaign_id'] and not self.show_campaign_selection():
			gui_utilities.show_dialog_error('Now Exiting', self.get_active_window(), 'A campaign must be selected.')
			self.quit()
コード例 #32
0
    def import_message_data(self):
        """
		Process a previously exported message archive file and restore the
		message data, settings, and applicable files from it.
		"""
        config_tab = self.tabs.get('config')
        if not config_tab:
            self.logger.warning(
                'attempted to import message data while the config tab was unavailable'
            )
            return
        config_prefix = config_tab.config_prefix
        config_tab.objects_save_to_config()
        dialog = gui_utilities.UtilityFileChooser(
            'Import Message Configuration', self.parent)
        dialog.quick_add_filter('King Phisher Message Files', '*.kpm')
        dialog.quick_add_filter('All Files', '*')
        response = dialog.run_quick_open()
        dialog.destroy()
        if not response:
            return
        target_file = response['target_path']

        dialog = gui_utilities.UtilityFileChooser('Destination Directory',
                                                  self.parent)
        response = dialog.run_quick_select_directory()
        dialog.destroy()
        if not response:
            return
        dest_dir = response['target_path']
        try:
            message_data = export.message_data_from_kpm(target_file, dest_dir)
        except KingPhisherInputValidationError as error:
            gui_utilities.show_dialog_error('Import Error', self.parent,
                                            error.message.capitalize() + '.')
            return

        config_keys = set(
            filter(lambda k: k.startswith(config_prefix), self.config.keys()))
        config_types = dict(zip(config_keys, map(type, config_keys)))
        for key, value in message_data.items():
            key = config_prefix + key
            if not key in config_keys:
                continue
            self.config[key] = value
            config_keys.remove(key)
        for unset_key in config_keys:
            config_type = config_types[unset_key]
            if not config_type in (bool, dict, int, list, str, tuple):
                continue
            self.config[unset_key] = config_type()
        config_tab.objects_load_from_config()
        gui_utilities.show_dialog_info('Successfully imported the message',
                                       self.parent)
コード例 #33
0
	def signal_popup_menu_activate_update(self, _):
		model_row = self._selected_model_row
		named_row = None if model_row is None else _ModelNamedRow(*model_row)
		if named_row is None:
			return
		if not (named_row.type == _ROW_TYPE_PLUGIN and named_row.installed and named_row.sensitive_installed):
			return
		if not self._plugin_uninstall(model_row):
			gui_utilities.show_dialog_error('Update Failed', self.window, 'Failed to uninstall the existing plugin data.')
			return
		self._plugin_install(model_row)
コード例 #34
0
ファイル: tag_editor.py プロジェクト: piratica/king-phisher
	def signal_renderer_edited(self, cell, path, property_value, details):
		tag_table, store_id, property_name = details
		model = self.gobjects['treeview_' + tag_table].get_model()
		model_iter = model.get_iter(path)
		tag_id = model.get_value(model_iter, 0)

		try:
			self.application.rpc('db/table/set', tag_table, tag_id, (property_name,), (property_value,))
		except AdvancedHTTPServer.AdvancedHTTPServerRPCError:
			gui_utilities.show_dialog_error('Failed To Modify', self.dialog, 'An error occurred while modifying the information.')
		else:
			model.set_value(model_iter, store_id, property_value)
コード例 #35
0
	def __init__(self, config, parent):
		self.config = config
		self.parent = parent
		self.logger = logging.getLogger('KingPhisher.Client.' + self.__class__.__name__)
		if not has_vte:
			gui_utilities.show_dialog_error('RPC terminal is unavailable', parent, 'VTE is not installed')
			return
		self.window = Gtk.Window()
		self.window.set_property('title', 'King Phisher RPC')
		self.window.set_transient_for(parent)
		self.window.set_destroy_with_parent(True)
		self.window.connect('destroy', self.signal_window_destroy)
		self.terminal = Vte.Terminal()
		self.terminal.set_scroll_on_keystroke(True)
		vbox = Gtk.VBox()
		self.window.add(vbox)
		vbox.pack_end(self.terminal, True, True, 0)

		action_group = Gtk.ActionGroup("rpc_terminal_window_actions")
		self._add_menu_actions(action_group)
		uimanager = self._create_ui_manager()
		uimanager.insert_action_group(action_group)
		menubar = uimanager.get_widget("/MenuBar")
		vbox.pack_start(menubar, False, False, 0)

		rpc = self.parent.rpc
		config = {}
		config['campaign_id'] = self.config['campaign_id']
		config['campaign_name'] = self.config['campaign_name']
		config['rpc_data'] = {
			'address': (rpc.host, rpc.port),
			'use_ssl': rpc.use_ssl,
			'username': rpc.username,
			'uri_base': rpc.uri_base,
			'hmac_key': rpc.hmac_key,
		}
		config = json.dumps(config)
		argv = []
		argv.append(utilities.which('python'))
		argv.append('-c')
		argv.append("import {0}; {0}.{1}.child_routine('{2}')".format(self.__module__, self.__class__.__name__, config))
		_, child_pid = self.terminal.fork_command_full(Vte.PtyFlags.DEFAULT, os.getcwd(), argv, None, GLib.SpawnFlags.DEFAULT, None, None)
		self.logger.info("vte spawned child process with pid: {0}".format(child_pid))
		self.child_pid = child_pid
		self.terminal.connect('child-exited', lambda vt: self.window.destroy())
		self.window.show_all()

		# Automatically enter the password
		vte_pty = self.terminal.get_pty_object()
		vte_pty_fd = vte_pty.get_fd()
		if len(select.select([vte_pty_fd], [], [], 0.5)[0]):
			os.write(vte_pty_fd, rpc.password + '\n')
		return
コード例 #36
0
	def campaign_delete(self):
		"""
		Delete the campaign on the server. A confirmation dialog will be
		displayed before the operation is performed. If the campaign is
		deleted and a new campaign is not selected with
		:py:meth:`.show_campaign_selection`, the client will quit.
		"""
		if not gui_utilities.show_dialog_yes_no('Delete This Campaign?', self.get_active_window(), 'This action is irreversible, all campaign data will be lost.'):
			return
		self.rpc('db/table/delete', 'campaigns', self.config['campaign_id'])
		if not self.show_campaign_selection():
			gui_utilities.show_dialog_error('Now Exiting', self.get_active_window(), 'A campaign must be selected.')
			self.quit()
コード例 #37
0
	def initialize(self):
		if not os.access(gtk_builder_file, os.R_OK):
			gui_utilities.show_dialog_error(
				'Plugin Error',
				self.application.get_active_window(),
				"The GTK Builder data file ({0}) is not available.".format(os.path.basename(gtk_builder_file))
			)
			return False
		self.menu_items = {}
		self.add_submenu('Tools > TOTP Self Enrollment')
		self.menu_items['setup'] = self.add_menu_item('Tools > TOTP Self Enrollment > Setup', self.enrollment_setup)
		self.menu_items['remove'] = self.add_menu_item('Tools > TOTP Self Enrollment > Remove', self.enrollment_remove)
		return True
コード例 #38
0
	def signal_menu_activate_set_working_directory(self, _):
		model, treeiter = self.treeview.get_selection().get_selected()
		if not treeiter:
			return
		if not self.get_is_folder(model[treeiter][2]):
			logger.warning('cannot set a file as an active working directory')
			gui_utilities.show_dialog_error(
				'Plugin Error',
				self.application.get_active_window(),
				'Cannot set a file the working directory.'
			)
			return
		self.change_cwd(model[treeiter][2])
コード例 #39
0
	def expand_path(self, output_file, *args, **kwargs):
		expanded_path = _expand_path(output_file, *args, **kwargs)
		try:
			expanded_path = mailer.render_message_template(expanded_path, self.application.config)
		except jinja2.exceptions.TemplateSyntaxError as error:
			self.logger.error("jinja2 syntax error ({0}) in directory: {1}".format(error.message, output_file))
			gui_utilities.show_dialog_error('Error', self.application.get_active_window(), 'Error creating the HTML file.')
			return None
		except ValueError as error:
			self.logger.error("value error ({0}) in directory: {1}".format(error, output_file))
			gui_utilities.show_dialog_error('Error', self.application.get_active_window(), 'Error creating the HTML file.')
			return None
		return expanded_path
コード例 #40
0
	def wrapper(self, *args, **kwargs):
		try:
			function(self, *args, **kwargs)
		except (IOError, OSError) as error:
			logger.error('an exception occurred during an operation', exc_info=True)
			err_message = "An error occured: {0}".format(error)
			gui_utilities.show_dialog_error(
				'Error',
				self.application.get_active_window(),
				err_message
			)
			return False
		return True
コード例 #41
0
	def expand_path(self, output_file, *args, **kwargs):
		expanded_path = _expand_path(output_file, *args, **kwargs)
		try:
			expanded_path = mailer.render_message_template(expanded_path, self.application.config)
		except jinja2.exceptions.TemplateSyntaxError as error:
			self.logger.error("jinja2 syntax error ({0}) in directory: {1}".format(error.message, output_file))
			gui_utilities.show_dialog_error('Error', self.application.get_active_window(), 'Error creating the HTML file.')
			return None
		except ValueError as error:
			self.logger.error("value error ({0}) in directory: {1}".format(error, output_file))
			gui_utilities.show_dialog_error('Error', self.application.get_active_window(), 'Error creating the HTML file.')
			return None
		return expanded_path
コード例 #42
0
	def initialize(self):
		if not os.access(gtk_builder_file, os.R_OK):
			gui_utilities.show_dialog_error(
				'Plugin Error',
				self.application.get_active_window(),
				"The GTK Builder data file ({0}) is not available.".format(os.path.basename(gtk_builder_file))
			)
			return False
		self.menu_items = {}
		self.add_submenu('Tools > TOTP Self Enrollment')
		self.menu_items['setup'] = self.add_menu_item('Tools > TOTP Self Enrollment > Setup', self.enrollment_setup)
		self.menu_items['remove'] = self.add_menu_item('Tools > TOTP Self Enrollment > Remove', self.enrollment_remove)
		return True
コード例 #43
0
ファイル: plugin_manager.py プロジェクト: qsdj/king-phisher
 def signal_popup_menu_activate_update(self, _):
     model_row = self._selected_model_row
     named_row = None if model_row is None else _ModelNamedRow(*model_row)
     if named_row is None:
         return
     if not (named_row.type == _ROW_TYPE_PLUGIN and named_row.installed
             and named_row.sensitive_installed):
         return
     if not self._plugin_uninstall(model_row):
         gui_utilities.show_dialog_error(
             'Update Failed', self.window,
             'Failed to uninstall the existing plugin data.')
         return
     self._plugin_install(model_row)
コード例 #44
0
	def signal_button_clicked(self, button):
		campaign_name_entry = self.gobjects['entry_new_campaign_name']
		campaign_name = campaign_name_entry.get_property('text')
		if not campaign_name:
			gui_utilities.show_dialog_warning('Invalid Campaign Name', self.dialog, 'Please specify a new campaign name')
			return
		try:
			self.parent.rpc('campaign/new', campaign_name)
		except AdvancedHTTPServer.AdvancedHTTPServerRPCError:
			gui_utilities.show_dialog_error('Failed To Create New Campaign', self.dialog, 'Encountered an error creating the new campaign')
			return
		campaign_name_entry.set_property('text', '')
		self.load_campaigns()
		self._highlight_campaign(campaign_name)
コード例 #45
0
ファイル: application.py プロジェクト: superf0sh/king-phisher
    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
コード例 #46
0
	def signal_button_clicked(self, button):
		campaign_name_entry = self.gobjects['entry_new_campaign_name']
		campaign_name = campaign_name_entry.get_property('text')
		if not campaign_name:
			gui_utilities.show_dialog_warning('Invalid Campaign Name', self.dialog, 'Please specify a new campaign name')
			return
		try:
			self.parent.rpc('campaign/new', campaign_name)
		except:
			gui_utilities.show_dialog_error('Failed To Create New Campaign', self.dialog, 'Encountered an error creating the new campaign')
			return
		campaign_name_entry.set_property('text', '')
		self.load_campaigns()
		self._highlight_campaign(campaign_name)
コード例 #47
0
	def signal_menuitem_activate_import_config(self, _):
		dialog = extras.FileChooserDialog('Import Configuration File', self.dialog)
		response = dialog.run_quick_open()
		dialog.destroy()
		if response is None:
			return
		config_path = response['target_path']
		try:
			self.application.merge_config(config_path, strict=False)
		except Exception:
			self.logger.warning('failed to merge configuration file: ' + config_path, exc_info=True)
			gui_utilities.show_dialog_error('Invalid Configuration File', self.dialog, 'Could not import the configuration file.')
		else:
			self.objects_load_from_config()
コード例 #48
0
	def stop_remote_service(self):
		"""
		Stop the remote King Phisher server. This will request that the
		server stop processing new requests and exit. This will display
		a confirmation dialog before performing the operation. If the
		remote service is stopped, the client will quit.
		"""
		if not gui_utilities.show_dialog_yes_no('Stop The Remote King Phisher Service?', self.get_active_window(), 'This will stop the remote King Phisher service and\nnew incoming requests will not be processed.'):
			return
		self.rpc('shutdown')
		self.logger.info('the remote king phisher service has been stopped')
		gui_utilities.show_dialog_error('Now Exiting', self.get_active_window(), 'The remote service has been stopped.')
		self.quit()
		return
コード例 #49
0
	def interact(self):
		self.dialog.show_all()
		self.set_status('Waiting')
		if not web_cloner.has_webkit2:
			gui_utilities.show_dialog_error('WebKit2GTK+ Is Unavailable', self.dialog, 'The WebKit2GTK+ package is not available.')
			self.dialog.destroy()
			return
		while self.dialog.run() == Gtk.ResponseType.APPLY:
			target_url = self.entry_target.get_text()
			if not target_url:
				gui_utilities.show_dialog_error('Missing Information', self.dialog, 'Please set the target URL.')
				self.set_status('Missing Information')
				continue
			dest_dir = self.entry_directory.get_text()
			if not dest_dir:
				gui_utilities.show_dialog_error('Missing Information', self.dialog, 'Please set the destination directory.')
				self.set_status('Missing Information')
				continue
			if not os.access(dest_dir, os.W_OK):
				gui_utilities.show_dialog_error('Invalid Directory', self.dialog, 'Can not write to the specified directory.')
				self.set_status('Invalid Directory')
				continue
			self.objects_save_to_config()

			self.set_status('Cloning', spinner_active=True)
			cloner = web_cloner.WebPageCloner(target_url, dest_dir)
			signal_id = self.button_cancel.connect('clicked', lambda _: cloner.stop_cloning())
			original_label = self.button_cancel.get_label()
			self.button_cancel.set_label('Cancel')
			cloner.wait()
			self.button_cancel.set_label(original_label)
			self.button_cancel.disconnect(signal_id)

			if cloner.load_failed:
				self.set_status('Failed')
				gui_utilities.show_dialog_error('Operation Failed', self.dialog, 'The web page clone operation failed.')
				continue
			for resource in cloner.cloned_resources.values():
				if gui_utilities.gtk_list_store_search(self.resources, resource.resource, column=0):
					continue
				self.resources.append(_ModelNamedRow(
					path=resource.resource,
					mime_type=resource.mime_type or 'N/A',
					size=resource.size
				))
			self.set_status('Done')
			gui_utilities.gtk_sync()
		if len(self.resources) and gui_utilities.show_dialog_yes_no('Transfer Cloned Pages', self.dialog, 'Would you like to start the SFTP client\nto upload the cloned pages?'):
			self.application.emit('sftp-client-start')
		self.dialog.destroy()
コード例 #50
0
ファイル: login.py プロジェクト: fo0nikens/king-phisher
	def signal_menuitem_activate_import_config(self, _):
		dialog = extras.FileChooserDialog('Import Configuration File', self.dialog)
		response = dialog.run_quick_open()
		dialog.destroy()
		if response is None:
			return
		config_path = response['target_path']
		try:
			self.application.merge_config(config_path, strict=False)
		except Exception:
			self.logger.warning('failed to merge configuration file: ' + config_path, exc_info=True)
			gui_utilities.show_dialog_error('Invalid Configuration File', self.dialog, 'Could not import the configuration file.')
		else:
			self.objects_load_from_config()
コード例 #51
0
	def stop_remote_service(self):
		"""
		Stop the remote King Phisher server. This will request that the
		server stop processing new requests and exit. This will display
		a confirmation dialog before performing the operation. If the
		remote service is stopped, the client will quit.
		"""
		active_window = self.get_active_window()
		if not gui_utilities.show_dialog_yes_no('Stop The Remote King Phisher Service?', active_window, 'This will stop the remote King Phisher service and\nnew incoming requests will not be processed.'):
			return
		self.rpc('shutdown')
		self.logger.info('the remote king phisher service has been stopped')
		gui_utilities.show_dialog_error('Now Exiting', active_window, 'The remote service has been stopped.')
		self.quit()
		return
コード例 #52
0
	def signal_renderer_toggled_enable(self, _, path):
		model_row = self._model[path]
		named_row = _ModelNamedRow(*model_row)
		if named_row.type != _ROW_TYPE_PLUGIN:
			return
		if named_row.id not in self.application.plugin_manager.loaded_plugins:
			return

		if named_row.id in self.__load_errors:
			gui_utilities.show_dialog_error('Can Not Enable Plugin', self.window, 'Can not enable a plugin which failed to load.')
			return
		if named_row.enabled:
			self._plugin_disable(model_row)
		else:
			self._plugin_enable(model_row)
コード例 #53
0
ファイル: tag_editor.py プロジェクト: piratica/king-phisher
    def signal_renderer_edited(self, cell, path, property_value, details):
        tag_table, store_id, property_name = details
        model = self.gobjects['treeview_' + tag_table].get_model()
        model_iter = model.get_iter(path)
        tag_id = model.get_value(model_iter, 0)

        try:
            self.application.rpc('db/table/set', tag_table, tag_id,
                                 (property_name, ), (property_value, ))
        except AdvancedHTTPServer.AdvancedHTTPServerRPCError:
            gui_utilities.show_dialog_error(
                'Failed To Modify', self.dialog,
                'An error occurred while modifying the information.')
        else:
            model.set_value(model_iter, store_id, property_value)
コード例 #54
0
ファイル: mail.py プロジェクト: coldfusion39/king-phisher
	def import_message_data(self):
		"""
		Process a previously exported message archive file and restore the
		message data, settings, and applicable files from it.
		"""
		config_tab = self.tabs.get('config')
		if not config_tab:
			self.logger.warning('attempted to import message data while the config tab was unavailable')
			return
		config_prefix = config_tab.config_prefix
		config_tab.objects_save_to_config()
		dialog = gui_utilities.FileChooser('Import Message Configuration', self.parent)
		dialog.quick_add_filter('King Phisher Message Files', '*.kpm')
		dialog.quick_add_filter('All Files', '*')
		response = dialog.run_quick_open()
		dialog.destroy()
		if not response:
			return
		target_file = response['target_path']

		dialog = gui_utilities.FileChooser('Destination Directory', self.parent)
		response = dialog.run_quick_select_directory()
		dialog.destroy()
		if not response:
			return
		dest_dir = response['target_path']
		try:
			message_data = export.message_data_from_kpm(target_file, dest_dir)
		except KingPhisherInputValidationError as error:
			gui_utilities.show_dialog_error('Import Error', self.parent, error.message.capitalize() + '.')
			return

		config_keys = set(key for key in self.config.keys() if key.startswith(config_prefix))
		config_types = dict(zip(config_keys, map(type, config_keys)))
		for key, value in message_data.items():
			key = config_prefix + key
			if not key in config_keys:
				continue
			self.config[key] = value
			config_keys.remove(key)
		for unset_key in config_keys:
			config_type = config_types[unset_key]
			if not config_type in (bool, dict, int, list, str, tuple):
				continue
			self.config[unset_key] = config_type()
		config_tab.objects_load_from_config()
		gui_utilities.show_dialog_info('Success', self.parent, 'Successfully imported the message.')
コード例 #55
0
    def delete_campaign(self):
        """
		Delete the campaign on the server. A confirmation dialog will be
		displayed before the operation is performed. If the campaign is
		deleted and a new campaign is not selected with
		:py:meth:`.show_campaign_selection`, the client will quit.
		"""
        if not gui_utilities.show_dialog_yes_no(
                'Delete This Campaign?', self,
                'This action is irreversible, all campaign data will be lost.'
        ):
            return
        self.rpc('campaign/delete', self.config['campaign_id'])
        if not self.show_campaign_selection():
            gui_utilities.show_dialog_error('Now Exiting', self,
                                            'A campaign must be selected.')
            self.client_quit()
コード例 #56
0
ファイル: plugin_manager.py プロジェクト: qsdj/king-phisher
    def signal_renderer_toggled_enable(self, _, path):
        model_row = self._model[path]
        named_row = _ModelNamedRow(*model_row)
        if named_row.type != _ROW_TYPE_PLUGIN:
            return
        if named_row.id not in self.application.plugin_manager.loaded_plugins:
            return

        if named_row.id in self.__load_errors:
            gui_utilities.show_dialog_error(
                'Can Not Enable Plugin', self.window,
                'Can not enable a plugin which failed to load.')
            return
        if named_row.enabled:
            self._plugin_disable(model_row)
        else:
            self._plugin_enable(model_row)
コード例 #57
0
    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
コード例 #58
0
 def initialize(self):
     """Connects to the start SFTP Client Signal to the plugin and checks for .ui file."""
     self.sftp_window = None
     if not os.access(sftp_utilities.gtk_builder_file, os.R_OK):
         gui_utilities.show_dialog_error(
             'Plugin Error', self.application.get_active_window(),
             "The GTK Builder data file ({0}) is not available.".format(
                 os.path.basename(sftp_utilities.gtk_builder_file)))
         return False
     if 'directories' not in self.config:
         self.config['directories'] = {}
     if 'transfer_hidden' not in self.config:
         self.config['transfer_hidden'] = False
     if 'show_hidden' not in self.config:
         self.config['show_hidden'] = False
     self.signal_connect('sftp-client-start', self.signal_sftp_start)
     return True
コード例 #59
0
	def signal_renderer_toggled(self, _, path):
		pm = self.application.plugin_manager
		name = self._model[path][0]  # pylint: disable=unsubscriptable-object
		if name in self._module_errors:
			gui_utilities.show_dialog_error('Can Not Enable Plugin', self.window, 'Can not enable a plugin which failed to load.')
			return
		if self._model[path][1]:  # pylint: disable=unsubscriptable-object
			pm.disable(name)
			self._model[path][1] = False # pylint: disable=unsubscriptable-object
			self.config['plugins.enabled'].remove(name)
		else:
			if not pm.loaded_plugins[name].is_compatible:
				gui_utilities.show_dialog_error('Incompatible Plugin', self.window, 'This plugin is not compatible.')
				return
			if not pm.enable(name):
				return
			self._model[path][1] = True # pylint: disable=unsubscriptable-object
			self.config['plugins.enabled'].append(name)