Example #1
0
    def get_rule_from_records(self, records):
        rule = ui_pb2.Rule(name=records.value(2))
        rule.enabled = self._bool(records.value(3))
        rule.precedence = self._bool(records.value(4))
        rule.action = records.value(5)
        rule.duration = records.value(6)
        rule.operator.type = records.value(7)
        rule.operator.sensitive = self._bool(records.value(8))
        rule.operator.operand = records.value(9)
        rule.operator.data = "" if records.value(10) == None else str(records.value(10))

        return rule
Example #2
0
    def delete_rule(self, rule_name, addr, callback):
        rule = ui_pb2.Rule(name=rule_name)
        rule.enabled = False
        rule.action = ""
        rule.duration = ""
        rule.operator.type = ""
        rule.operator.operand = ""
        rule.operator.data = ""

        noti = ui_pb2.Notification(type=ui_pb2.DELETE_RULE, rules=[rule])
        nid = self.send_notification(addr, noti, None)
        self._db.delete_rule(rule.name, addr)

        return nid, noti
Example #3
0
    def _save_rule(self):
        """
        Create a new rule based on the fields selected.

        Ensure that some constraints are met:
        - Determine if a field can be a regexp.
        - Validate regexp.
        - Fields cannot be empty.
        - If the user has not provided a rule name, auto assign one.
        """
        self.rule = ui_pb2.Rule()
        self.rule.name = self.ruleNameEdit.text()
        self.rule.description = self.ruleDescEdit.toPlainText()
        self.rule.enabled = self.enableCheck.isChecked()
        self.rule.precedence = self.precedenceCheck.isChecked()
        self.rule.operator.type = Config.RULE_TYPE_SIMPLE
        self.rule.action = Config.ACTION_DENY
        if self.actionAllowRadio.isChecked():
            self.rule.action = Config.ACTION_ALLOW
        elif self.actionRejectRadio.isChecked():
            self.rule.action = Config.ACTION_REJECT

        self.rule.duration = self._get_duration(
            self.durationCombo.currentIndex())

        # FIXME: there should be a sensitive checkbox per operand
        self.rule.operator.sensitive = self.sensitiveCheck.isChecked()
        rule_data = []
        if self.protoCheck.isChecked():
            if self.protoCombo.currentText() == "":
                return False, QC.translate(
                    "rules", "protocol can not be empty, or uncheck it")

            self.rule.operator.operand = "protocol"
            self.rule.operator.data = self.protoCombo.currentText()
            rule_data.append({
                "type": Config.RULE_TYPE_SIMPLE,
                "operand": "protocol",
                "data": self.protoCombo.currentText().lower(),
                "sensitive": self.sensitiveCheck.isChecked()
            })
            if self._is_regex(self.protoCombo.currentText()):
                rule_data[len(rule_data) - 1]['type'] = Config.RULE_TYPE_REGEXP
                if self._is_valid_regex(
                        self.protoCombo.currentText()) == False:
                    return False, QC.translate("rules",
                                               "Protocol regexp error")

        if self.procCheck.isChecked():
            if self.procLine.text() == "":
                return False, QC.translate("rules",
                                           "process path can not be empty")

            self.rule.operator.operand = "process.path"
            self.rule.operator.data = self.procLine.text()
            rule_data.append({
                "type": Config.RULE_TYPE_SIMPLE,
                "operand": "process.path",
                "data": self.procLine.text(),
                "sensitive": self.sensitiveCheck.isChecked()
            })
            if self._is_regex(self.procLine.text()):
                rule_data[len(rule_data) - 1]['type'] = Config.RULE_TYPE_REGEXP
                if self._is_valid_regex(self.procLine.text()) == False:
                    return False, QC.translate("rules",
                                               "Process path regexp error")

        if self.cmdlineCheck.isChecked():
            if self.cmdlineLine.text() == "":
                return False, QC.translate("rules",
                                           "command line can not be empty")

            self.rule.operator.operand = "process.command"
            self.rule.operator.data = self.cmdlineLine.text()
            rule_data.append({
                'type': Config.RULE_TYPE_SIMPLE,
                'operand': 'process.command',
                'data': self.cmdlineLine.text(),
                "sensitive": self.sensitiveCheck.isChecked()
            })
            if self._is_regex(self.cmdlineLine.text()):
                rule_data[len(rule_data) - 1]['type'] = Config.RULE_TYPE_REGEXP
                if self._is_valid_regex(self.cmdlineLine.text()) == False:
                    return False, QC.translate("rules",
                                               "Command line regexp error")

        if self.dstPortCheck.isChecked():
            if self.dstPortLine.text() == "":
                return False, QC.translate("rules",
                                           "Dest port can not be empty")

            self.rule.operator.operand = "dest.port"
            self.rule.operator.data = self.dstPortLine.text()
            rule_data.append({
                'type': Config.RULE_TYPE_SIMPLE,
                'operand': 'dest.port',
                'data': self.dstPortLine.text(),
                "sensitive": self.sensitiveCheck.isChecked()
            })
            if self._is_regex(self.dstPortLine.text()):
                rule_data[len(rule_data) - 1]['type'] = Config.RULE_TYPE_REGEXP
                if self._is_valid_regex(self.dstPortLine.text()) == False:
                    return False, QC.translate("rules",
                                               "Dst port regexp error")

        if self.dstHostCheck.isChecked():
            if self.dstHostLine.text() == "":
                return False, QC.translate("rules",
                                           "Dest host can not be empty")

            self.rule.operator.operand = "dest.host"
            self.rule.operator.data = self.dstHostLine.text()
            rule_data.append({
                'type': Config.RULE_TYPE_SIMPLE,
                'operand': 'dest.host',
                'data': self.dstHostLine.text(),
                "sensitive": self.sensitiveCheck.isChecked()
            })
            if self._is_regex(self.dstHostLine.text()):
                rule_data[len(rule_data) - 1]['type'] = Config.RULE_TYPE_REGEXP
                if self._is_valid_regex(self.dstHostLine.text()) == False:
                    return False, QC.translate("rules",
                                               "Dst host regexp error")

        if self.dstIPCheck.isChecked():
            if self.dstIPCombo.currentText() == "":
                return False, QC.translate("rules",
                                           "Dest IP/Network can not be empty")

            dstIPtext = self.dstIPCombo.currentText()

            if dstIPtext == self.LAN_LABEL:
                self.rule.operator.operand = "dest.ip"
                self.rule.operator.type = Config.RULE_TYPE_REGEXP
                dstIPtext = self.LAN_RANGES
            else:
                try:
                    if type(ipaddress.ip_address(self.dstIPCombo.currentText())) == ipaddress.IPv4Address \
                    or type(ipaddress.ip_address(self.dstIPCombo.currentText())) == ipaddress.IPv6Address:
                        self.rule.operator.operand = "dest.ip"
                        self.rule.operator.type = Config.RULE_TYPE_SIMPLE
                except Exception:
                    self.rule.operator.operand = "dest.network"
                    self.rule.operator.type = Config.RULE_TYPE_NETWORK

                if self._is_regex(dstIPtext):
                    self.rule.operator.operand = "dest.ip"
                    self.rule.operator.type = Config.RULE_TYPE_REGEXP
                    if self._is_valid_regex(
                            self.dstIPCombo.currentText()) == False:
                        return False, QC.translate("rules",
                                                   "Dst IP regexp error")

            rule_data.append({
                'type': self.rule.operator.type,
                'operand': self.rule.operator.operand,
                'data': dstIPtext,
                "sensitive": self.sensitiveCheck.isChecked()
            })

        if self.uidCheck.isChecked():
            if self.uidLine.text() == "":
                return False, QC.translate("rules", "User ID can not be empty")

            self.rule.operator.operand = "user.id"
            self.rule.operator.data = self.uidLine.text()
            rule_data.append({
                'type': Config.RULE_TYPE_SIMPLE,
                'operand': 'user.id',
                'data': self.uidLine.text(),
                "sensitive": self.sensitiveCheck.isChecked()
            })
            if self._is_regex(self.uidLine.text()):
                rule_data[len(rule_data) - 1]['type'] = Config.RULE_TYPE_REGEXP
                if self._is_valid_regex(self.uidLine.text()) == False:
                    return False, QC.translate("rules", "User ID regexp error")

        if self.pidCheck.isChecked():
            if self.pidLine.text() == "":
                return False, QC.translate("rules",
                                           "PID field can not be empty")

            self.rule.operator.operand = "process.id"
            self.rule.operator.data = self.pidLine.text()
            rule_data.append({
                'type': Config.RULE_TYPE_SIMPLE,
                'operand': 'process.id',
                'data': self.pidLine.text(),
                "sensitive": self.sensitiveCheck.isChecked()
            })
            if self._is_regex(self.pidLine.text()):
                rule_data[len(rule_data) - 1]['type'] = Config.RULE_TYPE_REGEXP
                if self._is_valid_regex(self.pidLine.text()) == False:
                    return False, QC.translate("rules",
                                               "PID field regexp error")

        if self.dstListsCheck.isChecked():
            if self.dstListsLine.text() == "":
                return False, QC.translate("rules",
                                           "Lists field cannot be empty")
            if os.path.isdir(self.dstListsLine.text()) == False:
                return False, QC.translate("rules",
                                           "Lists field must be a directory")

            self.rule.operator.type = Config.RULE_TYPE_LISTS
            self.rule.operator.operand = "lists.domains"
            rule_data.append({
                'type': Config.RULE_TYPE_LISTS,
                'operand': 'lists.domains',
                'data': self.dstListsLine.text(),
                'sensitive': self.sensitiveCheck.isChecked()
            })
            self.rule.operator.data = json.dumps(rule_data)

        if self.dstListRegexpCheck.isChecked():
            if self.dstRegexpListsLine.text() == "":
                return False, QC.translate("rules",
                                           "Lists field cannot be empty")
            if os.path.isdir(self.dstRegexpListsLine.text()) == False:
                return False, QC.translate("rules",
                                           "Lists field must be a directory")

            self.rule.operator.type = Config.RULE_TYPE_LISTS
            self.rule.operator.operand = "lists.domains_regexp"
            rule_data.append({
                'type': Config.RULE_TYPE_LISTS,
                'operand': 'lists.domains_regexp',
                'data': self.dstRegexpListsLine.text(),
                'sensitive': self.sensitiveCheck.isChecked()
            })
            self.rule.operator.data = json.dumps(rule_data)

        if self.dstListNetsCheck.isChecked():
            if self.dstListNetsLine.text() == "":
                return False, QC.translate("rules",
                                           "Lists field cannot be empty")
            if os.path.isdir(self.dstListNetsLine.text()) == False:
                return False, QC.translate("rules",
                                           "Lists field must be a directory")

            self.rule.operator.type = Config.RULE_TYPE_LISTS
            self.rule.operator.operand = "lists.nets"
            rule_data.append({
                'type': Config.RULE_TYPE_LISTS,
                'operand': 'lists.nets',
                'data': self.dstListNetsLine.text(),
                'sensitive': self.sensitiveCheck.isChecked()
            })
            self.rule.operator.data = json.dumps(rule_data)

        if self.dstListIPsCheck.isChecked():
            if self.dstListIPsLine.text() == "":
                return False, QC.translate("rules",
                                           "Lists field cannot be empty")
            if os.path.isdir(self.dstListIPsLine.text()) == False:
                return False, QC.translate("rules",
                                           "Lists field must be a directory")

            self.rule.operator.type = Config.RULE_TYPE_LISTS
            self.rule.operator.operand = "lists.ips"
            rule_data.append({
                'type': Config.RULE_TYPE_LISTS,
                'operand': 'lists.ips',
                'data': self.dstListIPsLine.text(),
                'sensitive': self.sensitiveCheck.isChecked()
            })
            self.rule.operator.data = json.dumps(rule_data)

        if len(rule_data) >= 2:
            self.rule.operator.type = Config.RULE_TYPE_LIST
            self.rule.operator.operand = Config.RULE_TYPE_LIST
            self.rule.operator.data = json.dumps(rule_data)
        elif len(rule_data) == 1:
            self.rule.operator.operand = rule_data[0]['operand']
            self.rule.operator.data = rule_data[0]['data']
            if self._is_regex(self.rule.operator.data):
                self.rule.operator.type = Config.RULE_TYPE_REGEXP
        else:
            return False, QC.translate("rules", "Select at least one field.")

        if self.ruleNameEdit.text() == "":
            self.rule.name = slugify(
                "%s %s %s" % (self.rule.action, self.rule.operator.type,
                              self.rule.operator.data))

        return True, ""
Example #4
0
    def _send_rule(self):
        try:
            self._cfg.setSettings("promptDialog/geometry", self.saveGeometry())
            self._rule = ui_pb2.Rule(name="user.choice")
            self._rule.enabled = True
            self._rule.action = Config.ACTION_DENY if self._default_action == self.ACTION_IDX_DENY else Config.ACTION_ALLOW
            self._rule.duration = self._get_duration(
                self.durationCombo.currentIndex())

            what_idx = self.whatCombo.currentIndex()
            self._rule.operator.type, self._rule.operator.operand, self._rule.operator.data = self._get_combo_operator(
                self.whatCombo, what_idx)
            if self._rule.operator.data == "":
                print("Invalid rule, discarding: ", self._rule)
                self._rule = None
                return

            rule_temp_name = self._get_rule_name(self._rule)
            self._rule.name = rule_temp_name

            # TODO: move to a method
            data = []
            if self.checkDstIP.isChecked(
            ) and self.whatCombo.itemData(what_idx) != self.FIELD_DST_IP:
                _type, _operand, _data = self._get_combo_operator(
                    self.whatIPCombo, self.whatIPCombo.currentIndex())
                data.append({
                    "type": _type,
                    "operand": _operand,
                    "data": _data
                })
                rule_temp_name = slugify("%s %s" % (rule_temp_name, _data))

            if self.checkDstPort.isChecked(
            ) and self.whatCombo.itemData(what_idx) != self.FIELD_DST_PORT:
                data.append({
                    "type": Config.RULE_TYPE_SIMPLE,
                    "operand": "dest.port",
                    "data": str(self._con.dst_port)
                })
                rule_temp_name = slugify(
                    "%s %s" % (rule_temp_name, str(self._con.dst_port)))

            if self.checkUserID.isChecked(
            ) and self.whatCombo.itemData(what_idx) != self.FIELD_USER_ID:
                data.append({
                    "type": Config.RULE_TYPE_SIMPLE,
                    "operand": "user.id",
                    "data": str(self._con.user_id)
                })
                rule_temp_name = slugify(
                    "%s %s" % (rule_temp_name, str(self._con.user_id)))

            if self._is_list_rule():
                data.append({
                    "type": self._rule.operator.type,
                    "operand": self._rule.operator.operand,
                    "data": self._rule.operator.data
                })
                self._rule.operator.data = json.dumps(data)
                self._rule.operator.type = Config.RULE_TYPE_LIST
                self._rule.operator.operand = Config.RULE_TYPE_LIST

            self._rule.name = rule_temp_name

            self.hide()
            if self._ischeckAdvanceded:
                self.checkAdvanced.toggle()
            self._ischeckAdvanceded = False

        except Exception as e:
            print("[pop-up] exception creating a rule:", e)
        finally:
            # signal that the user took a decision and
            # a new rule is available
            self._done.set()
            self.hide()
Example #5
0
    def _save_rule(self):
        """
        Create a new rule based on the fields selected.

        Ensure that some constraints are met:
        - Determine if a field can be a regexp.
        - Validate regexp.
        - Fields cannot be empty.
        - If the user has not provided a rule name, auto assign one.
        """
        self.rule = ui_pb2.Rule()
        self.rule.name = self.ruleNameEdit.text()
        self.rule.enabled = self.enableCheck.isChecked()
        self.rule.precedence = self.precedenceCheck.isChecked()
        self.rule.action = Config.ACTION_DENY if self.actionDenyRadio.isChecked(
        ) else Config.ACTION_ALLOW
        self.rule.operator.type = "simple"

        # TODO: move to config.get_duration()
        if self.durationCombo.currentIndex() == 0:
            self.rule.duration = Config.DURATION_ONCE
        elif self.durationCombo.currentIndex() == 6:
            self.rule.duration = Config.DURATION_UNTIL_RESTART
        elif self.durationCombo.currentIndex() == 7:
            self.rule.duration = Config.DURATION_ALWAYS
        else:
            self.rule.duration = self.durationCombo.currentText()

        # FIXME: there should be a sensitive checkbox per operand
        self.rule.operator.sensitive = self.sensitiveCheck.isChecked()
        rule_data = []
        if self.protoCheck.isChecked():
            if self.protoCombo.currentText() == "":
                return False, QC.translate(
                    "rules", "protocol can not be empty, or uncheck it")

            self.rule.operator.operand = "protocol"
            self.rule.operator.data = self.protoCombo.currentText()
            rule_data.append({
                "type": "simple",
                "operand": "protocol",
                "data": self.protoCombo.currentText().lower(),
                "sensitive": self.sensitiveCheck.isChecked()
            })
            if self._is_regex(self.protoCombo.currentText()):
                rule_data[len(rule_data) - 1]['type'] = "regexp"
                if self._is_valid_regex(
                        self.protoCombo.currentText()) == False:
                    return False, QC.translate("rules",
                                               "Protocol regexp error")

        if self.procCheck.isChecked():
            if self.procLine.text() == "":
                return False, QC.translate("rules",
                                           "process path can not be empty")

            self.rule.operator.operand = "process.path"
            self.rule.operator.data = self.procLine.text()
            rule_data.append({
                "type": "simple",
                "operand": "process.path",
                "data": self.procLine.text(),
                "sensitive": self.sensitiveCheck.isChecked()
            })
            if self._is_regex(self.procLine.text()):
                rule_data[len(rule_data) - 1]['type'] = "regexp"
                if self._is_valid_regex(self.procLine.text()) == False:
                    return False, QC.translate("rules",
                                               "Process path regexp error")

        if self.cmdlineCheck.isChecked():
            if self.cmdlineLine.text() == "":
                return False, QC.translate("rules",
                                           "command line can not be empty")

            self.rule.operator.operand = "process.command"
            self.rule.operator.data = self.cmdlineLine.text()
            rule_data.append({
                'type': 'simple',
                'operand': 'process.command',
                'data': self.cmdlineLine.text(),
                "sensitive": self.sensitiveCheck.isChecked()
            })
            if self._is_regex(self.cmdlineLine.text()):
                rule_data[len(rule_data) - 1]['type'] = "regexp"
                if self._is_valid_regex(self.cmdlineLine.text()) == False:
                    return False, QC.translate("rules",
                                               "Command line regexp error")

        if self.dstPortCheck.isChecked():
            if self.dstPortLine.text() == "":
                return False, QC.translate("rules",
                                           "Dest port can not be empty")

            self.rule.operator.operand = "dest.port"
            self.rule.operator.data = self.dstPortLine.text()
            rule_data.append({
                'type': 'simple',
                'operand': 'dest.port',
                'data': self.dstPortLine.text(),
                "sensitive": self.sensitiveCheck.isChecked()
            })
            if self._is_regex(self.dstPortLine.text()):
                rule_data[len(rule_data) - 1]['type'] = "regexp"
                if self._is_valid_regex(self.dstPortLine.text()) == False:
                    return False, QC.translate("rules",
                                               "Dst port regexp error")

        if self.dstHostCheck.isChecked():
            if self.dstHostLine.text() == "":
                return False, QC.translate("rules",
                                           "Dest host can not be empty")

            self.rule.operator.operand = "dest.host"
            self.rule.operator.data = self.dstHostLine.text()
            rule_data.append({
                'type': 'simple',
                'operand': 'dest.host',
                'data': self.dstHostLine.text(),
                "sensitive": self.sensitiveCheck.isChecked()
            })
            if self._is_regex(self.dstHostLine.text()):
                rule_data[len(rule_data) - 1]['type'] = "regexp"
                if self._is_valid_regex(self.dstHostLine.text()) == False:
                    return False, QC.translate("rules",
                                               "Dst host regexp error")

        if self.dstIPCheck.isChecked():
            if self.dstIPCombo.currentText() == "":
                return False, QC.translate("rules",
                                           "Dest IP/Network can not be empty")

            dstIPtext = self.dstIPCombo.currentText()

            if dstIPtext == self.LAN_LABEL:
                self.rule.operator.operand = "dest.ip"
                self.rule.operator.type = "regexp"
                dstIPtext = self.LAN_RANGES
            else:
                try:
                    if type(ipaddress.ip_address(self.dstIPCombo.currentText())) == ipaddress.IPv4Address \
                    or type(ipaddress.ip_address(self.dstIPCombo.currentText())) == ipaddress.IPv6Address:
                        self.rule.operator.operand = "dest.ip"
                        self.rule.operator.type = "simple"
                except Exception:
                    self.rule.operator.operand = "dest.network"
                    self.rule.operator.type = "network"

                if self._is_regex(dstIPtext):
                    self.rule.operator.operand = "dest.ip"
                    self.rule.operator.type = "regexp"
                    if self._is_valid_regex(
                            self.dstIPCombo.currentText()) == False:
                        return False, QC.translate("rules",
                                                   "Dst IP regexp error")

            rule_data.append({
                'type': self.rule.operator.type,
                'operand': self.rule.operator.operand,
                'data': dstIPtext,
                "sensitive": self.sensitiveCheck.isChecked()
            })

        if self.uidCheck.isChecked():
            if self.uidLine.text() == "":
                return False, QC.translate("rules", "User ID can not be empty")

            self.rule.operator.operand = "user.id"
            self.rule.operator.data = self.uidLine.text()
            rule_data.append({
                'type': 'simple',
                'operand': 'user.id',
                'data': self.uidLine.text(),
                "sensitive": self.sensitiveCheck.isChecked()
            })
            if self._is_regex(self.uidLine.text()):
                rule_data[len(rule_data) - 1]['type'] = "regexp"
                if self._is_valid_regex(self.uidLine.text()) == False:
                    return False, QC.translate("rules", "User ID regexp error")

        if self.dstListsCheck.isChecked():
            if self.dstListsLine.text() == "":
                return False, QC.translate("rules",
                                           "Lists field cannot be empty")
            if os.path.isdir(self.dstListsLine.text()) == False:
                return False, QC.translate("rules",
                                           "Lists field must be a directory")

            self.rule.operator.type = "lists"
            self.rule.operator.operand = "lists.domains"
            rule_data.append({
                'type': 'lists',
                'operand': 'lists.domains',
                'data': self.dstListsLine.text(),
                'sensitive': self.sensitiveCheck.isChecked()
            })
            self.rule.operator.data = json.dumps(rule_data)

        if len(rule_data) > 1:
            self.rule.operator.type = "list"
            self.rule.operator.operand = "list"
            self.rule.operator.data = json.dumps(rule_data)
        else:
            self.rule.operator.operand = rule_data[0]['operand']
            self.rule.operator.data = rule_data[0]['data']
            if self._is_regex(self.rule.operator.data):
                self.rule.operator.type = "regexp"

        if self.ruleNameEdit.text() == "":
            self.rule.name = slugify(
                "%s %s %s" % (self.rule.action, self.rule.operator.type,
                              self.rule.operator.data))

        return True, ""