class EntryField(object): """ This class is responsible by the main part of QS: the EntryField. All logic of completion, data handling and interface is here. """ def __init__(self): self.qs_data = QSData() self.entry = HIGTextEntry() self.entry.set_visibility(True) self.status = Status() self.status.set_empty() self.scan_result = Result() self.b_text = "" self.rgx_is_domain = "^((ht|f)tp(s?)\:\/\/|~/|/)?([\w]+:\w+@)?([a-zA-Z]{1}" self.rgx_is_domain += "([\w\-]+\.)+([\w]{2,5}))(:[\d]{1,5})?((/?\w+/)+|/?)" self.rgx_is_domain += "(\w+\.[\w]{3,4})?((\?\w+=\w+)?(&\w+=\w+)*)?" self.completion = gtk.EntryCompletion() self.entry.set_max_length(1000) # add button to launch result in umit self.btn_umit = gtk.Button ("Open Result") self.results_opened = False self.nmap_output = None self.load_data(None) self.btn_umit.connect("clicked", self._launch_umit, None) self.entry.show() def show_results(self): """ Show scan output """ if not self.results_opened: self.nmap_output = NmapOutputViewer() # remove some buttons self.nmap_output.hbox_buttons.remove(self.nmap_output.btn_output_properties) self.nmap_output.hbox_buttons.remove(self.nmap_output.btn_refresh) self.nmap_output.hbox_buttons.pack_start(self.btn_umit) self.vbox.pack_end(self.nmap_output) self.vbox.show_all() self.results_opened = True def hide_results(self): """ Hide scan output """ if self.results_opened: self.nmap_output.hbox_buttons.remove(self.btn_umit) self.vbox.remove(self.nmap_output) self.results_opened = False def menu_to_umit(self, widget, button, time, data=None): """ Here will be the small menu responsible to call Network Scanner. """ if button == 3: data.show_all() def _launch_umit(self, widget, event): """ Here will go the call to NetWork Scanner to display results previously loaded here. """ nscanner_call = "umit -f %s" % self.command_execution.get_xml_output_file() args = shlex.split(nscanner_call) self.command_process = Popen(args, bufsize=1, stdin=PIPE, stdout=PIPE, stderr=PIPE) def load_data(self, option=None): """ Load the data on gtk.ListStore, generate the model and set functions of match and signals. """ liststore = gtk.ListStore(str) if option == "host": for _d in self.qs_data.get_target_list(): liststore.append([_d]) elif option == "profile": for _d in self.qs_data.get_profiles("profile_name"): liststore.append([_d]) elif option == "nmap_options": for _d in self.qs_data.get_nmap_options(): liststore.append([_d]) else: for _d in self.qs_data.get_all().values(): for _i in _d: liststore.append([_i]) self.completion.set_model(liststore) self.completion.set_match_func(self.match_func) self.completion.connect('match-selected', self.on_completion_match) self.entry.connect('activate', self.on_completion_not_match) self.entry.connect('backspace', self.on_backspace) self.entry.set_completion(self.completion) self.completion.set_text_column(0) #def load_if_not_complete(self, widget, event): #self.load_data("host") def match_func(self, completion, key, iter): """ This function have the job to match and compare the words that was entered on the entry field. """ model = self.completion.get_model() modelstr = model[iter][0] if ' ' in key: last_word = " ".join(key.split()[1:]) if last_word != "": return modelstr.lower().startswith(last_word.lower()) or modelstr.lower().startswith(key.lower()) return modelstr.lower().startswith(key.lower()) def on_completion_not_match(self, widget): """ This method is called when the autocompletion don't match any result or user press Enter. """ target_list = TargetList() entered_text = self.entry.get_text() # If has a profile if len(entered_text) > 1 and entered_text.find(" ") != -1: possible_host = entered_text.split(" ")[0] possible_profile = " ".join(entered_text.split(" ")[1:]) else: # If is just a domain self.b_text = entered_text + " " self.entry.set_text(self.b_text) possible_host = entered_text possible_profile = None # Saving the target target_list.add_target(possible_host) self.entry.set_position(-1) # if len(self.b_text.split(" ")) > 1: # host = self.b_text.split(" ")[0] # profile = " ".join(self.b_text.split(" ")[1:]) # else: # host = entered_text # profile = None #Launch the scan self.run_scan(possible_host, possible_profile) #TODO: get the end of the scan here? try: alive = self.command_execution.scan_state() while alive: alive = self.command_execution.scan_state() file = self.command_execution.get_normal_output_file() self.show_results() self.nmap_output.show_nmap_output(file) self.nmap_output.refresh_output() #text_out = self.scan_result.set_nmap_output(possible_host, # self.command_execution.get_normal_output(), # possible_profile) #self.buffer.set_text(text_out) #self.vbox.pack_start(self.result_text, False, False, 0) #self.result_text.show() self.save_scan(possible_host) #del entered_text #self.load_data("profile") return True except: pass def on_completion_match(self, completion, model, iter): #get the text entered by the user entered_text = self.entry.get_text() if model[iter][0]: current_text = model[iter][0] # If has a profile if len(entered_text) > 1 and entered_text.find(" ") != -1: self.b_text = entered_text.split(" ")[0] + " " + current_text + " " self.entry.set_text(self.b_text) possible_host = entered_text.split(" ")[0] possible_profile = current_text #elif self.entry.get_text() else: # If is just a domain self.b_text = current_text + " " self.entry.set_text(self.b_text) possible_host = current_text possible_profile = None self.entry.set_position(-1) data_from_db = self.qs_data.get_from_db() if current_text in data_from_db.keys(): text_out = "" for _t in data_from_db[current_text]: if _t[0] == "ports" or _t[0] == "stats": pass else: text_out += "%s: %s\n" % (_t[0], _t[1]) #self.buffer.set_text(text_out) #self.vbox.pack_start(self.result_text, False, False, 0) #self.result_text.show() self.run_scan(possible_host, possible_profile) try: alive = self.command_execution.scan_state() while alive: alive = self.command_execution.scan_state() if not alive: break self.show_results() file = self.command_execution.get_normal_output_file() print "scan finished - %s" % file self.nmap_output.show_nmap_output(file) self.nmap_output.refresh_output() #text_out = self.scan_result.set_nmap_output(possible_host, # self.command_execution.get_normal_output(), # possible_profile) #self.buffer.set_text(text_out) #self.vbox.pack_start(self.result_text, False, False, 0) #self.result_text.show() self.save_scan(possible_host) #self.load_data("profile") return True except: print("exception") traceback.print_exc(file=sys.stdout) del data_from_db #self.load_data("profile") return True def on_backspace(self, entry): self.hide_results() self.resize(500,30) self.b_text = "" def disable_widgets(self): self.scan_result.set_sensitive(False) def enable_widgets(self): self.scan_result.set_sensitive(True) def kill_scan(self): try: self.command_execution.kill() except AttributeError: pass self.entry.set_text("") self.status.set_empty() self.disable_widgets() def run_scan(self, host, profile): if re.match(self.rgx_is_domain, host): commands = self.qs_data.get_profiles("profile_commands") try: nmap_option = commands[profile] except: nmap_option = "-T Aggressive -v -n" print "QuickScan: running scan: %s on %s" % (nmap_option, host) if Ipv6.is_ipv6(host): namp_option = nmap_option + " -6" self.command_execution = NmapCommand('%s %s %s' % (Path.nmap_command_path, nmap_option, host)) 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 the background.", type=gtk.MESSAGE_QUESTION, buttons=gtk.BUTTONS_OK_CANCEL) response = warn_dialog.run() warn_dialog.destroy() if response == gtk.RESPONSE_OK: self.kill_scan() else: return except: pass try: self.command_execution.run_scan() self.status.set_scanning() except OSError, msg: warn_dialog = HIGAlertDialog( message_format="Nmap couldn't be found", secondary_text="Umit Quick Scan couldn't find Nmap. " "Please check your Nmap instalation.", type=gtk.MESSAGE_ERROR) warn_dialog.run() warn_dialog.destroy() except Exception, msg: warn_dialog = HIGAlertDialog( message_format="Command is missing!", secondary_text="Please check your profile's command.", type=gtk.MESSAGE_ERROR) warn_dialog.run() warn_dialog.destroy() self.verify_thread_timeout_id = gobject.timeout_add(2000, self.verify_execution) return
def run_scheduler(sched, winhndl=None): """ Run scheduler forever. """ next_time = calc_next_time() scount = 0 # number of scans running while 1: # run forever and ever ;) current_time = time.time() if current_time < next_time: sleep_time = next_time - current_time + .1 if winhndl: stopsignal = win32event.WaitForSingleObject( winhndl, int(sleep_time * 1000)) if stopsignal == win32event.WAIT_OBJECT_0: break else: time.sleep(sleep_time) # check if time has changed by more than two minutes (clock changes) if abs(time.time() - next_time) > 120: # reset timer next_time = calc_next_time() sched.check_for_changes() for schema in sched.schemas: if schema.job_to_run(): if not int(schema.enabled): # schema disabled, neeexxt! continue name = schema.schema_name log.info("Scheduled schema to run: %s" % name) if not schema.command: log.warning("No command set for schema %s, \ skipping!" % name) continue scan = NmapCommand(schema.command) scan.run_scan() running_scans[scount] = (scan, schema.saveto, schema.mailto, name, schema.addtoinv, schema.smtp) scount += 1 # more one scan running for running, opts in running_scans.items(): scan = opts[0] try: scan_state = scan.scan_state() except Exception, err: log.critical("Scheduled schema '%s' failed to run. \ Reason: %s" % (schema.schema_name, err)) continue if not scan_state: # scan finished log.info("Scan finished: %s" % opts[3]) if opts[1]: # save xml output saveto = decide_output(opts[1]) f = open(saveto, 'w') f.write(open(scan.get_xml_output_file(), 'r').read()) f.close() log.info("Scan output saved as: %s" % saveto) if opts[2]: # mail output recipients = opts[2].split(',') log.info("Scan output will be mailed to: %s" % recipients) smtp = load_smtp_profile(opts[5]) auth = int(smtp['auth']) tls = int(smtp['tls']) mailfrom = smtp['mailfrom'] user = smtp['user'] passwd = smtp['pass'] server = smtp['server'] port = smtp['port'] curr_time = format_asctime(datetime.now()) orig_output = scan.get_xml_output_file() new_file_output = os.path.join( os.path.dirname(orig_output), "%s (%s).xml" % (curr_time, opts[3])) fd_wcont = open(new_file_output, 'w') for line in open(orig_output, 'r'): fd_wcont.write(line) fd_wcont.close() email = Email(mailfrom, recipients, server, None, user, passwd, tls, port) email.sendmail( subject=( _("UMIT: Status Report for scheduled schema") + " %r " % opts[3]), msg=(_("There was a scheduled job that just " "finished:") + (" %s\n" % curr_time) + _("Follows an attachment of the job output.")), attach=new_file_output) os.remove(new_file_output) if int(opts[4]): # add to inventory log.info("Scan result is being added to Inventory " "%s" % opts[3]) xmlstore = XMLStore(Path.umitdb_ng, False) try: xmlstore.store(scan.get_xml_output_file(), inventory=opts[3]) finally: xmlstore.close() # close connection to the database log.info("Scan finished insertion on Inventory " "%s" % opts[3]) scan.close() # delete temporary files scount -= 1 # one scan finished del running_scans[running] next_time += 60
def run_scheduler(sched, winhndl=None): """ Run scheduler forever. """ next_time = calc_next_time() scount = 0 # number of scans running while 1: # run forever and ever ;) current_time = time.time() if current_time < next_time: sleep_time = next_time - current_time + .1 if winhndl: stopsignal = win32event.WaitForSingleObject(winhndl, int(sleep_time * 1000)) if stopsignal == win32event.WAIT_OBJECT_0: break else: time.sleep(sleep_time) # check if time has changed by more than two minutes (clock changes) if abs(time.time() - next_time) > 120: # reset timer next_time = calc_next_time() sched.check_for_changes() for schema in sched.schemas: if schema.job_to_run(): if not int(schema.enabled): # schema disabled, neeexxt! continue name = schema.schema_name log.info("Scheduled schema to run: %s" % name) if not schema.command: log.warning("No command set for schema %s, \ skipping!" % name) continue scan = NmapCommand(schema.command) scan.run_scan() running_scans[scount] = (scan, schema.saveto, schema.mailto, name, schema.addtoinv, schema.smtp) scount += 1 # more one scan running for running, opts in running_scans.items(): scan = opts[0] try: scan_state = scan.scan_state() except Exception, err: log.critical("Scheduled schema '%s' failed to run. \ Reason: %s" % (schema.schema_name , err)) continue if not scan_state: # scan finished log.info("Scan finished: %s" % opts[3]) if opts[1]: # save xml output saveto = decide_output(opts[1]) f = open(saveto, 'w') f.write(open(scan.get_xml_output_file(), 'r').read()) f.close() log.info("Scan output saved as: %s" % saveto) if opts[2]: # mail output recipients = opts[2].split(',') log.info("Scan output will be mailed to: %s" % recipients) smtp = load_smtp_profile(opts[5]) auth = int(smtp['auth']) tls = int(smtp['tls']) mailfrom = smtp['mailfrom'] user = smtp['user'] passwd = smtp['pass'] server = smtp['server'] port = smtp['port'] curr_time = format_asctime(datetime.now()) orig_output = scan.get_xml_output_file() new_file_output = os.path.join( os.path.dirname(orig_output), "%s (%s).xml" % (curr_time, opts[3])) fd_wcont = open(new_file_output, 'w') for line in open(orig_output, 'r'): fd_wcont.write(line) fd_wcont.close() email = Email(mailfrom, recipients, server, None, user, passwd, tls, port) email.sendmail( subject=( _("UMIT: Status Report for scheduled schema") + " %r " % opts[3]), msg=( _("There was a scheduled job that just " "finished:") + (" %s\n" % curr_time) + _("Follows an attachment of the job output.")), attach=new_file_output) os.remove(new_file_output) if int(opts[4]): # add to inventory log.info("Scan result is being added to Inventory " "%s" % opts[3]) xmlstore = XMLStore(Path.umitdb_ng, False) try: xmlstore.store(scan.get_xml_output_file(), inventory=opts[3]) finally: xmlstore.close() # close connection to the database log.info("Scan finished insertion on Inventory " "%s" % opts[3]) scan.close() # delete temporary files scount -= 1 # one scan finished del running_scans[running] next_time += 60