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
Esempio n. 2
0
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
Esempio n. 3
0
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