ui,popups: allow to update checksums

When the checksum of a binary changes, due to an update or something
else, you'll be prompted to allow the outbound connection if the
previous checksum of the rule doesn't match the new one.

Without a visual warning was almost impossible to know what was going
on. Besides, you had to dismiss that pop-up, find the rule, and update
the checksum.

Now there's a warning message, and you can update the rule from
the pop-up.

Related: #413
This commit is contained in:
Gustavo Iñiguez Goia 2023-11-24 00:57:13 +01:00
parent ffd70836f6
commit 02cf65ac33
Failed to generate hash of commit
4 changed files with 380 additions and 137 deletions

View file

@ -584,6 +584,25 @@ class Database:
return q return q
def get_rule_by_field(self, node_addr=None, field=None, value=None):
"""
get rule records by field (process.path, etc)
"""
qstr = "SELECT * FROM rules WHERE {0} LIKE ?".format(field)
q = QSqlQuery(qstr, self.db)
if node_addr != None:
qstr = qstr + " AND node=?".format(node_addr)
q.prepare(qstr)
q.addBindValue("%" + value + "%")
if node_addr != None:
q.addBindValue(node_addr)
if not q.exec_():
print("get_rule_by_field() error:", q.lastError().driverText())
return None
return q
def get_rules(self, node_addr): def get_rules(self, node_addr):
""" """
get rule records, given the name of the rule and the node get rule records, given the name of the rule and the node

View file

@ -19,6 +19,7 @@ from opensnitch.config import Config
from opensnitch.version import version from opensnitch.version import version
from opensnitch.actions import Actions from opensnitch.actions import Actions
from opensnitch.rules import Rules, Rule from opensnitch.rules import Rules, Rule
from opensnitch.nodes import Nodes
from opensnitch import ui_pb2 from opensnitch import ui_pb2
@ -28,6 +29,10 @@ class PromptDialog(QtWidgets.QDialog, uic.loadUiType(DIALOG_UI_PATH)[0]):
_tick_trigger = QtCore.pyqtSignal() _tick_trigger = QtCore.pyqtSignal()
_timeout_trigger = QtCore.pyqtSignal() _timeout_trigger = QtCore.pyqtSignal()
PAGE_MAIN = 2
PAGE_DETAILS = 0
PAGE_CHECKSUMS = 1
DEFAULT_TIMEOUT = 15 DEFAULT_TIMEOUT = 15
# don't translate # don't translate
@ -59,6 +64,7 @@ class PromptDialog(QtWidgets.QDialog, uic.loadUiType(DIALOG_UI_PATH)[0]):
# Other interesting flags: QtCore.Qt.Tool | QtCore.Qt.BypassWindowManagerHint # Other interesting flags: QtCore.Qt.Tool | QtCore.Qt.BypassWindowManagerHint
self._cfg = Config.get() self._cfg = Config.get()
self._rules = Rules.instance() self._rules = Rules.instance()
self._nodes = Nodes.instance()
self.setupUi(self) self.setupUi(self)
self.setWindowIcon(appicon) self.setWindowIcon(appicon)
@ -108,6 +114,10 @@ class PromptDialog(QtWidgets.QDialog, uic.loadUiType(DIALOG_UI_PATH)[0]):
self.cmdInfo.clicked.connect(self._cb_cmdinfo_clicked) self.cmdInfo.clicked.connect(self._cb_cmdinfo_clicked)
self.cmdBack.clicked.connect(self._cb_cmdback_clicked) self.cmdBack.clicked.connect(self._cb_cmdback_clicked)
self.cmdUpdateRule.clicked.connect(self._cb_update_rule_clicked)
self.cmdBackChecksums.clicked.connect(self._cb_cmdback_clicked)
self.messageLabel.linkActivated.connect(self._cb_warninglbl_clicked)
self.allowIcon = Icons.new(self, "emblem-default") self.allowIcon = Icons.new(self, "emblem-default")
denyIcon = Icons.new(self, "emblem-important") denyIcon = Icons.new(self, "emblem-important")
rejectIcon = Icons.new(self, "window-close") rejectIcon = Icons.new(self, "window-close")
@ -116,6 +126,7 @@ class PromptDialog(QtWidgets.QDialog, uic.loadUiType(DIALOG_UI_PATH)[0]):
self.cmdInfo.setIcon(infoIcon) self.cmdInfo.setIcon(infoIcon)
self.cmdBack.setIcon(backIcon) self.cmdBack.setIcon(backIcon)
self.cmdBackChecksums.setIcon(backIcon)
self._default_action = self._cfg.getInt(self._cfg.DEFAULT_ACTION_KEY) self._default_action = self._cfg.getInt(self._cfg.DEFAULT_ACTION_KEY)
@ -197,7 +208,7 @@ class PromptDialog(QtWidgets.QDialog, uic.loadUiType(DIALOG_UI_PATH)[0]):
self.checkSum.setVisible(self._con.process_checksums[Config.OPERAND_PROCESS_HASH_MD5] != "" and state) self.checkSum.setVisible(self._con.process_checksums[Config.OPERAND_PROCESS_HASH_MD5] != "" and state)
self.checksumLabel_2.setVisible(self._con.process_checksums[Config.OPERAND_PROCESS_HASH_MD5] != "" and state) self.checksumLabel_2.setVisible(self._con.process_checksums[Config.OPERAND_PROCESS_HASH_MD5] != "" and state)
self.checksumLabel.setVisible(self._con.process_checksums[Config.OPERAND_PROCESS_HASH_MD5] != "" and state) self.checksumLabel.setVisible(self._con.process_checksums[Config.OPERAND_PROCESS_HASH_MD5] != "" and state)
self.stackedWidget.setCurrentIndex(1) self.stackedWidget.setCurrentIndex(self.PAGE_MAIN)
self._ischeckAdvanceded = state self._ischeckAdvanceded = state
self.adjust_size() self.adjust_size()
@ -206,12 +217,57 @@ class PromptDialog(QtWidgets.QDialog, uic.loadUiType(DIALOG_UI_PATH)[0]):
def _button_clicked(self): def _button_clicked(self):
self._stop_countdown() self._stop_countdown()
def _cb_warninglbl_clicked(self):
self._stop_countdown()
self.stackedWidget.setCurrentIndex(self.PAGE_CHECKSUMS)
def _cb_cmdinfo_clicked(self): def _cb_cmdinfo_clicked(self):
self.stackedWidget.setCurrentIndex(0) self.stackedWidget.setCurrentIndex(self.PAGE_DETAILS)
self._stop_countdown() self._stop_countdown()
def _cb_update_rule_clicked(self):
self.labelChecksumStatus.setStyleSheet('')
curRule = self.comboChecksumRule.currentText()
if curRule == "":
return
# get rule from the db
records = self._rules.get_by_name(self._peer, curRule)
if records == None or records.first() == False:
self.labelChecksumStatus.setStyleSheet('color: red')
self.labelChecksumStatus.setText("" + QC.translate("popups", "Rule not updated, not found by name"))
return
# transform it to proto rule
rule_obj = Rule.new_from_records(records)
if rule_obj.operator.type != Config.RULE_TYPE_LIST:
if rule_obj.operator.operand == Config.OPERAND_PROCESS_HASH_MD5:
rule_obj.operator.data = self._con.process_checksums[Config.OPERAND_PROCESS_HASH_MD5]
else:
for op in rule_obj.operator.list:
if op.operand == Config.OPERAND_PROCESS_HASH_MD5:
op.data = self._con.process_checksums[Config.OPERAND_PROCESS_HASH_MD5]
break
# add it back again to the db
added = self._rules.add_rules(self._peer, [rule_obj])
if not added:
self.labelChecksumStatus.setStyleSheet('color: red')
self.labelChecksumStatus.setText("" + QC.translate("popups", "Rule not updated."))
return
self._nodes.send_notification(
self._peer,
ui_pb2.Notification(
id=int(str(time.time()).replace(".", "")),
type=ui_pb2.CHANGE_RULE,
data="",
rules=[rule_obj]
)
)
self.labelChecksumStatus.setStyleSheet('color: green')
self.labelChecksumStatus.setText("" + QC.translate("popups", "Rule updated."))
def _cb_cmdback_clicked(self): def _cb_cmdback_clicked(self):
self.stackedWidget.setCurrentIndex(1) self.stackedWidget.setCurrentIndex(self.PAGE_MAIN)
self._stop_countdown() self._stop_countdown()
def _set_elide_text(self, widget, text, max_size=132): def _set_elide_text(self, widget, text, max_size=132):
@ -235,6 +291,14 @@ class PromptDialog(QtWidgets.QDialog, uic.loadUiType(DIALOG_UI_PATH)[0]):
self._local = is_local self._local = is_local
self._peer = peer self._peer = peer
self._con = connection self._con = connection
# XXX: workaround for protobufs that don't report the address of
# the node. In this case the addr is "unix:/local"
proto, addr = self._nodes.get_addr(peer)
self._peer = proto
if addr != None:
self._peer = proto+":"+addr
self._done.clear() self._done.clear()
# trigger and show dialog # trigger and show dialog
self._prompt_trigger.emit() self._prompt_trigger.emit()
@ -267,12 +331,12 @@ class PromptDialog(QtWidgets.QDialog, uic.loadUiType(DIALOG_UI_PATH)[0]):
@QtCore.pyqtSlot() @QtCore.pyqtSlot()
def on_connection_prompt_triggered(self): def on_connection_prompt_triggered(self):
self.stackedWidget.setCurrentIndex(1) self.stackedWidget.setCurrentIndex(self.PAGE_MAIN)
self._render_connection(self._con) self._render_connection(self._con)
if self._tick > 0: if self._tick > 0:
self.show() self.show()
# render details after displaying the pop-up. # render details after displaying the pop-up.
self._render_details(self._con) self._render_details(self._peer, self.connDetails, self._con)
@QtCore.pyqtSlot() @QtCore.pyqtSlot()
def on_tick_triggered(self): def on_tick_triggered(self):
@ -344,6 +408,109 @@ class PromptDialog(QtWidgets.QDialog, uic.loadUiType(DIALOG_UI_PATH)[0]):
self.argsLabel.setVisible(False) self.argsLabel.setVisible(False)
self.argsLabel.setText("") self.argsLabel.setText("")
def _verify_checksums(self, con, rule):
"""return true if the checksum of a rule matches the one of the process
opening a connection.
"""
if rule.operator.type != Config.RULE_TYPE_LIST:
return True, ""
if con.process_checksums[Config.OPERAND_PROCESS_HASH_MD5] == "":
return True, ""
for ro in rule.operator.list:
if ro.type == Config.RULE_TYPE_SIMPLE and ro.operand == Config.OPERAND_PROCESS_HASH_MD5:
if ro.data != con.process_checksums[Config.OPERAND_PROCESS_HASH_MD5]:
return False, ro.data
return True, ""
def _display_checksums_warning(self, peer, con):
self.messageLabel.setStyleSheet('')
self.labelChecksumStatus.setText('')
records = self._rules.get_by_field(peer, "operator_data", con.process_path)
if records != None and records.first():
rule = Rule.new_from_records(records)
validates, expected = self._verify_checksums(con, rule)
if not validates:
self.messageLabel.setStyleSheet('color: red')
self.messageLabel.setText(
QC.translate("popups", "WARNING, bad checksum (<a href='#'>More info</a>)"
)
)
self.labelChecksumNote.setText(
QC.translate("popups", "<font color=\"red\">WARNING, checksums differ.</font><br><br>Current process ({0}):<br>{1}<br><br>Expected from the rule:<br>{2}"
.format(
con.process_id,
con.process_checksums[Config.OPERAND_PROCESS_HASH_MD5],
expected
)))
self.comboChecksumRule.clear()
self.comboChecksumRule.addItem(rule.name)
while records.next():
rule = Rule.new_from_records(records)
self.comboChecksumRule.addItem(rule.name)
return "<b>WARNING</b><br>bad md5<br>This process:{0}<br>Expected from rule: {1}<br><br>".format(
con.process_checksums[Config.OPERAND_PROCESS_HASH_MD5],
expected
)
return ""
def _render_details(self, peer, detailsWidget, con):
tree = ""
space = "&nbsp;"
spaces = "&nbsp;"
indicator = ""
self._display_checksums_warning(peer, con)
try:
# reverse() doesn't exist on old protobuf libs.
con.process_tree.reverse()
except:
pass
for path in con.process_tree:
tree = "{0}<p>│{1}\t{2}{3}{4}</p>".format(tree, path.value, spaces, indicator, path.key)
spaces += "&nbsp;" * 4
indicator = "\\_ "
# XXX: table element doesn't work?
details = """<b>{0}</b> {1}:{2} -> {3}:{4}
<br><br>
<b>Path:</b>{5}{6}<br>
<b>Cmdline:</b>&nbsp;{7}<br>
<b>CWD:</b>{8}{9}<br>
<b>MD5:</b>{10}{11}<br>
<b>UID:</b>{12}{13}<br>
<b>PID:</b>{14}{15}<br>
<br>
<b>Process tree:</b><br>
{16}
<br>
<p><b>Environment variables:<b></p>
{17}
""".format(
con.protocol.upper(),
con.src_port, con.src_ip, con.dst_ip, con.dst_port,
space * 6, con.process_path,
" ".join(con.process_args),
space * 6, con.process_cwd,
space * 7, con.process_checksums[Config.OPERAND_PROCESS_HASH_MD5],
space * 9, con.user_id,
space * 9, con.process_id,
tree,
"".join('<p>{}={}</p>'.format(key, value) for key, value in con.process_env.items())
)
detailsWidget.document().clear()
detailsWidget.document().setHtml(details)
detailsWidget.moveCursor(QtGui.QTextCursor.Start)
def _render_connection(self, con): def _render_connection(self, con):
app_name, app_icon, description, _ = self._apps_parser.get_info_by_path(con.process_path, "terminal") app_name, app_icon, description, _ = self._apps_parser.get_info_by_path(con.process_path, "terminal")
app_args = " ".join(con.process_args) app_args = " ".join(con.process_args)
@ -357,6 +524,7 @@ class PromptDialog(QtWidgets.QDialog, uic.loadUiType(DIALOG_UI_PATH)[0]):
if app_name == "": if app_name == "":
self.appPathLabel.setVisible(False) self.appPathLabel.setVisible(False)
self.argsLabel.setVisible(False) self.argsLabel.setVisible(False)
self.argsLabel.setText("")
app_name = QC.translate("popups", "Unknown process %s" % con.process_path) app_name = QC.translate("popups", "Unknown process %s" % con.process_path)
self.appNameLabel.setText(QC.translate("popups", "Outgoing connection")) self.appNameLabel.setText(QC.translate("popups", "Outgoing connection"))
else: else:
@ -454,53 +622,6 @@ class PromptDialog(QtWidgets.QDialog, uic.loadUiType(DIALOG_UI_PATH)[0]):
self.setFixedSize(self.size()) self.setFixedSize(self.size())
def _render_details(self, con):
tree = ""
space = "&nbsp;"
spaces = "&nbsp;"
indicator = ""
try:
# reverse() doesn't exist on old protobuf libs.
con.process_tree.reverse()
except:
pass
for path in con.process_tree:
tree = "{0}<p>│{1}\t{2}{3}{4}</p>".format(tree, path.value, spaces, indicator, path.key)
spaces += "&nbsp;" * 4
indicator = "\_ "
# XXX: table element doesn't work?
details = """<b>{0}</b> {1}:{2} -> {3}:{4}
<br><br>
<b>Path:</b>{5}{6}<br>
<b>Cmdline:</b>&nbsp;{7}<br>
<b>CWD:</b>{8}{9}<br>
<b>MD5:</b>{10}{11}<br>
<b>UID:</b>{12}{13}<br>
<b>PID:</b>{14}{15}<br>
<br>
<b>Process tree:</b><br>
{16}
<br>
<p><b>Environment variables:<b></p>
{17}
""".format(
con.protocol.upper(),
con.src_port, con.src_ip, con.dst_ip, con.dst_port,
space * 6, con.process_path,
" ".join(con.process_args),
space * 6, con.process_cwd,
space * 7, con.process_checksums[Config.OPERAND_PROCESS_HASH_MD5],
space * 9, con.user_id,
space * 9, con.process_id,
tree,
"".join('<p>{}={}</p>'.format(key, value) for key, value in con.process_env.items())
)
self.connDetails.document().clear()
self.connDetails.document().setHtml(details)
self.connDetails.moveCursor(QtGui.QTextCursor.Start)
# https://gis.stackexchange.com/questions/86398/how-to-disable-the-escape-key-for-a-dialog # https://gis.stackexchange.com/questions/86398/how-to-disable-the-escape-key-for-a-dialog
def keyPressEvent(self, event): def keyPressEvent(self, event):

View file

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>563</width> <width>563</width>
<height>323</height> <height>339</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@ -188,7 +188,7 @@
</property> </property>
<property name="icon"> <property name="icon">
<iconset theme="emblem-important"> <iconset theme="emblem-important">
<normaloff>../../../../../../../../../../.designer/backup</normaloff>../../../../../../../../../../.designer/backup</iconset> <normaloff>../../../../../../../../../../../../../../../../../../.designer/backup</normaloff>../../../../../../../../../../../../../../../../../../.designer/backup</iconset>
</property> </property>
<property name="popupMode"> <property name="popupMode">
<enum>QToolButton::MenuButtonPopup</enum> <enum>QToolButton::MenuButtonPopup</enum>
@ -223,7 +223,7 @@
</property> </property>
<property name="icon"> <property name="icon">
<iconset theme="emblem-default"> <iconset theme="emblem-default">
<normaloff>../../../../../../../../../../.designer/backup</normaloff>../../../../../../../../../../.designer/backup</iconset> <normaloff>../../../../../../../../../../../../../../../../../../.designer/backup</normaloff>../../../../../../../../../../../../../../../../../../.designer/backup</iconset>
</property> </property>
</widget> </widget>
</item> </item>
@ -263,7 +263,7 @@
<item row="0" column="0"> <item row="0" column="0">
<widget class="QStackedWidget" name="stackedWidget"> <widget class="QStackedWidget" name="stackedWidget">
<property name="currentIndex"> <property name="currentIndex">
<number>1</number> <number>2</number>
</property> </property>
<widget class="QWidget" name="page"> <widget class="QWidget" name="page">
<layout class="QGridLayout" name="gridLayout_5"> <layout class="QGridLayout" name="gridLayout_5">
@ -297,7 +297,7 @@
</property> </property>
<property name="icon"> <property name="icon">
<iconset theme="go-previous"> <iconset theme="go-previous">
<normaloff>.</normaloff>.</iconset> <normaloff>../../../../../../../../../../.designer/backup</normaloff>../../../../../../../../../../.designer/backup</iconset>
</property> </property>
<property name="flat"> <property name="flat">
<bool>true</bool> <bool>true</bool>
@ -328,8 +328,105 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="page_3">
<layout class="QGridLayout" name="gridLayout_6">
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QPushButton" name="cmdBackChecksums">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset theme="go-previous">
<normaloff>../../../../../../.designer/backup</normaloff>../../../../../../.designer/backup</iconset>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="6" column="0">
<widget class="QPushButton" name="cmdUpdateRule">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Update rule</string>
</property>
<property name="icon">
<iconset theme="reload">
<normaloff>../../../../../../.designer/backup</normaloff>../../../../../../.designer/backup</iconset>
</property>
</widget>
</item>
<item row="8" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="4" column="0">
<widget class="QLabel" name="labelChecksumNote">
<property name="text">
<string/>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QComboBox" name="comboChecksumRule"/>
</item>
<item row="7" column="0">
<widget class="QLabel" name="labelChecksumStatus">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_2"> <widget class="QWidget" name="page_2">
<layout class="QGridLayout" name="gridLayout_3" rowstretch="0,0,0,0,1"> <layout class="QGridLayout" name="gridLayout_3" rowstretch="0,0,0,0,0,0">
<property name="leftMargin"> <property name="leftMargin">
<number>2</number> <number>2</number>
</property> </property>
@ -345,6 +442,44 @@
<property name="spacing"> <property name="spacing">
<number>0</number> <number>0</number>
</property> </property>
<item row="3" column="0">
<widget class="QLabel" name="messageLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string notr="true">Chromium Web Browser wants to connect to www.evilsocket.net on tcp port 443. And maybe to www.goodsocket.net on port 344</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="margin">
<number>5</number>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="Line" name="line_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="0" column="0"> <item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_3"> <layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="bottomMargin"> <property name="bottomMargin">
@ -412,6 +547,26 @@
<property name="spacing"> <property name="spacing">
<number>2</number> <number>2</number>
</property> </property>
<item row="0" column="1">
<widget class="QPushButton" name="cmdInfo">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset theme="dialog-information">
<normaloff>../../../../../../../../../../.designer/backup</normaloff>../../../../../../../../../../.designer/backup</iconset>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="appNameLabel"> <widget class="QLabel" name="appNameLabel">
<property name="sizePolicy"> <property name="sizePolicy">
@ -445,24 +600,35 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="1"> <item row="3" column="0" colspan="2">
<widget class="QPushButton" name="cmdInfo"> <widget class="QLabel" name="argsLabel">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum"> <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="font">
<font>
<pointsize>10</pointsize>
<kerning>true</kerning>
</font>
</property>
<property name="text"> <property name="text">
<string/> <string notr="true">chromium -arg1 -arg2</string>
</property> </property>
<property name="icon"> <property name="textFormat">
<iconset theme="dialog-information"> <enum>Qt::PlainText</enum>
<normaloff>.</normaloff>.</iconset>
</property> </property>
<property name="flat"> <property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="textInteractionFlags">
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget> </widget>
</item> </item>
<item row="1" column="0" colspan="2"> <item row="1" column="0" colspan="2">
@ -506,38 +672,7 @@
</sizepolicy> </sizepolicy>
</property> </property>
<property name="text"> <property name="text">
<string notr="true">(/path/to/bin/chromium)</string> <string notr="true">(/absolute/path/to/bin/chromium)</string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QLabel" name="argsLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<pointsize>10</pointsize>
<kerning>true</kerning>
</font>
</property>
<property name="text">
<string notr="true">(/path/to/bin/chromium)</string>
</property> </property>
<property name="textFormat"> <property name="textFormat">
<enum>Qt::PlainText</enum> <enum>Qt::PlainText</enum>
@ -557,20 +692,7 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="1" column="0"> <item row="5" column="0">
<widget class="Line" name="line_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="4" column="0">
<layout class="QGridLayout" name="gridLayout_2"> <layout class="QGridLayout" name="gridLayout_2">
<property name="topMargin"> <property name="topMargin">
<number>6</number> <number>6</number>
@ -946,31 +1068,6 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="3" column="0">
<widget class="QLabel" name="messageLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string notr="true">Chromium Web Browser wants to connect to www.evilsocket.net on tcp port 443. And maybe to www.goodsocket.net on port 344</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="margin">
<number>5</number>
</property>
<property name="textInteractionFlags">
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</widget> </widget>

View file

@ -132,6 +132,12 @@ class Rules(QObject):
def delete_by_field(self, field, values): def delete_by_field(self, field, values):
return self._db.delete_rules_by_field(field, values) return self._db.delete_rules_by_field(field, values)
def get_by_name(self, node, name):
return self._db.get_rule(name, node)
def get_by_field(self, node, field, value):
return self._db.get_rule_by_field(node, field, value)
def exists(self, rule, node_addr): def exists(self, rule, node_addr):
return self._db.rule_exists(rule, node_addr) return self._db.rule_exists(rule, node_addr)