From 0d80af45c296e6658c6b81c6c5295d29a1a1059c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20I=C3=B1iguez=20Goia?= Date: Thu, 25 Jun 2020 18:52:29 +0200 Subject: [PATCH 1/6] UI: force to bring the allow/deny pop-up to the front This solves an issue where the pop-up was only displayed on the same screen/desktop/workspace where the main window was. --- ui/opensnitch/dialogs/prompt.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/opensnitch/dialogs/prompt.py b/ui/opensnitch/dialogs/prompt.py index 58eb2edb0d..4094d8cad7 100644 --- a/ui/opensnitch/dialogs/prompt.py +++ b/ui/opensnitch/dialogs/prompt.py @@ -34,7 +34,7 @@ class PromptDialog(QtWidgets.QDialog, uic.loadUiType(DIALOG_UI_PATH)[0]): def __init__(self, parent=None): QtWidgets.QDialog.__init__(self, parent, QtCore.Qt.WindowStaysOnTopHint) - + # Other interesting flags: QtCore.Qt.Tool | QtCore.Qt.BypassWindowManagerHint self._cfg = Config.get() self.setupUi(self) @@ -78,6 +78,7 @@ def __init__(self, parent=None): def showEvent(self, event): super(PromptDialog, self).showEvent(event) self.resize(540, 300) + self.activateWindow() def _checkbox_toggled(self, state): self.applyButton.setText("%s" % self._apply_text) From 8494bfd9829e9171f887d19619ec0c262a41ddbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20I=C3=B1iguez=20Goia?= Date: Fri, 26 Jun 2020 21:53:17 +0200 Subject: [PATCH 2/6] UI: changed preferences dialog title --- ui/opensnitch/res/preferences.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/opensnitch/res/preferences.ui b/ui/opensnitch/res/preferences.ui index dec55438f2..aa503cbb6d 100644 --- a/ui/opensnitch/res/preferences.ui +++ b/ui/opensnitch/res/preferences.ui @@ -11,7 +11,7 @@ - Dialog + Preferences From 97139ecc6be2a9bd0dc18766bcae5c143deec26d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20I=C3=B1iguez=20Goia?= Date: Fri, 26 Jun 2020 22:47:44 +0200 Subject: [PATCH 3/6] UI: shorten default rules name Default rules name can be extremely long when the rule is of type list. It still will be in some cases, but should work in most cases. closes #37 --- ui/opensnitch/dialogs/prompt.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/ui/opensnitch/dialogs/prompt.py b/ui/opensnitch/dialogs/prompt.py index 4094d8cad7..fdcfe9af7c 100644 --- a/ui/opensnitch/dialogs/prompt.py +++ b/ui/opensnitch/dialogs/prompt.py @@ -361,6 +361,16 @@ def _on_apply_clicked(self): self._default_action = self.ACTION_ALLOW self._send_rule() + def _get_rule_name(self): + rule_temp_name = slugify("%s %s" % (self._rule.action, self._rule.duration)) + if self._ischeckAdvanceded: + rule_temp_name = "%s-list" % rule_temp_name + else: + rule_temp_name = "%s-simple" % rule_temp_name + rule_temp_name = slugify("%s %s" % (rule_temp_name, self._rule.operator.data)) + + return rule_temp_name + def _send_rule(self): self._cfg.setSettings("promptDialog/geometry", self.saveGeometry()) self._rule = ui_pb2.Rule(name="user.choice") @@ -373,17 +383,21 @@ def _send_rule(self): 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) + rule_temp_name = self._get_rule_name() + # TODO: move to a method data=[] if self._ischeckAdvanceded and self.checkDstIP.isChecked() and self.whatCombo.itemData(what_idx) != "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._ischeckAdvanceded and self.checkDstPort.isChecked() and self.whatCombo.itemData(what_idx) != "dst_port": data.append({"type": "simple", "operand": "dest.port", "data": str(self._con.dst_port)}) if self._ischeckAdvanceded and self.checkUserID.isChecked() and self.whatCombo.itemData(what_idx) != "user_id": data.append({"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._ischeckAdvanceded: data.append({"type": self._rule.operator.type, "operand": self._rule.operator.operand, "data": self._rule.operator.data}) @@ -391,7 +405,7 @@ def _send_rule(self): self._rule.operator.type = "list" self._rule.operator.operand = "" - self._rule.name = slugify("%s %s %s" % (self._rule.action, self._rule.operator.type, self._rule.operator.data)) + self._rule.name = rule_temp_name self.hide() if self._ischeckAdvanceded: From ace124ad6a6946bc5ba6686deefd8022db078fe5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20I=C3=B1iguez=20Goia?= Date: Mon, 20 Jul 2020 23:59:14 +0200 Subject: [PATCH 4/6] added the host to the options of the pop-up dialog The host to where a process is connecting to was missing in the options list, when the connection to allow was a query to resolve the domain name. Reported here: #48 Also added the connection port to the rule name. --- ui/opensnitch/dialogs/prompt.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/ui/opensnitch/dialogs/prompt.py b/ui/opensnitch/dialogs/prompt.py index fdcfe9af7c..a881df0a31 100644 --- a/ui/opensnitch/dialogs/prompt.py +++ b/ui/opensnitch/dialogs/prompt.py @@ -256,16 +256,17 @@ def _render_connection(self, con): if con.dst_host != "" and con.dst_host != con.dst_ip: try: - dst_host = re.search("(.*)\s\((.*)\)", con.dst_host) + # get the domain that a process is trying to resolve. format: 1.1.1.1 (host.example.com) + dst_host_regexp = re.search("(.*)\s\((.*)\)", con.dst_host) except Exception: pass - if dst_host != None and len(dst_host.groups()) == 2: - self._add_dsthost_to_combo(dst_host.group(2)) - else: - dst_host = con.dst_host - self.whatCombo.addItem("%s" % con.dst_host, "simple_host") - self._add_dsthost_to_combo(con.dst_host) + dst_host = con.dst_host + if dst_host_regexp != None and len(dst_host_regexp.groups()) == 2: + dst_host = dst_host_regexp.group(2) + print("host regexp: " + dst_host) + + self._add_dsthost_to_combo(dst_host) self.whatIPCombo.addItem("to %s" % con.dst_ip, "dst_ip") @@ -300,6 +301,9 @@ def closeEvent(self, e): e.ignore() def _add_dsthost_to_combo(self, dst_host): + self.whatCombo.addItem("%s" % dst_host, "simple_host") + self.whatIPCombo.addItem("%s" % dst_host, "simple_host") + parts = dst_host.split('.')[1:] nparts = len(parts) for i in range(0, nparts - 1): @@ -345,7 +349,7 @@ def _get_combo_operator(self, combo, what_idx): return "simple", "dest.ip", self._con.dst_ip elif combo.itemData(what_idx) == "simple_host": - return "simple", "dest.host", self._con.dst_host + return "simple", "dest.host", combo.currentText() elif combo.itemData(what_idx) == "regex_host": return "regexp", "dest.host", "%s" % '\.'.join(combo.currentText().split('.')).replace("*", ".*")[3:] @@ -394,6 +398,7 @@ def _send_rule(self): if self._ischeckAdvanceded and self.checkDstPort.isChecked() and self.whatCombo.itemData(what_idx) != "dst_port": data.append({"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._ischeckAdvanceded and self.checkUserID.isChecked() and self.whatCombo.itemData(what_idx) != "user_id": data.append({"type": "simple", "operand": "user.id", "data": str(self._con.user_id)}) From dba0c83ced3d6da402aeef29b24f3e024bbb963c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20I=C3=B1iguez=20Goia?= Date: Tue, 28 Jul 2020 18:23:21 +0200 Subject: [PATCH 5/6] fixed crash when clicking on a General tab wrong column Reported here: https://github.com/gustavo-iniguez-goya/opensnitch/issues/38#issuecomment-665006899 --- ui/opensnitch/dialogs/stats.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/opensnitch/dialogs/stats.py b/ui/opensnitch/dialogs/stats.py index 45b7bd3e33..57cb67664b 100644 --- a/ui/opensnitch/dialogs/stats.py +++ b/ui/opensnitch/dialogs/stats.py @@ -573,6 +573,8 @@ def _cb_main_table_double_clicked(self, row): elif idx == StatsDialog.COL_RULES: cur_idx = 2 self._set_rules_tab_active(row, cur_idx) + else: + return self._set_active_widgets(True, str(data)) From d137a50d417297787f689c623f0f2cb6765d181f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20I=C3=B1iguez=20Goia?= Date: Tue, 28 Jul 2020 22:38:53 +0200 Subject: [PATCH 6/6] check GUI and daemon versions granularly Do not display the warning dialog about diferent versions (daemon<->GUI), if we only have relesed fixes or minor changes. --- ui/opensnitch/service.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ui/opensnitch/service.py b/ui/opensnitch/service.py index e95462d5b0..5db3a3ab1d 100644 --- a/ui/opensnitch/service.py +++ b/ui/opensnitch/service.py @@ -220,6 +220,12 @@ def _async_worker(self): self._status_change_trigger.emit() was_connected = self._connected + def _check_versions(self, daemon_version): + lMayor, lMinor, lPatch = version.split(".") + rMayor, rMinor, rPatch = daemon_version.split(".") + if lMayor != rMayor or (lMayor == rMayor and lMinor != rMinor): + self._version_warning_trigger.emit(daemon_version, version) + def _is_local_request(self, proto, addr): if proto == "unix": return True @@ -372,8 +378,7 @@ def _populate_stats_events(self, db, addr, stats, table, colnames, cols, items): def Ping(self, request, context): try: self._last_ping = datetime.now() - if request.stats.daemon_version != version: - self._version_warning_trigger.emit(request.stats.daemon_version, version) + self._check_versions(request.stats.daemon_version) proto, addr = self._get_peer(context.peer()) # do not update db here, do it on the main thread