# Copyright (C) 2005 Insecure.Com LLC. # # Author: Adriano Monteiro Marques # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA import gtk import gobject import re from higwidgets.hignotebooks import HIGNotebook, HIGAnimatedTabLabel from higwidgets.higboxes import HIGVBox from higwidgets.higdialogs import HIGAlertDialog, HIGDialog from higwidgets.higscrollers import HIGScrolledWindow from umitGUI.NmapOutputViewer import NmapOutputViewer from umitGUI.ScanHostDetailsPage import ScanHostDetailsPage from umitGUI.ScanToolbar import ScanCommandToolbar, ScanToolbar from umitGUI.ScanHostsView import ScanHostsView from umitGUI.ScanOpenPortsPage import ScanOpenPortsPage from umitGUI.ScanRunDetailsPage import ScanRunDetailsPage from umitGUI.ScanNmapOutputPage import ScanNmapOutputPage from umitGUI.Icons import get_os_icon, get_os_logo, get_vulnerability_logo from umitCore.NmapCommand import NmapCommand from umitCore.NmapCommand import CommandConstructor from umitCore.UmitConf import CommandProfile, ProfileNotFound from umitCore.NmapParser import NmapParser from umitCore.Paths import Path from umitCore.Logging import log from umitCore.I18N import _ icon_dir = Path.get_pixmaps_dir() class PageStatus(object): """ Pages status: The page status can be one of the following: * saved: there is nothing to be saved in the current scan tab * unsaved_unchanged: for recently scanned results that were parsed and is unchanged. * unsaved_changed: for recently scanned results that were parsed and got some changes on its contents (like a comment) * loaded_unchanged: for scan results that were loaded from a file and got no modifications * loaded_changed: for scan results that were loaded from a file and got some modifications (like comments) * parsing_result: the result is been parsed to be displayed at the tab * scanning: there is no parsed result related to this tab, but there is a related scan running to show results on that tab * empty: there is nothing related to this tab. His widgets are disabled and this is the initial state of a new tab * unknown: the page status is unknown * scan_failed: the scan has failed * search_loaded: the scan was loaded from a search result """ def __init__(self, status=False): if status: self.status = status else: self.set_unknown() def set_empty(self): self._status = "empty" def set_saved(self): self._status = "saved" def set_unsaved_unchanged(self): self._status = "unsaved_unchanged" def set_unsaved_changed(self): self._status = "unsaved_changed" def set_loaded_unchanged(self): self._status = "loaded_unchanged" def set_loaded_changed(self): self._status = "loaded_changed" def set_parsing_result(self): self._status = "parsing_result" def set_scanning(self): self._status = "scanning" def set_unknown(self): self._status = "unknown" def set_scan_failed(self): self._status = "scan_failed" def set_search_loaded(self): self._status = "search_loaded" def get_status(self): return self._status def set_status(self, status): if status in self.available_status: self._status = status else: raise Exception("Unknown status!") def _verify_status(self, status): if self._status == status: return True return False def get_unsaved_unchanged(self): return self._verify_status("unsaved_unchanged") def get_unsaved_changed(self): return self._verify_status("unsaved_changed") def get_loaded_unchanged(self): return self._verify_status("loaded_unchanged") def get_loaded_changed(self): return self._verify_status("loaded_changed") def get_parsing_result(self): return self._verify_status("parsing_result") def get_scanning(self): return self._verify_status("scanning") def get_empty(self): return self._verify_status("empty") def get_unknown(self): return self._verify_status("unknown") def get_saved(self): return self._verify_status("saved") def get_scan_failed(self): return self._verify_status("scan_failed") def get_search_loaded(self): return self._verify_status("search_loaded") status = property(get_status, set_status) saved = property(get_saved) unsaved_unchanged = property(get_unsaved_unchanged) unsaved_changed = property(get_unsaved_changed) loaded_unchanged = property(get_loaded_unchanged) loaded_changed = property(get_loaded_changed) parsing_result = property(get_parsing_result) scanning = property(get_scanning) empty = property(get_empty) unknown = property(get_unknown) scan_failed = property(get_scan_failed) search_loaded = property(get_search_loaded) _status = "unknown" available_status = ["saved", "unsaved_unchanged", "unsaved_changed", "loaded_unchanged", "loaded_changed", "parsing_result", "scanning", "empty", "unknown", "search_loaded"] class ScanNotebook(HIGNotebook): def __init__(self): HIGNotebook.__init__(self) self.set_scrollable(True) self.tab_titles = [] self.scan_num = 1 def remove_page(self, page_num): page = self.get_nth_page(page_num) self.remove_tab_title(self.get_tab_title(page)) HIGNotebook.remove_page(self, page_num) def append_page(self, page, close_cb, tab_label=None, tab_title=None): log.debug(">>> Appending Scan Tab.") if tab_label: tab_label.set_text(self.sanitize_tab_title(tab_label.get_text())) elif tab_title: tab_label = HIGAnimatedTabLabel(self.sanitize_tab_title(tab_title)) else: tab_label = HIGAnimatedTabLabel(self.get_new_tab_title()) tab_label.connect("close-clicked", close_cb, page) HIGNotebook.append_page(self, page, tab_label) def sanitize_tab_title(self, title): log.debug(">>> Sanitize this title: %s" % title) scan_id = 1 title2 = title while title2 in self.tab_titles: title2 = "%s (%s)" % (title, scan_id) scan_id += 1 self.add_tab_title(title2) log.debug(">>> Title sanitized: %s" % title2) return title2 def remove_tab_title(self, title): log.debug(">>> Remove tab title: %s" % title) try: self.tab_titles.remove(title) except: pass def get_new_tab_title(self, parsed_result=None): log.debug(">>> Get new tab title") if parsed_result: if parsed_result.scan_name: return self.sanitize_tab_title(parsed_result.scan_name) try: filename = parsed_result.nmap_xml_file if filename and type(filename) in StringTypes: return self.sanitize_tab_title(filename) except: pass index = self.scan_num self.scan_num += 1 return self.sanitize_tab_title(_('untitled_scan%s') % index) def add_tab_title(self, title): log.debug(">>> Add tab title: %s" % title) self.tab_titles.append(title) def get_tab_title(self, page): log.debug(">>> Get tab title") return self.get_tab_label(page).get_text() def set_tab_title(self, page, title): log.debug(">>> Set tab title: %s" % title) old_title = self.get_tab_title(page) if old_title: self.remove_tab_title(old_title) if not title: title = self.get_new_tab_title(page.parsed) else: title = self.sanitize_tab_title(title) self.get_tab_label(page).set_text(title) class ScanNotebookPage(HIGVBox): def __init__(self): HIGVBox.__init__(self) self.set_spacing(0) self.status = PageStatus() self.status.set_empty() self.changes = False self.comments = {} self.parsed = NmapParser() self.top_box = HIGVBox() self.__create_toolbar() self.__create_command_toolbar() self.__create_scan_result() self.disable_widgets() self.saved = False self.saved_filename = '' self.top_box.set_border_width(6) self.top_box.set_spacing(5) self.top_box._pack_noexpand_nofill(self.toolbar) self.top_box._pack_noexpand_nofill(self.command_toolbar) self._pack_noexpand_nofill(self.top_box) self._pack_expand_fill(self.scan_result) def target_focus(self): self.toolbar.target_entry.child.grab_focus() def select_first_profile(self): self.toolbar.profile_entry.child.set_text(self.toolbar.profile_entry.get_model()[0][0]) def verify_changes(self): return self.__verify_comments_changes() def go_to_host(self, host): """Go to host line on nmap output result""" self.scan_result.scan_result_notebook.nmap_output.nmap_output.go_to_host(host) def __create_scan_result(self): self.scan_result = ScanResult() def __create_toolbar(self): self.toolbar = ScanToolbar() self.empty_target = _("") self.toolbar.target_entry.connect('changed', self.refresh_command_target) self.toolbar.profile_entry.connect('changed', self.refresh_command) self.toolbar.scan_button.connect('clicked', self.start_scan_cb) def __create_command_toolbar(self): self.command_toolbar = ScanCommandToolbar() self.command_toolbar.command_entry.connect('activate', lambda x: self.toolbar.scan_button.clicked()) # This variable says if the command at command entry was edited by user self.command_edited = False # When user clicks insite the command entry for edition self.command_toolbar.command_entry.connect("focus-in-event", self.remember_command) # When user gets out of the command entry after edition self.command_toolbar.command_entry.connect("focus-out-event", self.check_command) def remember_command(self, widget, extra=None): # User is inside command entry, probably editing it... self.old_target = self.toolbar.target_entry.selected_target # Target may be empty if not self.old_target: self.old_target = self.empty_target self.old_full_command = self.command_toolbar.command_entry.get_text() self.old_command = self.old_full_command.split(self.old_target)[0] def check_command(self, widget, extra=None): # User has left command entry. Verify if something has changed! new_command = self.command_toolbar.command #print "New:", new_command #print "Old:", self.old_full_command #if new_command != self.old_full_command: # print "Gosh! Is different!! Now, what?" #target = self.toolbar.target_entry.selected_target #if self.saved_target: # self.saved_command = self.command_toolbar.command_entry.get_text().split( # self.saved_target)[0] #else: # self.saved_command = self.command_toolbar.command_entry.get_text().split( # _(""))[0] # #print self.saved_target #print self.saved_command def disable_widgets(self): self.scan_result.set_sensitive(False) def enable_widgets(self): self.scan_result.set_sensitive(True) def refresh_command_target(self, widget): log.debug(">>> Refresh Command Target") profile = self.toolbar.selected_profile log.debug(">>> Profile: %s" % profile) if profile != '': target = self.toolbar.selected_target log.debug(">>> Target: %s" % target) try: cmd_profile = CommandProfile() command = cmd_profile.get_command(profile) % target del(cmd_profile) self.command_toolbar.command = command except ProfileNotFound: pass #self.profile_not_found_dialog() def refresh_command(self, widget): log.debug(">>> Refresh Command") profile = self.toolbar.selected_profile target = self.toolbar.selected_target log.debug(">>> Profile: %s" % profile) log.debug(">>> Target: %s" % target) if target == '': target = self.empty_target try: cmd_profile = CommandProfile() command = cmd_profile.get_command(profile) % target del(cmd_profile) self.command_toolbar.command = command except ProfileNotFound: pass #self.profile_not_found_dialog() except TypeError: pass # That means that the command string convertion "%" didn't work def profile_not_found_dialog(self): warn_dialog = HIGAlertDialog(message_format=_("Profile not found!"), secondary_text=_("The profile name you \ selected/typed couldn't be found, and probably doesn't exist. Please, check the profile \ name, and then try again."), type=gtk.MESSAGE_QUESTION) warn_dialog.run() warn_dialog.destroy() def get_tab_label(self): return self.get_parent().get_tab_title(self) def set_tab_label(self, label): self.get_parent().set_tab_title(self, label) def start_scan_cb(self, widget): target = self.toolbar.selected_target command = self.command_toolbar.command profile = self.toolbar.selected_profile log.debug(">>> Start Scan:") log.debug(">>> Target: '%s'" % target) log.debug(">>> Profile: '%s'" % profile) log.debug(">>> Command: '%s'" % command) if target and profile: self.set_tab_label("%s on %s" %(profile, target)) elif target: self.set_tab_label("Scan on %s" % target) elif profile: self.set_tab_label(profile) #### # Setting status to scanning self.status.set_scanning() #### if target != '': self.toolbar.add_new_target(target) if command != '': self.execute_command(command) else: warn_dialog = HIGAlertDialog(message_format=_("Empty Nmap Command!"), secondary_text=_("There is no command to be \ executed! Maybe the selected/typed profile doesn't exist. Please, check the profile name \ or type a nmap command that you would like to execute."), type=gtk.MESSAGE_ERROR) warn_dialog.run() warn_dialog.destroy() def close_tab(self): try: gobject.source_remove(self.verify_thread_timeout_id) except: pass def collect_umit_info(self): profile = CommandProfile() profile_name = self.toolbar.selected_profile self.parsed.target = self.toolbar.get_target() self.parsed.profile_name = profile_name self.parsed.nmap_command = self.command_toolbar.get_command() self.parsed.profile = profile.get_command(profile_name) self.parsed.profile_hint = profile.get_hint(profile_name) self.parsed.profile_description = profile.get_description(profile_name) self.parsed.profile_annotation = profile.get_annotation(profile_name) self.parsed.profile_options = profile.get_options(profile_name) del(profile) try: self.parsed.nmap_output = self.command_execution.get_raw_output() except: self.parsed.nmap_output = "\\n".join(self.scan_result.get_nmap_output().split("\n")) def kill_scan(self): self.command_execution.kill() self.scan_result.clear_nmap_output() self.scan_result.clear_host_view() self.status.set_empty() self.disable_widgets() def execute_command(self, command): try: alive = self.command_execution.scan_state() if alive: warn_dialog = HIGAlertDialog(message_format=_("Scan has not finished yet"), secondary_text=_("Another Scan is running in \ background and has not finished yet. To start another scan and kill the old one, click Ok. \ To wait the conclusion of the old scan, choose Cancel."), type=gtk.MESSAGE_QUESTION, buttons=gtk.BUTTONS_OK_CANCEL) response = warn_dialog.run() warn_dialog.destroy() if response == gtk.RESPONSE_OK: # Kill current scan, and let the another one to be created self.kill_scan() else: return except: pass self.command_execution = NmapCommand(command) try: self.command_execution.run_scan() except Exception, msg: warn_dialog = HIGAlertDialog(message_format=_("Command is missing!"), secondary_text=_("It seens that your profile's \ command is missing or something else went wrong. This may be caused by a miss configuration \ of your profile. Please, try to remove your profile and then create it again."), type=gtk.MESSAGE_ERROR) warn_dialog.run() warn_dialog.destroy() # Ask NmapOutputViewer to show/refresh nmap output from given file self.scan_result.show_nmap_output(self.command_execution.get_output_file()) # Set a "EXECUTING" icon to host list self.scan_result.set_hosts({_('Scanning'):{'stock':gtk.STOCK_EXECUTE,'action':None}}) self.scan_result.set_services({_('Scanning'):{'action':None}}) # Clear port list, to remove old information self.scan_result.clear_port_list() # When scan starts, change to nmap output view tab and refresh output self.scan_result.change_to_nmap_output_tab() self.scan_result.refresh_nmap_output() self.enable_widgets() # Add a timeout function self.verify_thread_timeout_id = gobject.timeout_add(2000, self.verify_execution) def verify_execution(self): # Using new subprocess style try: alive = self.command_execution.scan_state() except: self.disable_widgets() self.status.set_scan_failed() self.scan_result.set_nmap_output(self.command_execution.get_error()) return False #log.debug(">>> Process alive? %s" % alive) #log.debug(">>> Nmap output:\n %s" % self.command_execution.get_output()) # Maybe this automatic refresh should be eliminated to avoid processor burning self.scan_result.refresh_nmap_output() if alive: return True else: self.parse_result(self.command_execution.get_xml_output_file()) return False def load_result(self, file_to_parse): #### # Setting status to parsing_result self.status.set_parsing_result() #### self._parse(file_to_parse=file_to_parse) #### # Setting status to loaded_unchanged self.status.set_loaded_unchanged() #### def parse_result(self, file_to_parse): #### # Setting status to parsing_result self.status.set_parsing_result() #### self._parse(file_to_parse=file_to_parse) #### # Setting status to unsaved_unchanged self.status.set_unsaved_unchanged() #### def load_from_parsed_result(self, parsed_result): #### # Setting status to parsing_result self.status.set_parsing_result() #### self._parse(parsed_result=parsed_result) #### # Setting status to unsaved_unchanged self.status.set_unsaved_unchanged() #### def _parse(self, file_to_parse=None, parsed_result=None): '''Called when scan is done. Verify if any host were found ''' log.debug(">>> XML output file that is going to be parsed: %s" % file_to_parse) self.host_view_selection = self.scan_result.get_host_selection() self.service_view_selection = self.scan_result.get_service_selection() # All hosts details pages self.host_pages = [] self.changes = True self.host_view_selection.connect('changed', self.update_host_info) self.service_view_selection.connect('changed', self.update_service_info) self.scan_result.scan_host_view.clear_host_list() self.hosts = {} self.services = {} # Removed and created again to avoid host duplication problems when making # multiple scans inside the same scan tab try: del(self.parsed) except: pass if file_to_parse: self.parsed = NmapParser() self.parsed.set_xml_file(file_to_parse) try: log.debug(">>> Start parsing...") self.parsed.parse() log.debug(">>> Successfully parsed!") except: log.debug(">>> An exception occourried during xml ouput parsing") try: error = self.command_execution.get_error() except: error = _('Unknown error!') log.debug(">>> Error: '%s'" % error) # Treat root exceptions more carefully! if re.findall('[rR][oO0]{2}[tT]', error): need_root = HIGAlertDialog(\ message_format=_('Root privileges are needed!'),\ secondary_text=error) need_root.run() need_root.destroy() else: unknown_problem = HIGAlertDialog(\ message_format=_('An unexpected error occourried!'),\ secondary_text=error) unknown_problem.run() unknown_problem.destroy() return elif parsed_result: self.parsed = parsed_result if int(self.parsed.get_hosts_up()): for host in self.parsed.get_hosts(): hostname = host.get_hostname() host_page = self.set_host_details(host) list_states = ["open", "filtered", "open|filtered"] for service in host.services: name = service["service_name"] state = service["port_state"] if state not in list_states: continue if name not in self.services.keys(): self.services[name] = {"hosts":[]} hs = {"host":host, "page":host_page, "hostname":hostname} hs.update(service) self.services[name]["hosts"].append(hs) self.hosts[hostname] = {'host':host, 'page':host_page} host_details = self.hosts[hostname]['page'].host_details host_info = self.hosts[hostname]['host'] try: host_details.set_os_image(get_os_logo(host.get_osmatch()['name'])) except: host_details.set_os_image(get_os_logo('')) host_details.set_vulnerability_image(get_vulnerability_logo\ (host_info.get_openned_ports())) icon = None try:icon = get_os_icon(host.get_osmatch()['name']) except:icon = get_os_icon('') self.scan_result.scan_host_view.add_host({hostname:{'stock':icon, 'action':None}}) # Select the first host found self.host_view_selection.select_iter(self.scan_result.scan_host_view.\ host_list.get_iter_root()) self.scan_result.scan_host_view.set_services(self.services.keys()) try: # And them, we update the nmap output! ;) self.scan_result.scan_result_notebook.nmap_output.nmap_output.refresh_output() except: # Put saved nmap output self.scan_result.scan_result_notebook.nmap_output.\ nmap_output.text_buffer.\ set_text('\n'.join(self.parsed.get_nmap_output().split('\\n'))) target = self.parsed.get_target() if target != '': self.toolbar.target_entry.child.set_text(target) profile_name = self.parsed.profile_name if profile_name != '': profile = CommandProfile() profile.add_profile(self.parsed.profile_name, command=self.parsed.profile, hint=self.parsed.profile_hint, options=self.parsed.profile_options, description=self.parsed.profile_description, annotation=self.parsed.profile_annotation) del(profile) self.toolbar.profile_entry.update() self.toolbar.selected_profile = profile_name else: pass # The line bellow seens to be useless #self.command_toolbar.command = self.parsed.get_nmap_command() self.collect_umit_info() self.switch_scan_details(self.__set_scan_info()) self.check_fingerprints() def check_fingerprints(self): re_host = re.compile(r"(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})") re_os_fp = re.compile(r"(SInfo.*\);)") re_service_fp = re.compile(r"(SF-Port.*\);)") re_service_number = re.compile(r"SF-Port(\d+)") nmap_output = self.parsed.nmap_output.split("\\n\\n") fingerprints = {} current_ip = None for line in nmap_output: match_host = re_host.search(line) match_os = re_os_fp.search(line) match_service = re_service_fp.search(line) if match_host: current_ip = match_host.groups()[0] if match_os: if current_ip not in fingerprints.keys(): fingerprints[current_ip] = {} fingerprints[current_ip]["os"] = match_os.groups()[0] if match_service: if current_ip not in fingerprints.keys(): fingerprints[current_ip] = {} fp = match_service.groups()[0] fingerprints[current_ip]["service"] = fp #port = re_service_port.search(fp).groups()[0] #fingerprints[current_ip]["service_port"] = port #fingerprints[current_ip]["service_name"] # In the future, umit is going to catch the fingerprint informations and # load a umitGUI.OSFingerprintReport or umitGUI.ServiceFingerprintReport window # that will let user to directilly register a new fingerprint from the interface # without worrying about moving his mouse off the interface. """ for fp in fingerprints: # We've found a new fp! Please contribute dialog # If ok, show the form, sending the ip and fingerprint. """ key_num = len(fingerprints.keys()) dialog_text = "Umit has found that %s. The submission and registration of \ fingerprints are very important for you and the Nmap project! If you would like to contribute \ to see your favorite network mapper recognizing those fingerprints in the future, choose the \ Ok button, and a submission page will be openned in your default web browser with instructions \ about how to proceed on this registration." if key_num == 1: msg = _("you network scan discovered an unknown fingerprint sent by the \ host %s") % fingerprints.keys()[0] self.show_contribute_dialog(dialog_text % msg) elif key_num > 1: msg = _("you network scan discovered several unknown fingerprints sent by the \ follwoing hosts: ") for i in fingerprints: msg += "%s, " % i msg = msg[:-2] self.show_contribute_dialog(dialog_text % msg) def show_contribute_dialog(self, dialog_text): contribute_dialog = HIGAlertDialog(message_format=_("Unrecognized Services/OS \ Fingerprints Found!"), secondary_text=dialog_text, type=gtk.MESSAGE_QUESTION, buttons=gtk.BUTTONS_OK_CANCEL) response = contribute_dialog.run() contribute_dialog.destroy() if response == gtk.RESPONSE_OK: import webbrowser webbrowser.open("http://www.insecure.org/nmap/submit/") def __verify_comments_changes(self): try: for hostname in self.hosts: if self.hosts[hostname]['page'].host_details.\ get_comment() != self.comments[hostname]: log.debug("Changes on comments") self.changes = True return True except: return False def __set_scan_info(self): self.clean_scan_details() run_details = ScanRunDetailsPage() run_details.set_command_info(\ {'command':self.parsed.get_nmap_command(),\ 'version':self.parsed.get_scanner_version(),\ 'verbose':self.parsed.get_verbose_level(), 'debug':self.parsed.get_debugging_level()}) run_details.set_general_info(\ {'start':self.parsed.get_formated_date(),\ 'finish':self.parsed.get_formated_finish_date(),\ 'hosts_up':str(self.parsed.get_hosts_up()),\ 'hosts_down':str(self.parsed.get_hosts_down()),\ 'hosts_scanned':str(self.parsed.get_hosts_scanned()),\ 'openned_ports':str(self.parsed.get_openned_ports()),\ 'filtered_ports':str(self.parsed.get_filtered_ports()),\ 'closed_ports':str(self.parsed.get_closed_ports())}) run_details.set_scan_infos(self.parsed.get_scaninfo()) return run_details def update_host_info(self, widget): self.scan_result.scan_result_notebook.port_mode() model_host_list, selection = widget.get_selected_rows() host_objs = [self.hosts[model_host_list[i[0]][1]] for i in selection] self.clean_host_details() if len(host_objs) == 1: self.set_single_host_port(host_objs[0]['host']) self.switch_host_details(host_objs[0]['page']) else: self.set_multiple_host_port(host_objs) self.switch_host_details(self.set_multiple_host_details(host_objs)) # Switch nmap output to show first host occourrence try: self.go_to_host(host_objs[0]['host'].get_hostname()) except IndexError: pass def update_service_info(self, widget): self.scan_result.scan_result_notebook.host_mode() model_service_list, selection = widget.get_selected_rows() serv_objs = [self.services[model_service_list[i[0]][0]] for i in selection] # Removing current widgets from the host details page self.clean_host_details() if len(serv_objs) == 1: self.set_single_service_host(serv_objs[0]['hosts']) self.switch_host_details([page["page"] for page in serv_objs[0]['hosts']]) else: servs = [] for s in serv_objs: servs.append({"service_name":s["hosts"][0]["service_name"], "hosts":s["hosts"]}) self.set_multiple_service_host(servs) pages = [] for serv in [serv["hosts"] for serv in serv_objs]: for h in serv: # Prevent from adding a host more then once if h["page"] not in pages: pages.append(h["page"]) self.switch_host_details(pages) # Change scan tab to "Ports/Hosts" self.scan_result.scan_result_notebook.set_current_page(0) def clean_host_details(self): parent = self.scan_result.scan_result_notebook.host_details_vbox children = parent.get_children() for child in children: parent.remove(child) def clean_scan_details(self): parent = self.scan_result.scan_result_notebook.scan_details_vbox children = parent.get_children() for child in children: parent.remove(child) def switch_host_details(self, page): if type(page) == type([]) and len(page) > 1: for p in page: p.hide() p.set_expanded(False) self.scan_result.scan_result_notebook.host_details_vbox._pack_noexpand_nofill(p) self.scan_result.scan_result_notebook.host_details_vbox.show_all() return elif len(page) == 1: page = page[0] try: page.hide() except: pass else: self.scan_result.scan_result_notebook.host_details_vbox._pack_noexpand_nofill(page) page.set_expanded(True) page.show_all() def switch_scan_details(self, page): # Removing current widget from the host details page self.scan_result.scan_result_notebook.scan_details_vbox._pack_noexpand_nofill(page) page.show_all() def set_multiple_host_details(self, host_list): hosts = [] for h in host_list: hosts.append(h['page']) return hosts def _save_comment(self, widget, extra, host_id): if self.status.unsaved_unchanged: self.status.set_unsaved_changed() elif self.status.loaded_unchanged or self.status.saved: self.status.set_loaded_changed() # Catch a comment and record it to be saved posteriorly log.debug(">>> Catching edited comment to be saved posteriorly.") buff = widget.get_buffer() self.parsed.set_host_comment(host_id, buff.get_text(buff.get_start_iter(), buff.get_end_iter())) def set_host_details(self, host): # Start connecting event to automatically update comments, target and profile infos host_page = ScanHostDetailsPage(host.get_hostname()) host_details = host_page.host_details log.debug(">>> Setting host details") log.debug(">>> Hostname: %s" % host.get_hostname()) log.debug(">>> Comment: %s" % self.parsed.get_host_comment(host.id)) host_details.set_comment(self.parsed.get_host_comment(host.id)) # Setting events to automatically record the commentary to be saved host_page.host_details.comment_txt_vw.connect("insert-at-cursor", self._save_comment, host.id) host_page.host_details.comment_txt_vw.connect("focus-out-event", self._save_comment, host.id) self.comments[host.get_hostname()] = host.get_comment() uptime = host.get_uptime() host_details.set_host_status({'state':host.get_state(), 'openned':str(host.get_openned_ports()), 'filtered':str(host.get_filtered_ports()), 'closed':str(host.get_closed_ports()), 'scanned':str(host.get_scanned_ports()), 'uptime':uptime['seconds'], 'lastboot':uptime['lastboot']}) ipv4 = '' try:ipv4 = host.get_ip_address()['addr'] except KeyError: pass ipv6 = '' try:ipv6 = host.get_ipv6_address()['addr'] except KeyError: pass mac = '' try:mac = host.get_mac_address()['addr'] except KeyError: pass host_details.set_addresses({'ipv4':ipv4,'ipv6':ipv6,'mac':mac}) host_details.set_hostnames(host.get_hostnames()) os = host.get_osmatch() if os: os['portsused'] = host.get_ports_used() os['osclass'] = host.get_osclasses() host_details.set_os(os) host_details.set_tcpseq(host.get_tcpsequence()) host_details.set_ipseq(host.get_ipidsequence()) host_details.set_tcptsseq(host.get_tcptssequence()) return host_page def set_single_host_port(self, host): host_page = self.scan_result.scan_result_notebook.open_ports.host host_page.switch_port_to_list_store() p = host.get_ports() ports = [] for port in p: ports += port['port'] host_page.clear_port_list() for p in ports: host_page.add_port([self.findout_service_icon(p), p.get('portid', ''), p.get('port_state', ''), p.get('service_name', ''), p.get('service_product', '')]) def set_single_service_host(self, service): host_page = self.scan_result.scan_result_notebook.open_ports.host host_page.switch_host_to_list_store() host_page.clear_host_list() for h in service: host_page.add_host([self.findout_service_icon(h), h.get('hostname', ''), h.get('portid', ''), h.get('protocol', ''), h.get('port_state', ''), h.get('service_product', ''), h.get('service_version', '')]) def set_multiple_host_port(self, host_list): host_page = self.scan_result.scan_result_notebook.open_ports.host host_page.switch_port_to_tree_store() host_page.clear_port_tree() for host in host_list: parent = host_page.port_tree.append(None, [host['host'].\ get_hostname(),'','','','','']) for port in host['host'].get_ports(): for p in port.get('port', []): host_page.port_tree.append(parent, \ ['',self.findout_service_icon(p), p.get('portid', ""),\ p.get('port_state', ""),p.get('service_name', _("Unknown")),\ p.get('service_product', "")]) def set_multiple_service_host(self, service_list): host_page = self.scan_result.scan_result_notebook.open_ports.host host_page.switch_host_to_tree_store() host_page.clear_host_tree() for host in service_list: parent = host_page.host_tree.append(None, [host['service_name'], '','','','','', '', '']) for h in host['hosts']: host_page.host_tree.append(parent, \ ['', self.findout_service_icon(h), h["hostname"], h.get('portid', ""), h.get('protocol', ""), h.get('port_state', _("Unknown")), h.get('service_product', ''), h.get('service_version', _("Unknown"))]) def findout_service_icon(self, port_info): return gtk.STOCK_YES class ScanResult(gtk.HPaned): def __init__(self): gtk.HPaned.__init__(self) self.scan_host_view = ScanHostsView() self.scan_result_notebook = ScanResultNotebook() self.pack1(self.scan_host_view, True, False) self.pack2(self.scan_result_notebook, True, False) def set_nmap_output(self, msg): self.scan_result_notebook.nmap_output.nmap_output.text_view.get_buffer().set_text(msg) def clear_nmap_output(self): self.scan_result_notebook.nmap_output.nmap_output.text_view.get_buffer().set_text("") def clear_host_view(self): self.set_hosts({}) def clear_service_view(self): self.set_services({}) def get_host_selection(self): return self.scan_host_view.host_view.get_selection() def get_service_selection(self): return self.scan_host_view.service_view.get_selection() def get_nmap_output(self): return self.scan_result_notebook.nmap_output.get_nmap_output() def show_nmap_output(self, file): """Ask NmapOutputViewer to show/refresh nmap output from given file """ self.scan_result_notebook.nmap_output.nmap_output.show_nmap_output(file) def set_hosts(self, hosts_dic): """Set hosts at host list """ self.scan_host_view.set_hosts(hosts_dic) def set_services(self, services_dic): self.scan_host_view.set_services(services_dic) def clear_port_list(self): """Clear Umit's scan result ports list """ self.scan_result_notebook.open_ports.host.clear_port_list() def change_to_nmap_output_tab(self): """Show the nmap output tab """ self.scan_result_notebook.set_current_page(1) def refresh_nmap_output(self): """Refresh Nmap output in nmap output tab """ self.scan_result_notebook.nmap_output.nmap_output.refresh_output() class ScanResultNotebook(HIGNotebook): def __init__(self): HIGNotebook.__init__(self) self.set_scrollable(True) self.set_border_width(5) self.__create_widgets() self.__nmap_output_refreshing() self.append_page(self.open_ports_page, gtk.Label(_('Ports / Hosts'))) self.append_page(self.nmap_output_page, gtk.Label(_('Nmap Output'))) self.append_page(self.host_details_page, gtk.Label(_('Host Details'))) self.append_page(self.scan_details_page, gtk.Label(_('Scan Details'))) def get_nmap_output(self): return self.nmap_output.get_map_output() def host_mode(self): self.open_ports.host.host_mode() def port_mode(self): self.open_ports.host.port_mode() def __create_widgets(self): self.open_ports_page = HIGVBox() self.nmap_output_page = HIGVBox() self.host_details_page = HIGScrolledWindow() self.scan_details_page = HIGScrolledWindow() self.scan_details_vbox = HIGVBox() self.host_details_vbox = HIGVBox() self.open_ports = ScanOpenPortsPage() self.nmap_output = ScanNmapOutputPage() self.no_selected = gtk.Label(_('No host selected!')) self.host_details = self.no_selected self.no_details = gtk.Label(_('Scan is not finished yet!')) self.scan_details = self.no_details self.open_ports_page.add(self.open_ports) self.nmap_output_page.add(self.nmap_output) self.host_details_page.add_with_viewport(self.host_details_vbox) self.host_details_vbox._pack_expand_fill(self.host_details) self.scan_details_page.add_with_viewport(self.scan_details_vbox) self.scan_details_vbox._pack_expand_fill(self.scan_details) def __nmap_output_refreshing(self): self.connect('switch-page', self.refresh_cb) def refresh_cb(self, widget, page=None, page_num=None): if self.nmap_output.nmap_output.thread.isAlive(): if page_num == 2: self.nmap_output.nmap_output.refresh_output(None) if __name__ == "__main__": status = PageStatus("empty") status.set_saved() status.set_unsaved_unchanged() status.set_unsaved_changed() status.set_loaded_unchanged() status.set_loaded_changed() status.set_empty() status.set_scanning() status.set_parsing_result() status.set_unknown() print "Saved:", status.saved print "Unsaved unchanged:", status.unsaved_unchanged print "Unsaved changed:", status.unsaved_changed print "Loaded unchanged:", status.loaded_unchanged print "Loaded changed:", status.loaded_changed print "Empty:", status.empty print "Scanning:", status.scanning print "Parsing result:", status.parsing_result print "Unknown:", status.unknown