def __init__(self, parent, model_controller, caption):
        qt.QVBox.__init__(self, parent)

        self._model_controller = model_controller

        self.modelUpdateTimer = qt.QTimer(self)
       
        self.__pendingModelObjectRedraws = []

        self.reindex_flag_lock = Lock()
        self.reindex_flag = False

        self.connect( self.modelUpdateTimer, qt.SIGNAL("timeout()"), self._modelObjectViewUpdater)
                                        
        self.modelUpdateTimer.start( 1000  , False)
                                                                                 

        self.setName(caption) if caption else self.setName("")

        self.setFrameStyle(qt.QFrame.Panel | qt.QFrame.Plain)
        self.setLineWidth(0)

        self._host_items = {}

                                                                                                   
        self._category_items = {}

                                                                                                
                                                                        
        self._category_tree = {}

        self.contextpopups = {}
        self._setupContextPopups()

        self.contextdispatchers = {}

                       
        self._filter = ""
        self.ix = None

        self._setupContextDispatchers()

        split = qt.QSplitter(self)
        split.setOrientation(qt.QSplitter.Vertical)

        lv = self.listview = ModelObjectListView(split)
                                     
                                       
                                         
        lv.setRootIsDecorated(True)

                                               
        self.connect( lv, qt.SIGNAL("selectionChanged()"), self._itemSelected )
        self.connect( lv, qt.SIGNAL("rightButtonPressed(QListViewItem *,const QPoint&,int)"), self._showContextMenu )
                                                        
        lv.addColumn("Hosts")
        lv.setColumnWidthMode(0,qt.QListView.Maximum)
                                                                                    

                         
        lv.setTreeStepSize(20)

                                                                           
                                                                                                  
                                                                
                                                             
        self.rootitem = None

                                            
               

                                                                           
        self.details_table = EditionTable(split)
        hbox = qt.QHBox(self)
        self.object_label = qt.QLabel("", hbox)
        self.object_label.setMinimumSize(qt.QSize(50, 25))
        self.save_button = SaveButton(hbox, self._item_save)
        self._save_callback = None

        self.prefchilds = []
Exemple #2
0
    def __init__(self, parent, model_controller, caption):
        qt.QVBox.__init__(self, parent)

        self._model_controller = model_controller

        self.modelUpdateTimer = qt.QTimer(self)
       
        self.__pendingModelObjectRedraws = []

        self.reindex_flag_lock = Lock()
        self.reindex_flag = False

        self.connect( self.modelUpdateTimer, qt.SIGNAL("timeout()"), self._modelObjectViewUpdater)
                                        
        self.modelUpdateTimer.start( 1000  , False)
                                                                                 

        self.setName(caption) if caption else self.setName("")

        self.setFrameStyle(qt.QFrame.Panel | qt.QFrame.Plain)
        self.setLineWidth(0)

        self._host_items = {}

                                                                                                   
        self._category_items = {}

                                                                                                
                                                                        
        self._category_tree = {}

        self.contextpopups = {}
        self._setupContextPopups()

        self.contextdispatchers = {}

                       
        self._filter = ""
        self.ix = None

        self._setupContextDispatchers()

        split = qt.QSplitter(self)
        split.setOrientation(qt.QSplitter.Vertical)

        lv = self.listview = ModelObjectListView(split)
                                     
                                       
                                         
        lv.setRootIsDecorated(True)

                                               
        self.connect( lv, qt.SIGNAL("selectionChanged()"), self._itemSelected )
        self.connect( lv, qt.SIGNAL("rightButtonPressed(QListViewItem *,const QPoint&,int)"), self._showContextMenu )
                                                        
        lv.addColumn("Hosts")
        lv.setColumnWidthMode(0,qt.QListView.Maximum)
                                                                                    

                         
        lv.setTreeStepSize(20)

                                                                           
                                                                                                  
                                                                
                                                             
        self.rootitem = None

                                            
               

                                                                           
        self.details_table = EditionTable(split)
        hbox = qt.QHBox(self)
        self.object_label = qt.QLabel("", hbox)
        self.object_label.setMinimumSize(qt.QSize(50, 25))
        self.save_button = SaveButton(hbox, self._item_save)
        self._save_callback = None

        self.prefchilds = []
class HostsBrowser(qt.QVBox):
    """Tree view to display Hosts"""

    def __init__(self, parent, model_controller, caption):
        qt.QVBox.__init__(self, parent)

        self._model_controller = model_controller

        self.modelUpdateTimer = qt.QTimer(self)
       
        self.__pendingModelObjectRedraws = []

        self.reindex_flag_lock = Lock()
        self.reindex_flag = False

        self.connect( self.modelUpdateTimer, qt.SIGNAL("timeout()"), self._modelObjectViewUpdater)
                                        
        self.modelUpdateTimer.start( 1000  , False)
                                                                                 

        self.setName(caption) if caption else self.setName("")

        self.setFrameStyle(qt.QFrame.Panel | qt.QFrame.Plain)
        self.setLineWidth(0)

        self._host_items = {}

                                                                                                   
        self._category_items = {}

                                                                                                
                                                                        
        self._category_tree = {}

        self.contextpopups = {}
        self._setupContextPopups()

        self.contextdispatchers = {}

                       
        self._filter = ""
        self.ix = None

        self._setupContextDispatchers()

        split = qt.QSplitter(self)
        split.setOrientation(qt.QSplitter.Vertical)

        lv = self.listview = ModelObjectListView(split)
                                     
                                       
                                         
        lv.setRootIsDecorated(True)

                                               
        self.connect( lv, qt.SIGNAL("selectionChanged()"), self._itemSelected )
        self.connect( lv, qt.SIGNAL("rightButtonPressed(QListViewItem *,const QPoint&,int)"), self._showContextMenu )
                                                        
        lv.addColumn("Hosts")
        lv.setColumnWidthMode(0,qt.QListView.Maximum)
                                                                                    

                         
        lv.setTreeStepSize(20)

                                                                           
                                                                                                  
                                                                
                                                             
        self.rootitem = None

                                            
               

                                                                           
        self.details_table = EditionTable(split)
        hbox = qt.QHBox(self)
        self.object_label = qt.QLabel("", hbox)
        self.object_label.setMinimumSize(qt.QSize(50, 25))
        self.save_button = SaveButton(hbox, self._item_save)
        self._save_callback = None

        self.prefchilds = []

                              
                                                       

    def load(self, workspace, workspace_type):
        self.rootitem = WorkspaceListViewItem(self.listview, workspace, workspace_type)
        self.listview.setSelected(self.rootitem, True)

    def update(self, hosts):
        self.clearTree()
        self.redrawTree(hosts)
                                         
    def sizeHint(self):
        """Returns recommended size of dialog."""
        return qt.QSize(70, 200)

    def resizeEvent (self, event ):
                                                                  
                                                           
                                                                 
                              
        self.listview.setColumnWidth(0,self.size().width()-7)
                                                                              
                                                                       

    def clearTree(self):
        """
        clear the complete host tree
        """
        self._clearBranch(self.rootitem)
        self._host_items.clear()

    def _clearBranch(self, root):
        """
        clear a branch based on the root provided.
        """
        if root is not None:
            i = root.firstChild()
            items_to_remove = []
            while i is not None:
                items_to_remove.append(i)
                i = i.nextSibling()

            for i in items_to_remove:
                if i.type == "Category":
                    self._delCategory(i.name)
                elif i.type == "Host":
                    category_item = i.parent()
                    self._delHostFromCategory(i.object, category_item.name)

    def redrawTree(self, hosts):
        dialog = qt.QProgressDialog(self, "Loading workspace...", True)
        dialog.setCaption("Please wait")
        dialog.setLabelText("Loading workspace...")
        dialog.setTotalSteps(len(hosts) + 1)
        i = 1
        for host in hosts:
            dialog.setProgress(i)
            category = host.getCurrentCategory()
            self._addCategory(category)
            self._addHostToCategory(host, category)
            i += 1
        for ci in self._category_items.values():
            ci.setOpen(True)

        self.createIndex()
        dialog.setProgress(i)
        self.filterTree(self._filter)
        # we need to make sure that the dialog is closed
        rem = dialog.totalSteps() - i
        if rem > 0:
            dialog.setProgress(i + rem)

    def setReindex(self):
        self.reindex_flag_lock.acquire()
        if not self.reindex_flag:
            self.reindex_flag = True
        self.reindex_flag_lock.release()

    def reindex(self):
        self.reindex_flag_lock.acquire()
        if self.reindex_flag:
            self.createIndex()
            self.reindex_flag = False
        self.reindex_flag_lock.release()

    def filterTree(self, mfilter=""):
        self.reindex()
        hosts=[]
        viewall=False
        self._filter=mfilter

        for k in self._host_items.keys():
            hosts.append(self._host_items[k].object)

        if self._filter:
            hosts=self._filterHost(hosts)
        else:
            viewall=True
            hosts=[]

                                
                    

        for k in self._host_items.keys():
                                                  
            if (self._host_items[k].object.name in hosts) or viewall==True:
                self._host_items[k].setVisible(True)
            else:
                self._host_items[k].setVisible(False)


    def _filterHost(self,hosts):
                                  

        from whoosh.qparser import QueryParser
        with self.ix.searcher() as searcher:
            query = QueryParser("ip", self.ix.schema).parse(self._filter)
            results = searcher.search(query, limit=None)
                           
                        
                          
            hostv={}
            for r in results:
                hostv[r['ip']]=1

        return hostv

    def createIndex(self):
        hosts = self._model_controller.getAllHosts()
        schema = Schema(ip=TEXT(stored=True),
                        hostname=TEXT(stored=True),
                        mac=TEXT(stored=True),
                        os=TEXT(stored=True),
                        port=TEXT(stored=True),
                        srvname=TEXT(stored=True),
                        srvstatus=TEXT(stored=True),
                        vulnn=TEXT(stored=True),
                        namen=TEXT(stored=True),
                        owned=BOOLEAN,
                        cred=BOOLEAN,
                        vuln=BOOLEAN,
                        note=BOOLEAN)

        indexdir=CONF.getDataPath() + "/indexdir"
        if not os.path.exists(indexdir):
            os.mkdir(indexdir)

        self.ix = create_in(indexdir, schema)
        for host in hosts:
            self.indexHost(host)

    def indexHost(self, host):
        writer = self.ix.writer()
        writer.add_document(ip=unicode(host.name), os=unicode(host.getOS()),
                            owned=host.isOwned(),
                            vuln=True if host.vulnsCount() > 0 else False,
                            note=True if len(host.getNotes()) > 0 else False)

        for i in host.getAllInterfaces():
            for h in i._hostnames:
                writer.add_document(ip=unicode(host.name),
                                    hostname=unicode(h),
                                    mac=unicode(i.getMAC()))

        for v in host.getVulns():
            writer.add_document(ip=unicode(host.name), vulnn=unicode(v.name))

        for i in host.getAllInterfaces():
            for s in i.getAllServices():
                for v in s.getVulns():
                    writer.add_document(ip=unicode(host.name),
                                        vulnn=unicode(v.name),
                                        srvname=unicode(s.getName()))
                for p in s.getPorts():
                    writer.add_document(
                        ip=unicode(host.name),
                        port=unicode(str(p)),
                        owned=s.isOwned(),
                        vuln=True if s.vulnsCount() > 0 else False,
                        note=True if len(s.getNotes()) > 0 else False,
                        cred=True if s.credsCount() > 0 else False,
                        srvname=unicode(s.getName()),
                        srvstatus=unicode(s.getStatus()))
        writer.commit()

    def removeIndexHost(self, host):
        writer = self.ix.writer()
        writer.delete_by_term('ip', host.name)
        writer.commit()

    def selectWord(self, word):
        for k in self._host_items:
            host_item = self._host_items[k]
            if host_item.text(0).encode('utf8').strip() == word.strip():
                self.listview.setSelected(host_item, True)
                self.listview.ensureItemVisible(host_item)
                break
            else:
                for i in host_item.object.getAllInterfaces():
                    if i.ipv4['address'] == word.strip():
                        self.listview.setSelected(host_item, True)
                        self.listview.ensureItemVisible(host_item)
                        break
                    elif i.ipv6['address'] == word.strip():
                        self.listview.setSelected(host_item, True)
                        self.listview.ensureItemVisible(host_item)
                        break
                    else:
                        for h in i.getHostnames():
                            if h == word.strip():
                                self.listview.setSelected(host_item, True)
                                self.listview.ensureItemVisible(host_item)
                                break

    def workspaceChanged(self, workspace, workspace_type):
        if self.rootitem:
            root = self.rootitem
            self.listview.takeItem(root)
            del root
        self.clearTree()
        self.load(workspace,workspace_type)

    def updateWorkspaceName(self, nconflicts):
        self.rootitem.updateName(nconflicts)

    def _resolveConflicts(self, item):
        guiapi.resolveConflicts()

    def showResolveConflictDialog(self, conflicts):
        if len(conflicts):
            dialog = ConflictResolutionDialog(conflicts)
            dialog.exec_loop()

    def _item_save(self):
                                                                 
                         
        if self._save_callback is not None:
            self._save_callback()

    def setSaveCallback(self, callback):
        self._save_callback = callback

    def _itemSelected(self, item=False):
        """
        this is called when a list view item is selected
        """
                           
        i = self.listview.firstChild()
        self.items_selected=[]
        self.items_type={'Host': 0, 'Workspace': 0, 'Service':0,
                         'Interface':0, 'Application':0,'Category_General':0
                         ,'Category_Applications':0,'Category_Interfaces':0}
        while i is not None:
            if i.isSelected():

                if i.type=="Category":
                    self.items_type[i.type+"_"+i.name] =self.items_type[i.type+"_"+i.name]+1
                else:
                    self.items_type[i.type] =self.items_type[i.type]+1

                self.items_selected.append(i)
            i = i.itemBelow()
            mtype={'Host': 0, 'Workspace': 0, 'Service':0, 'Interface':0, 'Application':0,'Category':0}

        self.itemselected = self.listview.currentItem()

                                                                                
        self.details_table.clear()
        editor = self.itemselected.getEditor()
        editor.fillEditionTable(self.details_table)
        self.setSaveCallback(editor.save)

    def getItemSelected(self):
        return self.itemselected

    def _addCategory(self, category):
        if category not in self._category_tree:
            self._category_tree[category] = []
            ref = CategoryListViewItem(self.rootitem, category)
            self._category_items[category] = ref
        else:
            ref = self._getCategoryListViewItem(category)
        return ref

    def _addHost(self, host):
        category = host.getCurrentCategory()
        self._addCategory(category)
        self._addHostToCategory(host, category)
        #self.removeIndexHost(host)
        #self.indexHost(host)

    def _removeHost(self, host_id):
        item = self._host_items.get(host_id, None)
        if host_id in self._host_items:
            del self._host_items[host_id]
        for category in self._category_tree.keys():
            if host_id in self._category_tree.get(category):
                self._category_tree[category].remove(host_id)
                category_item = self._getCategoryListViewItem(category)
                try:
                    category_item.takeItem(item)
                except Exception:
                    api.devlog("Exception taking item from category")

    def _editHost(self, host):
        self._removeHost(host.getID())
        self._addHost(host)

    def _addHostToCategory(self, host, category):
        category_item = self._addCategory(category)
        self._host_items[host.getID()] = HostListViewItem(category_item, host.name, host)
        self._category_tree[category].append(host.getID())

    def _delHostFromCategory(self, host, category):
        id = host.getID()
        item = self._host_items.get(id, None)
        if id in self._host_items:
            del self._host_items[id]
        if category in self._category_tree:
            if id in self._category_tree[category]:
                self._category_tree[category].remove(id)
                category_item = self._getCategoryListViewItem(category)
                api.devlog("_delHostFromCategory: about to call takeItem for category %s" % category)
                try:
                    category_item.takeItem(item)
                except Exception:
                    pass
                api.devlog("_delHostFromCategory: after takeItem")

    def _getCategoryListViewItem(self, category):
        return self._category_items.get(category, None)

    def _delCategory(self, category, recursive=False):
        if category in self._category_tree:
            if recursive:                                              
                for id in self._category_tree:
                    host_item = self._getHostListViewItem(id)
                    if host_item is not None:
                        self._delHostFromCategory(host_item.object, category)
            else:
                                                                                   
                                               
                for id in self._category_tree:
                    host_item = self._getHostListViewItem(id)
                    if host_item is not None:
                        self._moveHostToCategory(host_item.object, CONF.getDefaultCategory())

                del self._category_tree[category]
                item = self._category_items[category]
                del self._category_items[category]
                self.rootitem.takeItem(item)

    def _getHostListViewItem(self, id):
        return self._host_items.get(id, None)

    def _showContextMenu(self, item, pos, val):
        """Pop up a context menu when an item is clicked on the list view."""
        ret = None

        if item is not None:                           

                                  
                       
                                                                                                                                                            
            if self.items_type['Interface']:
                if (self.items_type['Category_General'] or self.items_type['Workspace']):
                    popname="CategoryWorkspace_Interface"
                elif (self.items_type['Host'] or self.items_type['Service']):
                    popname="ServiceHost_Interface"
                else:
                    popname=item.type

            elif (self.items_type['Host'] or self.items_type['Service']):
                if (self.items_type['Category_General'] or self.items_type['Workspace']):
                    popname="CategoryWorkspace_ServiceHost"
                elif (self.items_type['Host'] and self.items_type['Service']):
                    popname="Service_Host"
                else:
                    if item.type is "Category":
                        popname="Host"
                    else:
                        popname=item.type
            else:
                                   
                if item.type is "Category":
                    popname=item.type + "_" + item.name
                else:
                    popname=item.type

            ret = self.contextpopups[popname].exec_loop(pos)

            if ret in self.contextdispatchers:
                self.contextdispatchers[ret](item)
                  
                                                                         

            api.devlog("contextMenuEvent - item: %s - ret %s" % (self.name, ret))

              

    def _newHost(self, item):
        api.devlog("newHost")
        dialog = NewHostDialog(self, self._newHostCallback)
        dialog.exec_loop()

    def _newHostCallback(self, name, os):
        if name:
                                          
            guiapi.createAndAddHost(name, os=os)

    def _delHost(self,item):
        api.devlog("delHost")
        if item is not None and item.object is not None:                                                  
            dialog = MessageDialog(self,title="Host delete",callback=self._delSelectedCallback)
            dialog.exec_loop()

    def _delHostCallback(self, item):
        api.devlog("delcallbackHost %s " % (item.object.name))
        guiapi.delHost(item.object.getID())

    def _newInterface(self, item):
        api.devlog("newInterface")
        dialog = NewInterfaceDialog(self, self._newInterfaceCallback)
        dialog.exec_loop()

    def _newInterfaceCallback(self, name, ipv4_address, ipv6_address):
        if name and (ipv4_address or ipv6_address):
            for i in self.items_selected:
                host_id = i.object.getID()
                guiapi.createAndAddInterface(host_id, name, ipv4_address=ipv4_address, ipv6_address=ipv6_address)

    def _delInterface(self,item):
        api.devlog("delInterface")
        if item is not None and item.object is not None:                                                  
            dialog = MessageDialog(self,title="Interface delete",callback=self._delSelectedCallback)
            dialog.exec_loop()

    def _delInterfaceCallback(self, item):
        api.devlog("delcallbackInterface %s " % (item.object.name))
        _parent=item.object.getParent()
        guiapi.delInterface(_parent.getID(), item.object.getID())

    def _newService(self,item):
        api.devlog("newService")
        dialog = NewServiceDialog(self, self._newServiceSelectedCallback)
        dialog.exec_loop()

    def _newServiceSelectedCallback(self, name, protocol, ports):
        if name and protocol and ports:
            for i in self.items_selected:
                if i.type == "Interface":
                    interface_id = i.object.getID()
                    host_id = i.object.getParent().getID()
                    guiapi.createAndAddServiceToInterface(host_id, interface_id , name, protocol=protocol, ports=ports)

    def _delService(self,item):
        if item is not None and item.object is not None:                                                  
            dialog = MessageDialog(self,title="Delete Item(s)",callback=self._delSelectedCallback)
            dialog.exec_loop()

    def _delServiceCallback(self, item):
        api.devlog("delcallbackService %s " % (item.name))
        _object=item.object
        _host=_object.getParent()
        guiapi.delServiceFromHost(_host.getID(), _object.getID())

    def _delSelectedCallback(self,item):

        for i in self.items_selected:
            if i.type == "Host":
                api.devlog("delcallbackHost %s " % (i.object.name))
                guiapi.delHost(i.object.getID())
            elif i.type == "Application":
                api.devlog("delcallbackApplication %s " % (i.object.name))
                _parent=i.object.getParent()
                _object=i.object
                guiapi.delApplication(_parent.getID(),_object.getID())
            elif i.type == "Interface":
                api.devlog("delcallbackInterface %s " % (i.object.name))
                _parent=i.object.getParent()
                _object=i.object
                guiapi.delInterface(_parent.getID(), _object.getID())
            elif i.type == "Service":
                api.devlog("delcallbackService %s " % (i.name))
                _object=i.object
                parent_interface = self._getParentForType(i, "Interface").object
                parent_host = self._getParentForType(i, "Host").object
                guiapi.delServiceFromInterface(parent_host.getID(), parent_interface.getID(), _object.getID())
                                                       
        self.listview.setCurrentItem(self.rootitem)
        self._itemSelected()

    def _getParentForType(self, obj, obj_type):
        parent = obj.parent()
        if obj_type == parent.type:
            return parent
        else:
            return self._getParentForType(parent, obj_type)

    def _newCategory(self,item):
        api.devlog("newCategory")

    def _renCategory(self,item):
        api.devlog("renCategory")

    def _delCategorymenu(self,item):
        api.devlog("delCategorymenu")
        if item is not None:                                                  
            dialog = MessageDialog(self,title="Category delete",callback=self._delCategoryCallback,item=item)
            dialog.exec_loop()

    def _delCategoryCallback(self, item):
        api.devlog("delcallbackCategory %s " % (item.name))

    def _newVuln(self, item):
        api.devlog("newVuln")
        if item is not None and item.object is not None:
            vuln_web_enabled = False
            if item.object.class_signature == "Service":
                vuln_web_enabled = True
            dialog = NewVulnDialog(
                self,
                callback=self._newVulnSelectedCallback,
                vuln_web_enabled=vuln_web_enabled)
            dialog.exec_loop()

    def _newVulnSelectedCallback(self, *args):
        callback = guiapi.createAndAddVuln
        if args[0]:
            # vuln web
            callback = guiapi.createAndAddVulnWeb

        for i in self.items_selected:
            callback(i.object, *args[1:])

    def _listVulns(self,item):
        if item is not None and item.object is not None:
            dialog = VulnsDialog(parent=self, model_object=item.object)
            dialog.exec_loop()

    def _listVulnsCvs(self,item):
        vulns=""
        hosts=[]
        for k in self._host_items.keys():
            hosts.append(self._host_items[k].object)

        filename =  qt.QFileDialog.getSaveFileName(
                    "/tmp",
                    "Vulnerability CVS  (*.csv)",
                    None,
                    "save file dialog",
                    "Choose a file to save the vulns" )
        from exporters.tofile import CSVVulnStatusReport
        CSVVulnStatusReport(path = filename, 
                            modelobjects = hosts).createCSVVulnStatusReport() 

    def _importVulnsCvs(self,item):
        filename =  qt.QFileDialog.getOpenFileName(
                    CONF.getDefaultTempPath(),
                    "Csv vulnerability file  (*.*)",
                    None,
                    "open file dialog",
                    "Choose a vulnerability file" );
        
        if os.path.isfile(filename):
            with open(filename) as f:
                data = f.read()
            f.close()

            for l in data.split("\n"):
                api.devlog(l)
                if re.search("^#",l):
                    api.devlog("ERROR FILE")
                    continue
                
                d = l.split("|")
                if len(d) <8:
                    api.log("Error vuln line: ("+l+")" )
                else:
                    self._newVulnImport(d[1],d[2],d[3],d[4],d[5],d[6],d[7])

    def _newVulnImport(self,ip,port,protocol,name,desc,severity,type):
        if port == "": #vuln host
            h_id = guiapi.createAndAddHost(ip)
            v_id = guiapi.createAndAddVulnToHost(h_id, name, desc, [],severity)
        else: #vuln port
            h_id = guiapi.createAndAddHost(ip)
            if self._isIPV4(ip):
                i_id = guiapi.createAndAddInterface(h_id,ip,ipv4_address=ip)
            else:
                i_id = guiapi.createAndAddInterface(h_id,ip,ipv6_address=ip)
            s_id = guiapi.createAndAddServiceToInterface(h_id,i_id,port,protocol,ports=[port])
            if type == "2":
                v_id = guiapi.createAndAddVulnWebToService(h_id,s_id, name, desc, [], severity, "/", "/")
            else:                
                v_id = guiapi.createAndAddVulnToService(h_id,s_id, name, desc, [],severity)

        api.devlog("type:" + type)
                                   
    def _isIPV4(self, ip):
        if len(ip.split(".")) == 4:
            return True
        else:
            return False

    def _listNotes(self, item):
        if item is not None and item.object is not None:                                                  
            dialog = NotesDialog(parent=self, model_object=item.object)
            dialog.exec_loop()

    def _newNote(self, item):
        if item is not None and item.object is not None:                                                  
            dialog = NewNoteDialog(self, callback=self._newNoteSelectedCallback)
            dialog.exec_loop()

    def _newNoteSelectedCallback(self, name, text):
        for i in self.items_selected:
            if i.type == "Host":
                api.devlog("newNotecallbackHost %s " % (i.object.name))
                guiapi.createAndAddNoteToHost(i.object.getID(), name, text)
            elif i.type == "Application":
                _parent=i.object.getParent()
                api.devlog("newNotecallbackApplication %s " % (i.object.name))
                guiapi.createAndAddNoteToApplication(_parent.getID(), i.object.getID(), name, text)
            elif i.type == "Interface":
                _parent=i.object.getParent()
                api.devlog("newNotecallbackInterface %s " % (i.object.name))
                guiapi.createAndAddNoteToInterface(_parent.getID(), i.object.getID(), name, text)
            elif i.type == "Service":
                _parent=i.object.getParent().getParent()
                api.devlog("newNotecallbackService %s " % (i.name))
                guiapi.createAndAddNoteToService(_parent.getID(), i.object.getID(), name, text)

    def _listCreds(self, item):
        if item is not None and item.object is not None:
            dialog = CredsDialog(parent=self, model_object=item.object)
            dialog.exec_loop()

    def _newCred(self, item):
        api.devlog("newCred")
        dialog = NewCredDialog(self, self._newCredSelectedCallback)
        dialog.exec_loop()

    def _importCreds(self, item):
        filename =  qt.QFileDialog.getOpenFileName(
                    CONF.getDefaultTempPath(),
                    "Csv user,pass or user:pass  (*.*)",
                    None,
                    "open file dialog",
                    "Choose a password file" );
        
        if os.path.isfile(filename):
            with open(filename) as f:
                data = f.read()
            f.close()

            for l in data.split():
                api.devlog(l)
                if re.search("^#",l):
                    api.devlog("ERROR FILE")
                    continue
                
                d = l.split(",")
                if len(d)<=1:
                    d = l.split(":")
                
                api.devlog(d)
                if len(d) <=1:
                    api.devlog("Error password line: ("+l+")" )
                else:
                    self._newCredSelectedCallback(d[0],d[1])

    def _newCredSelectedCallback(self,username,password):

        for i in self.items_selected:
            if i.type in ['Host','Service']:
                guiapi.createAndAddCred(i.object,username,password)

    def _showWorkspaceProperties(self, item):
        if item.object is not None:
            d = WorkspacePropertiesDialog(self, "Workspace Properties", workspace=item.object)
            d.exec_loop()

    def _modelObjectViewUpdater(self): 
        if len(self.__pendingModelObjectRedraws):
            self.update(self.__pendingModelObjectRedraws.pop().hosts)
            self.__pendingModelObjectRedraws[:] = []

    def customEvent(self, event):
        if event.type() == UPDATEMODEL_ID:
            self.__pendingModelObjectRedraws.append(event)

        elif event.type() == RENAMEHOSTSROOT_ID:
            self.renameRootItem(event.name)

        elif event.type() == DIFFHOSTS_ID:
            self._diffHosts(event.old_host, event.new_host)

        elif event.type() == CLEARHOSTS_ID:
            self.clearTree()

        elif event.type() == WORKSPACE_CHANGED:
            self.workspaceChanged(event.workspace, event.workspace_type)

        elif event.type() == CONFLICT_UPDATE:
            self.updateWorkspaceName(event.nconflicts)

        elif event.type() == RESOLVECONFLICTS_ID:
            self.showResolveConflictDialog(event.conflicts)

        elif event.type() == ADDHOST:
            self._addHost(event.host)
            self.setReindex()

        elif event.type() == DELHOST:
            self._removeHost(event.host_id)
            self.setReindex()

        elif event.type() == EDITHOST:
            self._editHost(event.host)
            self.setReindex()


    def _setupContextPopups(self):
        """
        Configures a context popup menu for each kind of item shown in the tree.
        This is done because different options may be needed for each item
        """
                         
        popup = qt.QPopupMenu(self)
                                      
                                             
                                            
        popup.insertSeparator()
        popup.insertItem('Resolve Conflicts', 303)
        popup.insertItem('Save Vulns CSV', 402)
        popup.insertItem('Import Vulns CSV', 403)
                                
                                              
        popup.insertSeparator()
        popup.insertItem('Add Host', 800)

        self.contextpopups["Workspace"] = popup

        self.contextpopups["Category_General"] = self.contextpopups["Workspace"]

                                
        popup = qt.QPopupMenu(self)
                                                  
                                
                                       

        self.contextpopups["Category_Applications"] = popup

                              
        popup = qt.QPopupMenu(self)
        popup.insertItem('Add Interfaces', 600)
                                
                                       

        self.contextpopups["Category_Interfaces"] = popup

                        
                                     
                                                     
                                 
                                              
                                 
                                                   
                                                      
                                 
                                           
                                             
                                 
                                        

                                                   

               
        popup = qt.QPopupMenu(self)
        popup.insertItem('Delete Host', 802)
        popup.insertSeparator()
        popup.insertItem('Add Interface', 600)
        popup.insertSeparator()
        popup.insertItem('New Vulnerability',400)
        popup.insertItem('List Vulnerabilities',401)
        popup.insertSeparator()
        popup.insertItem('New note', 500)
        popup.insertItem('Show notes', 501)
        popup.insertSeparator()
        popup.insertItem('New Credential', 550)
        popup.insertItem('Show Credentials', 551)
        popup.insertItem('Import Creds', 561)
                                
                                       

        self.contextpopups["Host"] = popup

                    
        popup = qt.QPopupMenu(self)
        popup.insertItem('Delete Interface', 602)
        popup.insertSeparator()
        popup.insertItem('Add Service', 200)
        popup.insertSeparator()
        popup.insertItem('New Vulnerability',400)
        popup.insertItem('List Vulnerabilities',401)
        popup.insertSeparator()
        popup.insertItem('New note', 500)
        popup.insertItem('Show notes', 501)
                                
                                       

        self.contextpopups["Interface"] = popup

                  
        popup = qt.QPopupMenu(self)
        popup.insertItem('Delete Service', 202)
        popup.insertSeparator()
        popup.insertItem('New Vulnerability',400)
        popup.insertItem('List Vulnerabilities',401)
        popup.insertSeparator()
        popup.insertItem('New note', 500)
        popup.insertItem('Show notes', 501)
        popup.insertSeparator()
        popup.insertItem('New Credential', 550)
        popup.insertItem('Show Credentials', 551)
        popup.insertItem('Import Creds', 561)
                                
                                       

        self.contextpopups["Service"] = popup

                       
                       
                       

                                


                     
        popup = qt.QPopupMenu(self)
        popup.insertItem('Delete Items', 202)
        popup.insertSeparator()
        popup.insertItem('New Vulnerability Items',400)
        popup.insertSeparator()
        popup.insertItem('New note Items', 500)
        popup.insertSeparator()
        popup.insertItem('New Credential', 550)
        popup.insertItem('Import Creds', 561)

        self.contextpopups["Service_Host"] = popup

                              
                        
        popup = qt.QPopupMenu(self)
        popup.insertItem('Add Service', 200)
        popup.insertSeparator()
        popup.insertItem('Delete Items', 202)
        popup.insertSeparator()
        popup.insertItem('New Vulnerability Items',400)
        popup.insertSeparator()
        popup.insertItem('New note Items', 500)
        popup.insertSeparator()
        popup.insertItem('New Credential', 550)
        popup.insertItem('Import Creds', 561)
                                
                                       

        self.contextpopups["ServiceHost_Interface"] = popup

                                    
        popup = qt.QPopupMenu(self)
                                      
                                             
        popup.insertItem('Properties', 302)
        popup.insertSeparator()
        popup.insertItem('Add Host', 800)
        popup.insertSeparator()
        popup.insertItem('Add Service', 200)
        popup.insertSeparator()
        popup.insertItem('Delete Items', 202)
        popup.insertSeparator()
        popup.insertItem('New Vulnerability Items',400)
        popup.insertSeparator()
        popup.insertItem('New note Items', 500)
        popup.insertSeparator()
        popup.insertItem('Add Service', 200)
        popup.insertSeparator()
        popup.insertItem('New Credential', 550)
        popup.insertItem('Import Creds', 561)
                                
                                       
        self.contextpopups["CategoryWorkspace_Interface"] = popup

                                      
        popup = qt.QPopupMenu(self)
                                      
                                             
        popup.insertItem('Properties', 302)
        popup.insertSeparator()
        popup.insertItem('Add Host', 800)
        popup.insertSeparator()
        popup.insertItem('Delete Items', 202)
        popup.insertSeparator()
        popup.insertItem('New Vulnerability Items',400)
        popup.insertSeparator()
        popup.insertItem('New note Items', 500)
        popup.insertSeparator()
        popup.insertItem('New Credential', 550)
        popup.insertItem('Import Creds', 561)
                                
                                       
        self.contextpopups["CategoryWorkspace_ServiceHost"] = popup


                                    
                              
                                                

                                                                                             
                                                             
                                                                                       
                                                                                       
    def _setupContextDispatchers(self):
        """
        Configures a context dispatcher for each kind of item shown in the tree.
        This is done because different options may be needed for each item
        """

        self.contextdispatchers[100] = self._newCategory
        self.contextdispatchers[102] = self._delCategorymenu

        self.contextdispatchers[200] = self._newService
        self.contextdispatchers[202] = self._delService

                                                           
                                                           
        self.contextdispatchers[302] = self._showWorkspaceProperties
        self.contextdispatchers[303] = self._resolveConflicts

        self.contextdispatchers[400] = self._newVuln
        self.contextdispatchers[401] = self._listVulns
        self.contextdispatchers[402] = self._listVulnsCvs
        self.contextdispatchers[403] = self._importVulnsCvs

        self.contextdispatchers[500] = self._newNote
        self.contextdispatchers[501] = self._listNotes

        self.contextdispatchers[550] = self._newCred
        self.contextdispatchers[551] = self._listCreds
        self.contextdispatchers[561] = self._importCreds

        self.contextdispatchers[600] = self._newInterface
        self.contextdispatchers[602] = self._delInterface

        self.contextdispatchers[800] = self._newHost
        self.contextdispatchers[802] = self._delHost


    def renameRootItem(self, new_name):
        self.rootitem.setText(0, new_name)
Exemple #4
0
class HostsBrowser(qt.QVBox):
    """Tree view to display Hosts"""

    def __init__(self, parent, model_controller, caption):
        qt.QVBox.__init__(self, parent)

        self._model_controller = model_controller

        self.modelUpdateTimer = qt.QTimer(self)
       
        self.__pendingModelObjectRedraws = []

        self.reindex_flag_lock = Lock()
        self.reindex_flag = False

        self.connect( self.modelUpdateTimer, qt.SIGNAL("timeout()"), self._modelObjectViewUpdater)
                                        
        self.modelUpdateTimer.start( 1000  , False)
                                                                                 

        self.setName(caption) if caption else self.setName("")

        self.setFrameStyle(qt.QFrame.Panel | qt.QFrame.Plain)
        self.setLineWidth(0)

        self._host_items = {}

                                                                                                   
        self._category_items = {}

                                                                                                
                                                                        
        self._category_tree = {}

        self.contextpopups = {}
        self._setupContextPopups()

        self.contextdispatchers = {}

                       
        self._filter = ""
        self.ix = None

        self._setupContextDispatchers()

        split = qt.QSplitter(self)
        split.setOrientation(qt.QSplitter.Vertical)

        lv = self.listview = ModelObjectListView(split)
                                     
                                       
                                         
        lv.setRootIsDecorated(True)

                                               
        self.connect( lv, qt.SIGNAL("selectionChanged()"), self._itemSelected )
        self.connect( lv, qt.SIGNAL("rightButtonPressed(QListViewItem *,const QPoint&,int)"), self._showContextMenu )
                                                        
        lv.addColumn("Hosts")
        lv.setColumnWidthMode(0,qt.QListView.Maximum)
                                                                                    

                         
        lv.setTreeStepSize(20)

                                                                           
                                                                                                  
                                                                
                                                             
        self.rootitem = None

                                            
               

                                                                           
        self.details_table = EditionTable(split)
        hbox = qt.QHBox(self)
        self.object_label = qt.QLabel("", hbox)
        self.object_label.setMinimumSize(qt.QSize(50, 25))
        self.save_button = SaveButton(hbox, self._item_save)
        self._save_callback = None

        self.prefchilds = []

                              
                                                       

    def load(self, workspace):
        self.rootitem = WorkspaceListViewItem(self.listview, workspace)
        self.listview.setSelected(self.rootitem, True)

    def update(self, hosts):
        self.clearTree()
        self.redrawTree(hosts)
                                         
    def sizeHint(self):
        """Returns recommended size of dialog."""
        return qt.QSize(70, 200)

    def resizeEvent (self, event ):
                                                                  
                                                           
                                                                 
                              
        self.listview.setColumnWidth(0,self.size().width()-7)
                                                                              
                                                                       

    def clearTree(self):
        """
        clear the complete host tree
        """
        self._clearBranch(self.rootitem)
        self._host_items.clear()

    def _clearBranch(self, root):
        """
        clear a branch based on the root provided.
        """
        if root is not None:
            i = root.firstChild()
            items_to_remove = []
            while i is not None:
                items_to_remove.append(i)
                i = i.nextSibling()

            for i in items_to_remove:
                if i.type == "Category":
                    self._delCategory(i.name)
                elif i.type == "Host":
                    category_item = i.parent()
                    self._delHostFromCategory(i.object, category_item.name)

    def redrawTree(self, hosts):
        dialog = qt.QProgressDialog(self, "Loading workspace...", True)
        dialog.setCaption("Please wait")
        dialog.setLabelText("Loading workspace...")
        dialog.setTotalSteps(len(hosts) + 1)
        i = 1
        for host in hosts:
            dialog.setProgress(i)
            category = host.getCurrentCategory()
            self._addCategory(category)
            self._addHostToCategory(host, category)
            i += 1
        for ci in self._category_items.values():
            ci.setOpen(True)

        self.createIndex()
        dialog.setProgress(i)
        self.filterTree(self._filter)
        # we need to make sure that the dialog is closed
        rem = dialog.totalSteps() - i
        if rem > 0:
            dialog.setProgress(i + rem)

    def setReindex(self):
        self.reindex_flag_lock.acquire()
        if not self.reindex_flag:
            self.reindex_flag = True
        self.reindex_flag_lock.release()

    def reindex(self):
        self.reindex_flag_lock.acquire()
        if self.reindex_flag:
            self.createIndex()
            self.reindex_flag = False
        self.reindex_flag_lock.release()

    def filterTree(self, mfilter=""):
        self.reindex()
        hosts=[]
        viewall=False
        self._filter=mfilter

        for k in self._host_items.keys():
            hosts.append(self._host_items[k].object)

        if self._filter:
            hosts=self._filterHost(hosts)
        else:
            viewall=True
            hosts=[]

                                
                    

        for k in self._host_items.keys():
                                                  
            if (self._host_items[k].object.name in hosts) or viewall==True:
                self._host_items[k].setVisible(True)
            else:
                self._host_items[k].setVisible(False)


    def _filterHost(self,hosts):
                                  

        from whoosh.qparser import QueryParser
        with self.ix.searcher() as searcher:
            query = QueryParser("ip", self.ix.schema).parse(self._filter)
            results = searcher.search(query, limit=None)
                           
                        
                          
            hostv={}
            for r in results:
                hostv[r['ip']]=1

        return hostv

    def createIndex(self):
        hosts = self._model_controller.getAllHosts()
        schema = Schema(ip=TEXT(stored=True),
                        hostname=TEXT(stored=True),
                        mac=TEXT(stored=True),
                        os=TEXT(stored=True),
                        port=TEXT(stored=True),
                        srvname=TEXT(stored=True),
                        srvstatus=TEXT(stored=True),
                        vulnn=TEXT(stored=True),
                        namen=TEXT(stored=True),
                        owned=BOOLEAN,
                        cred=BOOLEAN,
                        vuln=BOOLEAN,
                        note=BOOLEAN)

        indexdir=CONF.getDataPath() + "/indexdir"
        if not os.path.exists(indexdir):
            os.mkdir(indexdir)

        self.ix = create_in(indexdir, schema)
        for host in hosts:
            self.indexHost(host)

    def indexHost(self, host):
        writer = self.ix.writer()
        writer.add_document(ip=unicode(host.name), os=unicode(host.getOS()),
                            owned=host.isOwned(),
                            vuln=True if host.vulnsCount() > 0 else False,
                            note=True if len(host.getNotes()) > 0 else False)

        for i in host.getAllInterfaces():
            for h in i._hostnames:
                writer.add_document(ip=unicode(host.name),
                                    hostname=unicode(h),
                                    mac=unicode(i.getMAC()))

        for v in host.getVulns():
            writer.add_document(ip=unicode(host.name), vulnn=unicode(v.name))

        for i in host.getAllInterfaces():
            for s in i.getAllServices():
                for v in s.getVulns():
                    writer.add_document(ip=unicode(host.name),
                                        vulnn=unicode(v.name),
                                        srvname=unicode(s.getName()))
                for p in s.getPorts():
                    writer.add_document(
                        ip=unicode(host.name),
                        port=unicode(str(p)),
                        owned=s.isOwned(),
                        vuln=True if s.vulnsCount() > 0 else False,
                        note=True if len(s.getNotes()) > 0 else False,
                        cred=True if s.credsCount() > 0 else False,
                        srvname=unicode(s.getName()),
                        srvstatus=unicode(s.getStatus()))
        writer.commit()

    def removeIndexHost(self, host):
        writer = self.ix.writer()
        writer.delete_by_term('ip', host.name)
        writer.commit()

    def selectWord(self, word):
        for k in self._host_items:
            host_item = self._host_items[k]
            if host_item.text(0).encode('utf8').strip() == word.strip():
                self.listview.setSelected(host_item, True)
                self.listview.ensureItemVisible(host_item)
                break
            else:
                for i in host_item.object.getAllInterfaces():
                    if i.ipv4['address'] == word.strip():
                        self.listview.setSelected(host_item, True)
                        self.listview.ensureItemVisible(host_item)
                        break
                    elif i.ipv6['address'] == word.strip():
                        self.listview.setSelected(host_item, True)
                        self.listview.ensureItemVisible(host_item)
                        break
                    else:
                        for h in i.getHostnames():
                            if h == word.strip():
                                self.listview.setSelected(host_item, True)
                                self.listview.ensureItemVisible(host_item)
                                break

    def workspaceChanged(self, workspace):
        if self.rootitem:
            root = self.rootitem
            self.listview.takeItem(root)
            del root
        self.clearTree()
        self.load(workspace)

    def updateWorkspaceName(self, nconflicts):
        self.rootitem.updateName(nconflicts)

    def _resolveConflicts(self, item):
        guiapi.resolveConflicts()

    def showResolveConflictDialog(self, conflicts):
        if len(conflicts):
            dialog = ConflictResolutionDialog(conflicts)
            dialog.exec_loop()

    def _item_save(self):
                                                                 
                         
        if self._save_callback is not None:
            self._save_callback()

    def setSaveCallback(self, callback):
        self._save_callback = callback

    def _itemSelected(self, item=False):
        """
        this is called when a list view item is selected
        """
                           
        i = self.listview.firstChild()
        self.items_selected=[]
        self.items_type={'Host': 0, 'Workspace': 0, 'Service':0,
                         'Interface':0, 'Application':0,'Category_General':0
                         ,'Category_Applications':0,'Category_Interfaces':0}
        while i is not None:
            if i.isSelected():

                if i.type=="Category":
                    self.items_type[i.type+"_"+i.name] =self.items_type[i.type+"_"+i.name]+1
                else:
                    self.items_type[i.type] =self.items_type[i.type]+1

                self.items_selected.append(i)
            i = i.itemBelow()
            mtype={'Host': 0, 'Workspace': 0, 'Service':0, 'Interface':0, 'Application':0,'Category':0}

        self.itemselected = self.listview.currentItem()

                                                                                
        self.details_table.clear()
        editor = self.itemselected.getEditor()
        editor.fillEditionTable(self.details_table)
        self.setSaveCallback(editor.save)

    def getItemSelected(self):
        return self.itemselected

    def _addCategory(self, category):
        if category not in self._category_tree:
            self._category_tree[category] = []
            ref = CategoryListViewItem(self.rootitem, category)
            self._category_items[category] = ref
        else:
            ref = self._getCategoryListViewItem(category)
        return ref

    def _addHost(self, host):
        category = host.getCurrentCategory()
        self._addCategory(category)
        self._addHostToCategory(host, category)
        #self.removeIndexHost(host)
        #self.indexHost(host)

    def _removeHost(self, host_id):
        item = self._host_items.get(host_id, None)
        if host_id in self._host_items:
            del self._host_items[host_id]
        for category in self._category_tree.keys():
            if host_id in self._category_tree.get(category):
                self._category_tree[category].remove(host_id)
                category_item = self._getCategoryListViewItem(category)
                try:
                    category_item.takeItem(item)
                except Exception:
                    api.devlog("Exception taking item from category")

    def _editHost(self, host):
        self._removeHost(host.getID())
        self._addHost(host)

    def _addHostToCategory(self, host, category):
        category_item = self._addCategory(category)
        self._host_items[host.getID()] = HostListViewItem(category_item, host.name, host)
        self._category_tree[category].append(host.getID())

    def _delHostFromCategory(self, host, category):
        id = host.getID()
        item = self._host_items.get(id, None)
        if id in self._host_items:
            del self._host_items[id]
        if category in self._category_tree:
            if id in self._category_tree[category]:
                self._category_tree[category].remove(id)
                category_item = self._getCategoryListViewItem(category)
                api.devlog("_delHostFromCategory: about to call takeItem for category %s" % category)
                try:
                    category_item.takeItem(item)
                except Exception:
                    pass
                api.devlog("_delHostFromCategory: after takeItem")

    def _getCategoryListViewItem(self, category):
        return self._category_items.get(category, None)

    def _delCategory(self, category, recursive=False):
        if category in self._category_tree:
            if recursive:                                              
                for id in self._category_tree:
                    host_item = self._getHostListViewItem(id)
                    if host_item is not None:
                        self._delHostFromCategory(host_item.object, category)
            else:
                                                                                   
                                               
                for id in self._category_tree:
                    host_item = self._getHostListViewItem(id)
                    if host_item is not None:
                        self._moveHostToCategory(host_item.object, CONF.getDefaultCategory())

                del self._category_tree[category]
                item = self._category_items[category]
                del self._category_items[category]
                self.rootitem.takeItem(item)

    def _getHostListViewItem(self, id):
        return self._host_items.get(id, None)

    def _showContextMenu(self, item, pos, val):
        """Pop up a context menu when an item is clicked on the list view."""
        ret = None

        if item is not None:                           

                                  
                       
                                                                                                                                                            
            if self.items_type['Interface']:
                if (self.items_type['Category_General'] or self.items_type['Workspace']):
                    popname="CategoryWorkspace_Interface"
                elif (self.items_type['Host'] or self.items_type['Service']):
                    popname="ServiceHost_Interface"
                else:
                    popname=item.type

            elif (self.items_type['Host'] or self.items_type['Service']):
                if (self.items_type['Category_General'] or self.items_type['Workspace']):
                    popname="CategoryWorkspace_ServiceHost"
                elif (self.items_type['Host'] and self.items_type['Service']):
                    popname="Service_Host"
                else:
                    if item.type is "Category":
                        popname="Host"
                    else:
                        popname=item.type
            else:
                                   
                if item.type is "Category":
                    popname=item.type + "_" + item.name
                else:
                    popname=item.type

            ret = self.contextpopups[popname].exec_loop(pos)

            if ret in self.contextdispatchers:
                self.contextdispatchers[ret](item)
                  
                                                                         

            api.devlog("contextMenuEvent - item: %s - ret %s" % (self.name, ret))

              

    def _newHost(self, item):
        api.devlog("newHost")
        dialog = NewHostDialog(self, self._newHostCallback)
        dialog.exec_loop()

    def _newHostCallback(self, name, os):
        if name:
                                          
            guiapi.createAndAddHost(name, os=os)

    def _delHost(self,item):
        api.devlog("delHost")
        if item is not None and item.object is not None:                                                  
            dialog = MessageDialog(self,title="Host delete",callback=self._delSelectedCallback)
            dialog.exec_loop()

    def _delHostCallback(self, item):
        api.devlog("delcallbackHost %s " % (item.object.name))
        guiapi.delHost(item.object.getID())

    def _newInterface(self, item):
        api.devlog("newInterface")
        dialog = NewInterfaceDialog(self, self._newInterfaceCallback)
        dialog.exec_loop()

    def _newInterfaceCallback(self, name, ipv4_address, ipv6_address):
        if name and (ipv4_address or ipv6_address):
            for i in self.items_selected:
                host_id = i.object.getID()
                guiapi.createAndAddInterface(host_id, name, ipv4_address=ipv4_address, ipv6_address=ipv6_address)

    def _delInterface(self,item):
        api.devlog("delInterface")
        if item is not None and item.object is not None:                                                  
            dialog = MessageDialog(self,title="Interface delete",callback=self._delSelectedCallback)
            dialog.exec_loop()

    def _delInterfaceCallback(self, item):
        api.devlog("delcallbackInterface %s " % (item.object.name))
        _parent=item.object.getParent()
        guiapi.delInterface(_parent.getID(), item.object.getID())

    def _newService(self,item):
        api.devlog("newService")
        dialog = NewServiceDialog(self, self._newServiceSelectedCallback)
        dialog.exec_loop()

    def _newServiceSelectedCallback(self, name, protocol, ports):
        if name and protocol and ports:
            for i in self.items_selected:
                if i.type == "Interface":
                    interface_id = i.object.getID()
                    host_id = i.object.getParent().getID()
                    guiapi.createAndAddServiceToInterface(host_id, interface_id , name, protocol=protocol, ports=ports)

    def _delService(self,item):
        if item is not None and item.object is not None:                                                  
            dialog = MessageDialog(self,title="Delete Item(s)",callback=self._delSelectedCallback)
            dialog.exec_loop()

    def _delServiceCallback(self, item):
        api.devlog("delcallbackService %s " % (item.name))
        _object=item.object
        _host=_object.getParent()
        guiapi.delServiceFromHost(_host.getID(), _object.getID())

    def _delSelectedCallback(self,item):

        for i in self.items_selected:
            if i.type == "Host":
                api.devlog("delcallbackHost %s " % (i.object.name))
                guiapi.delHost(i.object.getID())
            elif i.type == "Application":
                api.devlog("delcallbackApplication %s " % (i.object.name))
                _parent=i.object.getParent()
                _object=i.object
                guiapi.delApplication(_parent.getID(),_object.getID())
            elif i.type == "Interface":
                api.devlog("delcallbackInterface %s " % (i.object.name))
                _parent=i.object.getParent()
                _object=i.object
                guiapi.delInterface(_parent.getID(), _object.getID())
            elif i.type == "Service":
                api.devlog("delcallbackService %s " % (i.name))
                _object=i.object
                parent_interface = self._getParentForType(i, "Interface").object
                parent_host = self._getParentForType(i, "Host").object
                guiapi.delServiceFromInterface(parent_host.getID(), parent_interface.getID(), _object.getID())
                                                       
        self.listview.setCurrentItem(self.rootitem)
        self._itemSelected()

    def _getParentForType(self, obj, obj_type):
        parent = obj.parent()
        if obj_type == parent.type:
            return parent
        else:
            return self._getParentForType(parent, obj_type)

    def _newCategory(self,item):
        api.devlog("newCategory")

    def _renCategory(self,item):
        api.devlog("renCategory")

    def _delCategorymenu(self,item):
        api.devlog("delCategorymenu")
        if item is not None:                                                  
            dialog = MessageDialog(self,title="Category delete",callback=self._delCategoryCallback,item=item)
            dialog.exec_loop()

    def _delCategoryCallback(self, item):
        api.devlog("delcallbackCategory %s " % (item.name))

    def _newVuln(self, item):
        api.devlog("newVuln")
        if item is not None and item.object is not None:
            vuln_web_enabled = False
            if item.object.class_signature == "Service":
                vuln_web_enabled = True
            dialog = NewVulnDialog(
                self,
                callback=self._newVulnSelectedCallback,
                vuln_web_enabled=vuln_web_enabled)
            dialog.exec_loop()

    def _newVulnSelectedCallback(self, *args):
        callback = guiapi.createAndAddVuln
        if args[0]:
            # vuln web
            callback = guiapi.createAndAddVulnWeb

        for i in self.items_selected:
            callback(i.object, *args[1:])

    def _listVulns(self,item):
        if item is not None and item.object is not None:
            dialog = VulnsDialog(parent=self, model_object=item.object)
            dialog.exec_loop()

    def _listVulnsCvs(self,item):
        vulns=""
        hosts=[]
        for k in self._host_items.keys():
            hosts.append(self._host_items[k].object)

        filename =  qt.QFileDialog.getSaveFileName(
                    "/tmp",
                    "Vulnerability CVS  (*.csv)",
                    None,
                    "save file dialog",
                    "Choose a file to save the vulns" )
        from exporters.tofile import CSVVulnStatusReport
        CSVVulnStatusReport(path = filename, 
                            modelobjects = hosts).createCSVVulnStatusReport() 

    def _importVulnsCvs(self,item):
        filename =  qt.QFileDialog.getOpenFileName(
                    CONF.getDefaultTempPath(),
                    "Csv vulnerability file  (*.*)",
                    None,
                    "open file dialog",
                    "Choose a vulnerability file" );
        
        if os.path.isfile(filename):
            with open(filename) as f:
                data = f.read()
            f.close()

            for l in data.split("\n"):
                api.devlog(l)
                if re.search("^#",l):
                    api.devlog("ERROR FILE")
                    continue
                
                d = l.split("|")
                
                if len(d) <=5:
                    api.devlog("Error vuln line: ("+l+")" )
                else:
                    self._newVulnImport(d[0],d[1],d[2],d[3],d[4],d[5],d[6])

    def _newVulnImport(self,ip,port,protocol,name,desc,severity,type):
        if port == "0": #vuln host
            h_id = guiapi.createAndAddHost(ip)
            v_id = guiapi.createAndAddVulnToHost(h_id, name, desc, [],severity)
        else: #vuln port
            h_id = guiapi.createAndAddHost(ip)
            if self._isIPV4(ip):
                i_id = guiapi.createAndAddInterface(h_id,ip,ipv4_address=ip)
            else:
                i_id = guiapi.createAndAddInterface(h_id,ip,ipv6_address=ip)
            s_id = guiapi.createAndAddServiceToInterface(h_id,i_id,port,protocol,ports=[port])
            if type == "2":
                v_id = guiapi.createAndAddVulnWebToService(h_id,s_id, name, desc, "/","/",[],severity)
            else:
                v_id = guiapi.createAndAddVulnToService(h_id,s_id, name, desc, [],severity)

        api.devlog("type:" + type)
                                   
    def _isIPV4(self, ip):
        if len(ip.split(".")) == 4:
            return True
        else:
            return False

    def _listNotes(self, item):
        if item is not None and item.object is not None:                                                  
            dialog = NotesDialog(parent=self, model_object=item.object)
            dialog.exec_loop()

    def _newNote(self, item):
        if item is not None and item.object is not None:                                                  
            dialog = NewNoteDialog(self, callback=self._newNoteSelectedCallback)
            dialog.exec_loop()

    def _newNoteSelectedCallback(self, name, text):
        for i in self.items_selected:
            if i.type == "Host":
                api.devlog("newNotecallbackHost %s " % (i.object.name))
                guiapi.createAndAddNoteToHost(i.object.getID(), name, text)
            elif i.type == "Application":
                _parent=i.object.getParent()
                api.devlog("newNotecallbackApplication %s " % (i.object.name))
                guiapi.createAndAddNoteToApplication(_parent.getID(), i.object.getID(), name, text)
            elif i.type == "Interface":
                _parent=i.object.getParent()
                api.devlog("newNotecallbackInterface %s " % (i.object.name))
                guiapi.createAndAddNoteToInterface(_parent.getID(), i.object.getID(), name, text)
            elif i.type == "Service":
                _parent=i.object.getParent().getParent()
                api.devlog("newNotecallbackService %s " % (i.name))
                guiapi.createAndAddNoteToService(_parent.getID(), i.object.getID(), name, text)

    def _listCreds(self, item):
        if item is not None and item.object is not None:
            dialog = CredsDialog(parent=self, model_object=item.object)
            dialog.exec_loop()

    def _newCred(self, item):
        api.devlog("newCred")
        dialog = NewCredDialog(self, self._newCredSelectedCallback)
        dialog.exec_loop()

    def _importCreds(self, item):
        filename =  qt.QFileDialog.getOpenFileName(
                    CONF.getDefaultTempPath(),
                    "Csv user,pass or user:pass  (*.*)",
                    None,
                    "open file dialog",
                    "Choose a password file" );
        
        if os.path.isfile(filename):
            with open(filename) as f:
                data = f.read()
            f.close()

            for l in data.split():
                api.devlog(l)
                if re.search("^#",l):
                    api.devlog("ERROR FILE")
                    continue
                
                d = l.split(",")
                if len(d)<=1:
                    d = l.split(":")
                
                api.devlog(d)
                if len(d) <=1:
                    api.devlog("Error password line: ("+l+")" )
                else:
                    self._newCredSelectedCallback(d[0],d[1])

    def _newCredSelectedCallback(self,username,password):

        for i in self.items_selected:
            if i.type in ['Host','Service']:
                guiapi.createAndAddCred(i.object,username,password)

    def _showWorkspaceProperties(self, item):
        if item.object is not None:
            api.log("Llege a showWorkspace", "ERROR")
            d = WorkspacePropertiesDialog(self, "Workspace Properties", workspace=item.object)
            d.exec_loop()

    def _modelObjectViewUpdater(self): 
        if len(self.__pendingModelObjectRedraws):
            self.update(self.__pendingModelObjectRedraws.pop().hosts)
            self.__pendingModelObjectRedraws[:] = []

    def customEvent(self, event):
        if event.type() == UPDATEMODEL_ID:
            self.__pendingModelObjectRedraws.append(event)

        elif event.type() == RENAMEHOSTSROOT_ID:
            self.renameRootItem(event.name)

        elif event.type() == DIFFHOSTS_ID:
            self._diffHosts(event.old_host, event.new_host)

        elif event.type() == CLEARHOSTS_ID:
            self.clearTree()

        elif event.type() == WORKSPACE_CHANGED:
            self.workspaceChanged(event.workspace)

        elif event.type() == CONFLICT_UPDATE:
            self.updateWorkspaceName(event.nconflicts)

        elif event.type() == RESOLVECONFLICTS_ID:
            self.showResolveConflictDialog(event.conflicts)

        elif event.type() == ADDHOST:
            self._addHost(event.host)
            self.setReindex()

        elif event.type() == DELHOST:
            self._removeHost(event.host_id)
            self.setReindex()

        elif event.type() == EDITHOST:
            self._editHost(event.host)
            self.setReindex()


    def _setupContextPopups(self):
        """
        Configures a context popup menu for each kind of item shown in the tree.
        This is done because different options may be needed for each item
        """
                         
        popup = qt.QPopupMenu(self)
                                      
                                             
                                            
        popup.insertSeparator()
        popup.insertItem('Resolve Conflicts', 303)
        popup.insertItem('Save Vulns CSV', 402)
        popup.insertItem('Import Vulns CSV', 403)
                                
                                              
        popup.insertSeparator()
        popup.insertItem('Add Host', 800)

        self.contextpopups["Workspace"] = popup

        self.contextpopups["Category_General"] = self.contextpopups["Workspace"]

                                
        popup = qt.QPopupMenu(self)
                                                  
                                
                                       

        self.contextpopups["Category_Applications"] = popup

                              
        popup = qt.QPopupMenu(self)
        popup.insertItem('Add Interfaces', 600)
                                
                                       

        self.contextpopups["Category_Interfaces"] = popup

                        
                                     
                                                     
                                 
                                              
                                 
                                                   
                                                      
                                 
                                           
                                             
                                 
                                        

                                                   

               
        popup = qt.QPopupMenu(self)
        popup.insertItem('Delete Host', 802)
        popup.insertSeparator()
        popup.insertItem('Add Interface', 600)
        popup.insertSeparator()
        popup.insertItem('New Vulnerability',400)
        popup.insertItem('List Vulnerabilities',401)
        popup.insertSeparator()
        popup.insertItem('New note', 500)
        popup.insertItem('Show notes', 501)
        popup.insertSeparator()
        popup.insertItem('New Credential', 550)
        popup.insertItem('Show Credentials', 551)
        popup.insertItem('Import Creds', 561)
                                
                                       

        self.contextpopups["Host"] = popup

                    
        popup = qt.QPopupMenu(self)
        popup.insertItem('Delete Interface', 602)
        popup.insertSeparator()
        popup.insertItem('Add Service', 200)
        popup.insertSeparator()
        popup.insertItem('New Vulnerability',400)
        popup.insertItem('List Vulnerabilities',401)
        popup.insertSeparator()
        popup.insertItem('New note', 500)
        popup.insertItem('Show notes', 501)
                                
                                       

        self.contextpopups["Interface"] = popup

                  
        popup = qt.QPopupMenu(self)
        popup.insertItem('Delete Service', 202)
        popup.insertSeparator()
        popup.insertItem('New Vulnerability',400)
        popup.insertItem('List Vulnerabilities',401)
        popup.insertSeparator()
        popup.insertItem('New note', 500)
        popup.insertItem('Show notes', 501)
        popup.insertSeparator()
        popup.insertItem('New Credential', 550)
        popup.insertItem('Show Credentials', 551)
        popup.insertItem('Import Creds', 561)
                                
                                       

        self.contextpopups["Service"] = popup

                       
                       
                       

                                


                     
        popup = qt.QPopupMenu(self)
        popup.insertItem('Delete Items', 202)
        popup.insertSeparator()
        popup.insertItem('New Vulnerability Items',400)
        popup.insertSeparator()
        popup.insertItem('New note Items', 500)
        popup.insertSeparator()
        popup.insertItem('New Credential', 550)
        popup.insertItem('Import Creds', 561)

        self.contextpopups["Service_Host"] = popup

                              
                        
        popup = qt.QPopupMenu(self)
        popup.insertItem('Add Service', 200)
        popup.insertSeparator()
        popup.insertItem('Delete Items', 202)
        popup.insertSeparator()
        popup.insertItem('New Vulnerability Items',400)
        popup.insertSeparator()
        popup.insertItem('New note Items', 500)
        popup.insertSeparator()
        popup.insertItem('New Credential', 550)
        popup.insertItem('Import Creds', 561)
                                
                                       

        self.contextpopups["ServiceHost_Interface"] = popup

                                    
        popup = qt.QPopupMenu(self)
                                      
                                             
        popup.insertItem('Properties', 302)
        popup.insertSeparator()
        popup.insertItem('Add Host', 800)
        popup.insertSeparator()
        popup.insertItem('Add Service', 200)
        popup.insertSeparator()
        popup.insertItem('Delete Items', 202)
        popup.insertSeparator()
        popup.insertItem('New Vulnerability Items',400)
        popup.insertSeparator()
        popup.insertItem('New note Items', 500)
        popup.insertSeparator()
        popup.insertItem('Add Service', 200)
        popup.insertSeparator()
        popup.insertItem('New Credential', 550)
        popup.insertItem('Import Creds', 561)
                                
                                       
        self.contextpopups["CategoryWorkspace_Interface"] = popup

                                      
        popup = qt.QPopupMenu(self)
                                      
                                             
        popup.insertItem('Properties', 302)
        popup.insertSeparator()
        popup.insertItem('Add Host', 800)
        popup.insertSeparator()
        popup.insertItem('Delete Items', 202)
        popup.insertSeparator()
        popup.insertItem('New Vulnerability Items',400)
        popup.insertSeparator()
        popup.insertItem('New note Items', 500)
        popup.insertSeparator()
        popup.insertItem('New Credential', 550)
        popup.insertItem('Import Creds', 561)
                                
                                       
        self.contextpopups["CategoryWorkspace_ServiceHost"] = popup


                                    
                              
                                                

                                                                                             
                                                             
                                                                                       
                                                                                       
    def _setupContextDispatchers(self):
        """
        Configures a context dispatcher for each kind of item shown in the tree.
        This is done because different options may be needed for each item
        """

        self.contextdispatchers[100] = self._newCategory
        self.contextdispatchers[102] = self._delCategorymenu

        self.contextdispatchers[200] = self._newService
        self.contextdispatchers[202] = self._delService

                                                           
                                                           
        self.contextdispatchers[302] = self._showWorkspaceProperties
        self.contextdispatchers[303] = self._resolveConflicts

        self.contextdispatchers[400] = self._newVuln
        self.contextdispatchers[401] = self._listVulns
        self.contextdispatchers[402] = self._listVulnsCvs
        self.contextdispatchers[403] = self._importVulnsCvs

        self.contextdispatchers[500] = self._newNote
        self.contextdispatchers[501] = self._listNotes

        self.contextdispatchers[550] = self._newCred
        self.contextdispatchers[551] = self._listCreds
        self.contextdispatchers[561] = self._importCreds

        self.contextdispatchers[600] = self._newInterface
        self.contextdispatchers[602] = self._delInterface

        self.contextdispatchers[800] = self._newHost
        self.contextdispatchers[802] = self._delHost


    def renameRootItem(self, new_name):
        self.rootitem.setText(0, new_name)