from FindForm import FindForm from AlertListView import AlertListView from qt import * from string import find from Prelude import * from _prelude import * MARGIN = 5 SPACING = 5 class Simple(QWidget): def createSeverityWidgets(self, layout): layout.addSpacing(20) label = QLabel("Severity:", self) layout.addWidget(label) self.severityComboBox = QComboBox(self) self.severityComboBox.insertItem("All") self.severityComboBox.insertItem(QPixmap("images/impact_severity_low.png"), "low") self.severityComboBox.insertItem(QPixmap("images/impact_severity_medium.png"), "medium") self.severityComboBox.insertItem(QPixmap("images/impact_severity_high.png"), "high") layout.addWidget(self.severityComboBox) layout.addStretch(1) def createClassificationWidgets(self, layout): label = QLabel("Classification:", self) layout.addWidget(label) self.classificationLineEdit = QLineEdit(self) layout.addWidget(self.classificationLineEdit) layout.addSpacing(20) def createSourceWidgets(self, layout): groupbox = QGroupBox("Source", self) layout.addWidget(groupbox) groupbox.setColumnLayout(0, Qt.Vertical) groupbox.layout().setSpacing(6) topLayout = QHBoxLayout(groupbox.layout()) leftLayout = QVBoxLayout(topLayout) for name in "address", "protocol", "process name": label = QLabel(name, groupbox) leftLayout.addWidget(label) rightLayout = QVBoxLayout(topLayout) self.sourceAddressLineEdit = QLineEdit(groupbox) rightLayout.addWidget(self.sourceAddressLineEdit) subRightLayout = QHBoxLayout(rightLayout) self.sourceProtocolComboBox = QComboBox(groupbox) subRightLayout.addWidget(self.sourceProtocolComboBox) for protocol in "All", "TCP", "UDP", "ICMP": self.sourceProtocolComboBox.insertItem(protocol) subRightLayout.addStretch() label = QLabel("port", groupbox) subRightLayout.addWidget(label) self.sourcePortSpinBox = QSpinBox(0, 65535, 1, groupbox) subRightLayout.addWidget(self.sourcePortSpinBox) self.sourceProcessLineEdit = QLineEdit(groupbox) rightLayout.addWidget(self.sourceProcessLineEdit) def createTargetWidgets(self, layout): groupbox = QGroupBox("Target", self) layout.addWidget(groupbox) groupbox.setColumnLayout(0, Qt.Vertical) groupbox.layout().setSpacing(6) topLayout = QHBoxLayout(groupbox.layout()) leftLayout = QVBoxLayout(topLayout) for name in "address", "protocol", "process name": label = QLabel(name, groupbox) leftLayout.addWidget(label) rightLayout = QVBoxLayout(topLayout) self.targetAddressLineEdit = QLineEdit(groupbox) rightLayout.addWidget(self.targetAddressLineEdit) subRightLayout = QHBoxLayout(rightLayout) self.targetProtocolComboBox = QComboBox(groupbox) subRightLayout.addWidget(self.targetProtocolComboBox) for protocol in "All", "TCP", "UDP", "ICMP": self.targetProtocolComboBox.insertItem(protocol) subRightLayout.addStretch() label = QLabel("port", groupbox) subRightLayout.addWidget(label) self.targetPortSpinBox = QSpinBox(0, 65535, 1, groupbox) subRightLayout.addWidget(self.targetPortSpinBox) self.targetProcessLineEdit = QLineEdit(groupbox) rightLayout.addWidget(self.targetProcessLineEdit) def createSensorWidgets(self, layout): label = QLabel("Sensor name", self) layout.addWidget(label) self.sensorLineEdit = QLineEdit(self) layout.addWidget(self.sensorLineEdit) layout.addStretch() layout.setSpacing(10) def createTimeWidgets(self, layout): layout = QGridLayout(layout, 2, 3) layout.addWidget(QLabel("From", self), 0, 0) self.detectTimeFromEdit = QDateTimeEdit(self) layout.addWidget(self.detectTimeFromEdit, 0, 1) self.detectTimeFromCheckBox = QCheckBox(self) layout.addWidget(self.detectTimeFromCheckBox, 0, 2) layout.addWidget(QLabel("To", self), 1, 0) self.detectTimeToEdit = QDateTimeEdit(self) layout.addWidget(self.detectTimeToEdit, 1, 1) self.detectTimeToCheckBox = QCheckBox(self) layout.addWidget(self.detectTimeToCheckBox, 1, 2) def initWidgets(self): self.comboBoxWidgets = (self.severityComboBox, self.sourceProtocolComboBox, self.targetProtocolComboBox) self.spinBoxWidgets = (self.sourcePortSpinBox, self.targetPortSpinBox) self.lineEditWidgets = (self.classificationLineEdit, self.sourceAddressLineEdit, self.sourceProcessLineEdit, self.targetAddressLineEdit, self.targetProcessLineEdit, self.sensorLineEdit) self.dateTimeEditWidgets = (self.detectTimeFromEdit, self.detectTimeToEdit) self.dateTimeCheckBoxWidgets = (self.detectTimeFromCheckBox, self.detectTimeToCheckBox) self.inputWidgetEmpty = { } for widget in self.comboBoxWidgets + self.spinBoxWidgets + self.lineEditWidgets + self.dateTimeCheckBoxWidgets: self.inputWidgetEmpty[widget] = True for widget in self.comboBoxWidgets: self.connect(widget, SIGNAL("activated(int)"), self.comboBoxChanged) for widget in self.spinBoxWidgets: self.connect(widget, SIGNAL("valueChanged(int)"), self.spinBoxChanged) for widget in self.lineEditWidgets: self.connect(widget, SIGNAL("textChanged(const QString &)"), self.lineEditChanged) for widget in self.detectTimeFromEdit, self.detectTimeToEdit: widget.setEnabled(False) widget.dateEdit().setOrder(QDateEdit.YMD) self.resetDateTimeEdits() self.connect(self.detectTimeFromCheckBox, SIGNAL("toggled(bool)"), self.detectTimeFromEnabledChange) self.connect(self.detectTimeToCheckBox, SIGNAL("toggled(bool)"), self.detectTimeToEnabledChange) def __init__(self, parent): QWidget.__init__(self, parent.tab) parent.tab.addTab(self, "Simple") self.parent = parent tabLayout = QVBoxLayout(self) layout = QHBoxLayout(tabLayout) layout.setMargin(MARGIN) self.createSeverityWidgets(layout) self.createClassificationWidgets(layout) groupBoxLayout = QHBoxLayout(tabLayout) groupBoxLayout.setSpacing(SPACING) groupBoxLayout.setMargin(MARGIN) self.createSourceWidgets(groupBoxLayout) self.createTargetWidgets(groupBoxLayout) layout = QHBoxLayout(tabLayout) layout.setMargin(MARGIN) self.createSensorWidgets(layout) self.createTimeWidgets(layout) self.initWidgets() def resetLineEdits(self): for widget in self.lineEditWidgets: widget.clear() def resetComboBoxes(self): for widget in self.comboBoxWidgets: widget.setCurrentItem(0) self.updateSearchButton(True, widget) def resetSpinBoxes(self): for widget in self.spinBoxWidgets: widget.setValue(0) def resetDateTimeEdits(self): dateTime = QDateTime() dateTime.setTime_t(0, Qt.UTC) for widget in self.dateTimeEditWidgets: widget.setDateTime(dateTime) def resetCheckBoxes(self): for widget in self.dateTimeCheckBoxWidgets: widget.setChecked(False) def reset(self): self.resetLineEdits() self.resetComboBoxes() self.resetSpinBoxes() self.resetDateTimeEdits() self.resetCheckBoxes() def updateSearchButton(self, empty, sender=None): if not sender: sender = self.parent.sender() self.inputWidgetEmpty[sender] = empty if not empty: self.parent.searchButton.setEnabled(True) if not False in self.inputWidgetEmpty.values(): self.parent.searchButton.setEnabled(False) def lineEditChanged(self, value): self.updateSearchButton(len(value) == 0) def comboBoxChanged(self, value): self.updateSearchButton(value == 0) def spinBoxChanged(self, value): self.updateSearchButton(value == 0) def detectTimeFromEnabledChange(self, checked): self.detectTimeFromEdit.setEnabled(checked) def detectTimeEnabledChange(self, widget, checked): widget.setEnabled(checked) if checked: widget.setDateTime(QDateTime(QDate.currentDate())) else: dateTime = QDateTime() dateTime.setTime_t(0, Qt.LocalTime) widget.setDateTime(dateTime) self.updateSearchButton(not checked, widget) def detectTimeFromEnabledChange(self, checked): self.detectTimeEnabledChange(self.detectTimeFromEdit, checked) def detectTimeToEnabledChange(self, checked): self.detectTimeEnabledChange(self.detectTimeToEdit, checked) def getDateTime(self, widget): if not widget.isEnabled(): return None dateTime = widget.dateTime() if dateTime.isNull() or not dateTime.isValid(): return None return dateTime.toString("yyyy-MM-dd hh:mm:ss") def isEmpty(self): return (not False in self.inputWidgetEmpty.values()) def getCriteria(self): criteria = IDMEFCriteria() severity = self.severityComboBox.currentItem() try: criteria &= IDMEFCriteria("alert.assessment.impact.severity == %s" % { 1: 'low', 2: 'medium', 3: 'high' }[severity]) except KeyError: pass classification = self.classificationLineEdit.text() if classification: criteria &= IDMEFCriteria("alert.classification.name substr '%s'" % classification) address = self.sourceAddressLineEdit.text() if address: criteria &= IDMEFCriteria("alert.source.node.address.address substr '%s'" % address) process = self.sourceProcessLineEdit.text() if process: criteria &= IDMEFCriteria("alert.source.process.name substr '%s'" % process) protocol = self.sourceProtocolComboBox.currentText() if protocol and protocol != "All": criteria &= IDMEFCriteria("alert.source.service.protocol substr '%s'" % protocol) port = self.sourcePortSpinBox.value() if port: criteria &= IDMEFCriteria("alert.source.service.port == %d" % port) address = self.targetAddressLineEdit.text() if address: criteria &= IDMEFCriteria("alert.target.node.address.address substr '%s'" % address) process = self.targetProcessLineEdit.text() if process: criteria &= IDMEFCriteria("alert.target.process.name substr '%s'" % process) protocol = self.targetProtocolComboBox.currentText() if protocol and protocol != "All": criteria &= IDMEFCriteria("alert.target.service.protocol substr '%s'" % protocol) port = self.targetPortSpinBox.value() if port: criteria &= IDMEFCriteria("alert.target.service.port == %d" % port) sensor = self.sensorLineEdit.text() if sensor: criteria &= IDMEFCriteria("alert.analyzer.model substr '%s'" % sensor) from_ = self.getDateTime(self.detectTimeFromEdit) if from_: criteria &= IDMEFCriteria("alert.detect_time >= '%s'" % from_) to = self.getDateTime(self.detectTimeToEdit) if to: criteria &= IDMEFCriteria("alert.detect_time <= '%s'" % to) return criteria class AdvancedCriterion: height = 0 def __init__(self, scrollview, vlayout, name, object, prev): self.scrollview = scrollview self.name = name self.object = object self.type = get_idmef_object_type(object) width = scrollview.visibleWidth() layout = QHBoxLayout(vlayout) if prev: self.createOperatorComboBox(width, layout) else: self.operatorComboBox = None layout.addStretch(1) self.createObjectNameLineEdit(width, layout) self.createRelationComboBox(width, layout) self.createValueWidget(width, layout) self.resize() scrollview.verticalScrollBar().setValue(scrollview.verticalScrollBar().maxValue() + 1) def __del__(self): widgets = [self.objectNameLineEdit, self.relationComboBox, self.valueWidget] if self.operatorComboBox: widgets.append(self.operatorComboBox) for widget in widgets: widget.close() def resize(self): widgets = [self.objectNameLineEdit, self.relationComboBox, self.valueWidget] if self.operatorComboBox: widgets.append(self.operatorComboBox) maxHeight = 0 for widget in widgets: height = widget.height() if height > maxHeight: maxHeight = height for widget in widgets: widget.setFixedHeight(maxHeight) AdvancedCriterion.height += maxHeight self.scrollview.resizeContents(self.scrollview.contentsWidth(), AdvancedCriterion.height) def createOperatorComboBox(self, width, layout): self.operatorComboBox = QComboBox(self.scrollview) self.operatorComboBox.setFixedWidth(width * 0.2) for operator in "and", "or": self.operatorComboBox.insertItem(operator) self.scrollview.addChild(self.operatorComboBox, 0, AdvancedCriterion.height) layout.addWidget(self.operatorComboBox) self.operatorComboBox.show() def createObjectNameLineEdit(self, width, layout): self.objectNameLineEdit = QLineEdit(self.scrollview) self.objectNameLineEdit.setFixedWidth(width * 0.2) self.objectNameLineEdit.setReadOnly(True) self.objectNameLineEdit.setText(self.name) self.scrollview.addChild(self.objectNameLineEdit, width * 0.2, AdvancedCriterion.height) layout.addWidget(self.objectNameLineEdit) self.objectNameLineEdit.show() def createRelationComboBox(self, width, layout): self.relationComboBox = QComboBox(self.scrollview) self.relationComboBox.setFixedWidth(width * 0.1) self.relationComboBox.insertItem("=") if self.type != "enum": for relation in "!=", ">", ">=", "<", "<=": self.relationComboBox.insertItem(relation) if self.type == "string": self.relationComboBox.insertItem("=~") self.scrollview.addChild(self.relationComboBox, width * 0.4, AdvancedCriterion.height) layout.addWidget(self.relationComboBox) self.relationComboBox.show() def createValueWidget(self, width, layout): if self.type == "time": self.valueWidget = QDateTimeEdit(self.scrollview) self.valueWidget.dateEdit().setOrder(QDateEdit.YMD) self.valueWidget.setDateTime(QDateTime(QDate.currentDate())) elif self.type == "enum": self.valueWidget = QComboBox(self.scrollview) enum_types = { "additional_data.type": ("string", "boolean", "byte", "character", "date_time", "integer", "ntpstamp", "portlist", "real", "xml"), "classification.origin": ("unknown", "bugtraqid", "cve", "vendor_specific"), "userid.type": ("original_user", "current_user", "target_user", "user_privs", "current_group", "group_privs", "other_privs"), "user.category": ("unknown", "application", "os_device"), "address.category": ("unknown", "atm", "e_mail", "lotus_notes", "mac", "sna", "vm", "ipv4_addr", "ipv4_addr_hex", "ipv4_net", "ipv4_net_mask", "ipv6_addr", "ipv6_addr_hex", "ipv6_net", "ipv6_net_mask"), "service.type": ("no_specific_service", "web_service", "snmp_service"), "node.category": ("unknown", "ads", "afs", "coda", "dfs", "dns", "hosts", "kerberos", "nds", "nis", "nisplus", "nt", "wfw"), "spoofed": ("unknown", "yes", "no"), "file.category": ("current", "original"), "linkage.category": ("hard_link", "mount_point", "reparse_point", "shortcut", "stream", "symbolic_link"), "impact.severity": ("low", "medium", "high"), "impact.completion": ("failed", "succeeded"), "impact.type": ("other", "admin", "dos", "file", "recon", "user"), "action.category": ("other", "block_installed", "notification_sent", "taken_offline"), "confidence.rating": ("numeric", "low", "medium", "high"), "alert.type": ("default", "tool_alert", "correlation_alert", "overflow_alert") } for object in enum_types.keys(): if find(self.object, object) != -1: for item in enum_types[object]: self.valueWidget.insertItem(item) break else: self.valueWidget = QLineEdit(self.scrollview) self.valueWidget.setFixedWidth(width * 0.5) self.scrollview.addChild(self.valueWidget, width * 0.5, AdvancedCriterion.height) layout.addWidget(self.valueWidget) self.valueWidget.show() def getOperator(self): if self.operatorComboBox: return " %s " % self.operatorComboBox.currentText() return " " def getObject(self): return " %s " % self.object def getRelation(self): relation = self.relationComboBox.currentText() if relation == "=~": relation = "substr" return " %s " % relation def getValue(self): value = "" if self.type == "time": value = self.valueWidget.dateTime().toString("yyyy-MM-dd hh:mm:ss") elif self.type == "enum": value = self.valueWidget.currentText() else: value = self.valueWidget.text() return "'%s'" % str(value) def getCriterion(self): criterion = "" criterion += self.getOperator() criterion += self.getObject() criterion += self.getRelation() criterion += self.getValue() return criterion class Advanced(QWidget): additionalData = ("additional_data", "type", "meaning") classification = ("classification", "origin", "name", "url") userId = ("userid", "ident", "type", "name", "number") user = ("user", "ident", "category", userId) address = ("address", "ident", "category", "vlan_name", "vlan_num", "address", "netmask") process = ("process", "ident", "name", "pid", "path", "env", "arg") webservice = ("webservice", "url", "cgi", "http_method", "arg") snmpservice = ("snmpservice", "oid", "community", "command") service = ("service", "ident", "name", "port", "portlist", "protocol", webservice, snmpservice) node = ("node", "ident", "category", "location", "name", address) source = ("source", "ident", "spoofed", "interface", node, user, process, service) fileAccess = ("file_access", "ident", "permission") inode = ("inode", "change_time", "number", "major_device", "minor_device", "c_major_device", "c_minor_device") file = ("file", "ident", "category", "fstype", "name", "path", "create_time", "modify_time", "access_time", "data_size", "disk_size", fileAccess, inode) target = ("target", "ident", "decoy", "interface", node, user, process, service, file) analyzer = ("analyzer", "analyzerid", "manufacturer", "model", "version", "class", "ostype", "osversion", node, process) impact = ("impact", "severity", "completion", "type", "description") action = ("action", "category", "description") confidence = ("confidence", "rating") assessment = ("assessment", impact, action, confidence) alert = ("alert", "ident", assessment, analyzer, "create_time", "detect_time", "analyzer_time", source, target, classification, additionalData) def __init__(self, parent): QWidget.__init__(self, parent.tab) parent.tab.addTab(self, "Advanced") self.parent = parent self.criterionList = [ ] layout = QGridLayout(self, 2, 2) layout.setColStretch(0, 1) layout.setColStretch(1, 2) # build IDMEF Tree QListView self.IDMEFTreeListView = QListView(self) self.IDMEFTreeListView.setResizeMode(QListView.LastColumn) self.IDMEFTreeListView.setSorting(-1) self.IDMEFTreeListView.setRootIsDecorated(True) #self.IDMEFTreeListView.setHScrollBarMode(QScrollView.AlwaysOn) QObject.connect(self.IDMEFTreeListView, SIGNAL("selectionChanged(QListViewItem *)"), self.nodeSelected) layout.addWidget(self.IDMEFTreeListView, 0, 0) self.IDMEFTreeListView.addColumn("IDMEF Tree") self.buildElement(Advanced.alert, self.IDMEFTreeListView).setOpen(True) # build Add and remove buttons self.addButton = QPushButton("Add", self) self.addButton.setEnabled(False) QObject.connect(self.addButton, SIGNAL("clicked()"), self.addField) layout.addWidget(self.addButton, 1, 0) # build criterion list self.criterionView = QScrollView(self) self.criterionView.setVScrollBarMode(QScrollView.AlwaysOn) #self.criterionViewLayout = QVBoxLayout(self.criterionView, 0, -1) self.criterionViewLayout = self.criterionView.layout() layout.addMultiCellWidget(self.criterionView, 0, 1, 1, 1) def __del__(self): AdvancedCriterion.height = 0 def buildElement(self, element, parent, after=None): item = QListViewItem(parent, after) item.setText(0, element[0]) prev = None for field in element[1:]: if type(field) is tuple: prev = self.buildElement(field, item, prev) else: subItem = QListViewItem(item, prev) subItem.setText(0, field) prev = subItem return item def nodeSelected(self, item): self.addButton.setEnabled(item.childCount() == 0) def addCriterion(self, name, object): prev = None if len(self.criterionList) > 0: prev = self.criterionList[-1] criterion = AdvancedCriterion(self.criterionView, self.criterionViewLayout, name, object, prev) self.criterionList.append(criterion) self.parent.searchButton.setEnabled(True) def addField(self): item = self.IDMEFTreeListView.currentItem() name = str(item.text(0)) object = name while True: item = item.parent() if not item: break object = str(item.text(0)) + "." + object self.addCriterion(name, object) def reset(self): self.criterionList = [ ] AdvancedCriterion.height = 0 self.parent.searchButton.setEnabled(False) def isEmpty(self): return len(self.criterionList) == 0 def getCriteria(self): criteria = "" for criterion in self.criterionList: criteria += criterion.getCriterion() return IDMEFCriteria(criteria) class FindDialog(QDialog): def __init__(self, parent, interface): QDialog.__init__(self, parent) self.setCaption("Find - Pylude") self.setWFlags(Qt.WDestructiveClose) self.resize(700, 600) self.db = interface.db mainLayout = QVBoxLayout(self) mainLayout.setMargin(MARGIN) mainLayout.setSpacing(SPACING) self.tab = QTabWidget(self) mainLayout.addWidget(self.tab) self.connect(self.tab, SIGNAL("currentChanged(QWidget *)"), self.tabChanged) buttonLayout = QHBoxLayout(mainLayout) closeButton = QPushButton("&Close", self) self.connect(closeButton, SIGNAL("clicked()"), self.closeActivated) buttonLayout.addWidget(closeButton) resetButton = QPushButton("&Reset", self) buttonLayout.addWidget(resetButton) self.connect(resetButton, SIGNAL("clicked()"), self.resetActivated) self.searchButton = QPushButton("&Search", self) buttonLayout.addWidget(self.searchButton) self.searchButton.setEnabled(False) self.searchButton.setDefault(True) self.connect(self.searchButton, SIGNAL("clicked()"), self.searchActivated) buttonLayout.insertStretch(1) self.alertListView = AlertListView(self, interface) mainLayout.addWidget(self.alertListView) mainLayout.setStretchFactor(self.alertListView, 1) self.simple = Simple(self) self.advanced = Advanced(self) self.current = self.simple def tabChanged(self, tab): if tab == self.simple: self.current = self.simple else: self.current = self.advanced self.searchButton.setEnabled(not self.current.isEmpty()) def closeEvent(self, event): FindForm.closeEvent(self, event) AdvancedCriterion.height = 0 self.simple = None self.advanced = None self.current = None self.parent().removeChild(self) def closeActivated(self): self.close() def resetActivated(self): self.current.reset() def searchActivated(self): self.alertListView.deleteItems() criteria = self.current.getCriteria() identList = self.db.get_alert_ident_list(criteria) if not identList: return self.alertListView.updateAlerts(identList)