diff --git a/ui/opensnitch/auth/__init__.py b/ui/opensnitch/auth/__init__.py index 4e7159fd65..afd762beb9 100644 --- a/ui/opensnitch/auth/__init__.py +++ b/ui/opensnitch/auth/__init__.py @@ -5,6 +5,12 @@ TLSSimple = "tls-simple" TLSMutual = "tls-mutual" +NO_CLIENT_CERT = "no-client-cert" +REQ_CERT = "req-cert" +REQ_ANY_CERT = "req-any-cert" +VERIFY_CERT = "verify-cert" +REQ_AND_VERIFY_CERT = "req-and-verify-cert" + def load_file(file_path): try: diff --git a/ui/opensnitch/dialogs/preferences.py b/ui/opensnitch/dialogs/preferences.py index 4b69f42457..7bea24aa15 100644 --- a/ui/opensnitch/dialogs/preferences.py +++ b/ui/opensnitch/dialogs/preferences.py @@ -29,6 +29,10 @@ class PreferencesDialog(QtWidgets.QDialog, uic.loadUiType(DIALOG_UI_PATH)[0]): TAB_NODES = 3 TAB_DB = 4 + NODE_PAGE_GENERAL = 0 + NODE_PAGE_LOGGING = 1 + NODE_PAGE_AUTH = 2 + SUM = 1 REST = 0 @@ -36,6 +40,19 @@ class PreferencesDialog(QtWidgets.QDialog, uic.loadUiType(DIALOG_UI_PATH)[0]): AUTH_TLS_SIMPLE = 1 AUTH_TLS_MUTUAL = 2 + NODE_AUTH = { + AUTH_SIMPLE: auth.Simple, + AUTH_TLS_SIMPLE: auth.TLSSimple, + AUTH_TLS_MUTUAL: auth.TLSMutual + } + NODE_AUTH_VERIFY = { + 0: auth.NO_CLIENT_CERT, + 1: auth.REQ_CERT, + 2: auth.REQ_ANY_CERT, + 3: auth.VERIFY_CERT, + 4: auth.REQ_AND_VERIFY_CERT + } + def __init__(self, parent=None, appicon=None): QtWidgets.QDialog.__init__(self, parent, QtCore.Qt.WindowStaysOnTopHint) @@ -82,6 +99,14 @@ def __init__(self, parent=None, appicon=None): self.comboAuthType.setItemData(PreferencesDialog.AUTH_SIMPLE, auth.Simple) self.comboAuthType.setItemData(PreferencesDialog.AUTH_TLS_SIMPLE, auth.TLSSimple) self.comboAuthType.setItemData(PreferencesDialog.AUTH_TLS_MUTUAL, auth.TLSMutual) + self.comboNodeAuthType.setItemData(PreferencesDialog.AUTH_SIMPLE, auth.Simple) + self.comboNodeAuthType.setItemData(PreferencesDialog.AUTH_TLS_SIMPLE, auth.TLSSimple) + self.comboNodeAuthType.setItemData(PreferencesDialog.AUTH_TLS_MUTUAL, auth.TLSMutual) + self.comboNodeAuthVerifyType.setItemData(0, auth.NO_CLIENT_CERT) + self.comboNodeAuthVerifyType.setItemData(1, auth.REQ_CERT) + self.comboNodeAuthVerifyType.setItemData(2, auth.REQ_ANY_CERT) + self.comboNodeAuthVerifyType.setItemData(3, auth.VERIFY_CERT) + self.comboNodeAuthVerifyType.setItemData(4, auth.REQ_AND_VERIFY_CERT) self.comboUIRules.currentIndexChanged.connect(self._cb_combo_uirules_changed) @@ -162,11 +187,22 @@ def showEvent(self, event): self.comboNodeAddress.currentTextChanged.connect(self._cb_node_needs_update) self.checkInterceptUnknown.clicked.connect(self._cb_node_needs_update) self.checkApplyToNodes.clicked.connect(self._cb_node_needs_update) - self.comboDBType.currentIndexChanged.connect(self._cb_db_type_changed) - self.checkDBMaxDays.toggled.connect(self._cb_db_max_days_toggled) + self.comboNodeAction.currentIndexChanged.connect(self._cb_node_needs_update) + self.checkNodeAuthSkipVerify.clicked.connect(self._cb_node_needs_update) + self.comboNodeAuthVerifyType.currentIndexChanged.connect(self._cb_node_needs_update) + + self.comboAuthType.currentIndexChanged.connect(self._cb_combo_auth_type_changed) + self.comboNodeAuthType.currentIndexChanged.connect(self._cb_combo_node_auth_type_changed) + self.lineCACertFile.textChanged.connect(self._cb_line_certs_changed) self.lineCertFile.textChanged.connect(self._cb_line_certs_changed) self.lineCertKeyFile.textChanged.connect(self._cb_line_certs_changed) + self.lineNodeCACertFile.textChanged.connect(self._cb_node_line_certs_changed) + self.lineNodeCertFile.textChanged.connect(self._cb_node_line_certs_changed) + self.lineNodeCertKeyFile.textChanged.connect(self._cb_node_line_certs_changed) + + self.comboDBType.currentIndexChanged.connect(self._cb_db_type_changed) + self.checkDBMaxDays.toggled.connect(self._cb_db_max_days_toggled) # True when any node option changes self._node_needs_update = False @@ -298,38 +334,42 @@ def _load_settings(self): def _load_node_settings(self): addr = self.comboNodes.currentText() - if addr != "": - try: - node_data = self._node_list[addr]['data'] - self.labelNodeVersion.setText(node_data.version) - self.labelNodeName.setText(node_data.name) - self.comboNodeLogLevel.setCurrentIndex(node_data.logLevel) - - node_config = json.loads(node_data.config) - self.comboNodeAction.setCurrentText(node_config['DefaultAction']) - self.comboNodeDuration.setCurrentText(node_config['DefaultDuration']) - self.comboNodeMonitorMethod.setCurrentText(node_config['ProcMonitorMethod']) - self.checkInterceptUnknown.setChecked(node_config['InterceptUnknown']) - self.comboNodeLogLevel.setCurrentIndex(int(node_config['LogLevel'])) - - if node_config.get('LogUTC') == None: - node_config['LogUTC'] = False - self.checkNodeLogUTC.setChecked(node_config['LogUTC']) - if node_config.get('LogMicro') == None: - node_config['LogMicro'] = False - self.checkNodeLogMicro.setChecked(node_config['LogMicro']) - - if node_config.get('Server') != None: - self.comboNodeAddress.setEnabled(True) - self.comboNodeLogFile.setEnabled(True) - - self.comboNodeAddress.setCurrentText(node_config['Server']['Address']) - self.comboNodeLogFile.setCurrentText(node_config['Server']['LogFile']) - else: - self.comboNodeAddress.setEnabled(False) - self.comboNodeLogFile.setEnabled(False) - except Exception as e: - print(self.LOG_TAG + "exception loading config: ", e) + if addr == "": + return + + try: + node_data = self._node_list[addr]['data'] + self.labelNodeVersion.setText(node_data.version) + self.labelNodeName.setText(node_data.name) + self.comboNodeLogLevel.setCurrentIndex(node_data.logLevel) + + node_config = json.loads(node_data.config) + self.comboNodeAction.setCurrentText(node_config['DefaultAction']) + self.comboNodeDuration.setCurrentText(node_config['DefaultDuration']) + self.comboNodeMonitorMethod.setCurrentText(node_config['ProcMonitorMethod']) + self.checkInterceptUnknown.setChecked(node_config['InterceptUnknown']) + self.comboNodeLogLevel.setCurrentIndex(int(node_config['LogLevel'])) + + if node_config.get('LogUTC') == None: + node_config['LogUTC'] = False + self.checkNodeLogUTC.setChecked(node_config['LogUTC']) + if node_config.get('LogMicro') == None: + node_config['LogMicro'] = False + self.checkNodeLogMicro.setChecked(node_config['LogMicro']) + + if node_config.get('Server') != None: + self.comboNodeAddress.setEnabled(True) + self.comboNodeLogFile.setEnabled(True) + + self.comboNodeAddress.setCurrentText(node_config['Server']['Address']) + self.comboNodeLogFile.setCurrentText(node_config['Server']['LogFile']) + + self._load_node_auth_settings(node_config['Server']) + else: + self.comboNodeAddress.setEnabled(False) + self.comboNodeLogFile.setEnabled(False) + except Exception as e: + print(self.LOG_TAG + "exception loading config: ", e) def _load_node_config(self, addr): try: @@ -359,6 +399,10 @@ def _load_node_config(self, addr): # skip setting Server Address if we're applying the config to all nodes node_config['Server']['Address'] = self.comboNodeAddress.currentText() node_config['Server']['LogFile'] = self.comboNodeLogFile.currentText() + + cfg = self._load_node_auth_config(node_config['Server']) + if cfg != None: + node_config['Server'] = cfg else: print(addr, " doesn't have Server item") return json.dumps(node_config, indent=" "), None @@ -367,6 +411,52 @@ def _load_node_config(self, addr): return None, QC.translate("preferences", "Error loading {0} configuration").format(addr) + def _load_node_auth_settings(self, config): + try: + if config.get('Authentication') == None: + self.toolBox.setItemEnabled(self.NODE_PAGE_AUTH, False) + return + authtype_idx = self.comboNodeAuthType.findData(config['Authentication']['Type']) + self.lineNodeCACertFile.setEnabled(authtype_idx >= 0) + self.lineNodeServerCertFile.setEnabled(authtype_idx >= 0) + self.lineNodeCertFile.setEnabled(authtype_idx >= 0) + self.lineNodeCertKeyFile.setEnabled(authtype_idx >= 0) + if authtype_idx >= 0: + self.lineNodeCACertFile.setText(config['Authentication']['TLSOptions']['CACert']) + self.lineNodeServerCertFile.setText(config['Authentication']['TLSOptions']['ServerCert']) + self.lineNodeCertFile.setText(config['Authentication']['TLSOptions']['ClientCert']) + self.lineNodeCertKeyFile.setText(config['Authentication']['TLSOptions']['ClientKey']) + self.checkNodeAuthSkipVerify.setChecked(config['Authentication']['TLSOptions']['SkipVerify']) + + clienttype_idx = self.comboNodeAuthVerifyType.findData(config['Authentication']['TLSOptions']['ClientAuthType']) + if clienttype_idx >= 0: + self.comboNodeAuthVerifyType.setCurrentIndex(clienttype_idx) + else: + authtype_idx = 0 + self.comboNodeAuthType.setCurrentIndex(authtype_idx) + except Exception as e: + print("[prefs] node auth options exception:", e) + self._set_status_error(str(e)) + + def _load_node_auth_config(self, config): + try: + if config.get('Authentication') == None: + self.toolBox.setItemEnabled(self.NODE_PAGE_AUTH, False) + return + config['Authentication']['Type'] = self.NODE_AUTH[self.comboNodeAuthType.currentIndex()] + config['Authentication']['TLSOptions']['CACert']= self.lineNodeCACertFile.text() + config['Authentication']['TLSOptions']['ServerCert'] = self.lineNodeServerCertFile.text() + config['Authentication']['TLSOptions']['ClientCert'] = self.lineNodeCertFile.text() + config['Authentication']['TLSOptions']['ClientKey'] = self.lineNodeCertKeyFile.text() + config['Authentication']['TLSOptions']['SkipVerify'] = self.checkNodeAuthSkipVerify.isChecked() + config['Authentication']['TLSOptions']['ClientAuthType'] = self.NODE_AUTH_VERIFY[self.comboNodeAuthVerifyType.currentIndex()] + + return config + except Exception as e: + print("[prefs] node auth options exception:", e) + self._set_status_error(str(e)) + return None + def _load_ui_columns_config(self): cols = self._cfg.getSettings(Config.STATS_SHOW_COLUMNS) if cols == None: @@ -405,39 +495,11 @@ def _reset_node_settings(self): def _save_settings(self): self._reset_status_message() + self._show_status_label() self._save_ui_config() if not self._save_db_config(): return - - if self.tabWidget.currentIndex() == self.TAB_NODES: - self._show_status_label() - - addr = self.comboNodes.currentText() - if (self._node_needs_update or self.checkApplyToNodes.isChecked()) and addr != "": - try: - notif = ui_pb2.Notification( - id=int(str(time.time()).replace(".", "")), - type=ui_pb2.CHANGE_CONFIG, - data="", - rules=[]) - if self.checkApplyToNodes.isChecked(): - for addr in self._nodes.get_nodes(): - error = self._save_node_config(notif, addr) - if error != None: - self._set_status_error(error) - return - else: - error = self._save_node_config(notif, addr) - if error != None: - self._set_status_error(error) - return - except Exception as e: - print(self.LOG_TAG + "exception saving config: ", e) - self._set_status_error(QC.translate("preferences", "Exception saving config: {0}").format(str(e))) - elif addr == "": - self._set_status_message(QC.translate("preferences", "There're no nodes connected")) - - self._node_needs_update = False + self._save_nodes_config() self.saved.emit() self._settingsSaved = True @@ -564,6 +626,34 @@ def _save_ui_columns_config(self): self._cfg.setSettings(Config.STATS_SHOW_COLUMNS, cols) + def _save_nodes_config(self): + addr = self.comboNodes.currentText() + if (self._node_needs_update or self.checkApplyToNodes.isChecked()) and addr != "": + try: + notif = ui_pb2.Notification( + id=int(str(time.time()).replace(".", "")), + type=ui_pb2.CHANGE_CONFIG, + data="", + rules=[]) + if self.checkApplyToNodes.isChecked(): + for addr in self._nodes.get_nodes(): + error = self._save_node_config(notif, addr) + if error != None: + self._set_status_error(error) + return + else: + error = self._save_node_config(notif, addr) + if error != None: + self._set_status_error(error) + return + except Exception as e: + print(self.LOG_TAG + "exception saving config: ", e) + self._set_status_error(QC.translate("preferences", "Exception saving config: {0}").format(str(e))) + elif addr == "": + self._set_status_message(QC.translate("preferences", "There're no nodes connected")) + + self._node_needs_update = False + def _save_node_config(self, notifObject, addr): try: self._set_status_message(QC.translate("preferences", "Applying configuration on {0} ...").format(addr)) @@ -589,6 +679,34 @@ def _save_node_config(self, notifObject, addr): return None + def _save_node_auth_config(self, config): + try: + if config.get('Authentication') == None: + self.toolBox.setItemEnabled(self.NODE_PAGE_AUTH, False) + return + authtype_idx = self.comboNodeAuthType.findData(config['Authentication']['Type']) + self.lineNodeCACertFile.setEnabled(authtype_idx >= 0) + self.lineNodeServerCertFile.setEnabled(authtype_idx >= 0) + self.lineNodeCertFile.setEnabled(authtype_idx >= 0) + self.lineNodeCertKeyFile.setEnabled(authtype_idx >= 0) + if authtype_idx >= 0: + self.lineNodeCACertFile.setText(config['Authentication']['TLSOptions']['CACert']) + self.lineNodeServerCertFile.setText(config['Authentication']['TLSOptions']['ServerCert']) + self.lineNodeCertFile.setText(config['Authentication']['TLSOptions']['ClientCert']) + self.lineNodeCertKeyFile.setText(config['Authentication']['TLSOptions']['ClientKey']) + self.checkNodeAuthSkipVerify.setChecked(config['Authentication']['TLSOptions']['SkipVerify']) + + clienttype_idx = self.comboNodeAuthVerifyType.findData(config['Authentication']['TLSOptions']['ClientAuthType']) + if clienttype_idx >= 0: + self.comboNodeAuthVerifyType.setCurrentIndex(clienttype_idx) + else: + authtype_idx = 0 + self.comboNodeAuthType.setCurrentIndex(authtype_idx) + except Exception as e: + print("[prefs] node auth options exception:", e) + self._set_status_error(str(e)) + + def _validate_certs(self): try: if self.comboAuthType.currentIndex() == PreferencesDialog.AUTH_SIMPLE: @@ -677,6 +795,10 @@ def _cb_notification_callback(self, reply): def _cb_line_certs_changed(self, text): self._changes_needs_restart = QC.translate("preferences", "Certs changed") + def _cb_node_line_certs_changed(self, text): + self._changes_needs_restart = QC.translate("preferences", "Node certs changed") + self._node_needs_update = True + def _cb_file_db_clicked(self): options = QtWidgets.QFileDialog.Options() fileName, _ = QtWidgets.QFileDialog.getSaveFileName(self, "", "","All Files (*)", options=options) @@ -744,6 +866,21 @@ def _cb_combo_auth_type_changed(self, index): self.lineCertFile.setEnabled(index >= PreferencesDialog.AUTH_TLS_SIMPLE) self.lineCertKeyFile.setEnabled(index >= PreferencesDialog.AUTH_TLS_SIMPLE) + def _cb_combo_node_auth_type_changed(self, index): + curtype = self.comboNodeAuthType.itemData(self.comboNodeAuthType.currentIndex()) + #savedtype = self._cfg.getSettings(Config.AUTH_TYPE) + #if curtype != savedtype: + # self._changes_needs_restart = QC.translate("preferences", "Auth type changed") + + self.lineNodeCACertFile.setEnabled(index == PreferencesDialog.AUTH_TLS_MUTUAL) + self.lineNodeServerCertFile.setEnabled(index >= PreferencesDialog.AUTH_TLS_SIMPLE) + self.lineNodeCertFile.setEnabled(index >= PreferencesDialog.AUTH_TLS_SIMPLE) + self.lineNodeCertKeyFile.setEnabled(index >= PreferencesDialog.AUTH_TLS_SIMPLE) + self.checkNodeAuthSkipVerify.setEnabled(index >= PreferencesDialog.AUTH_TLS_SIMPLE) + self.comboNodeAuthVerifyType.setEnabled(index >= PreferencesDialog.AUTH_TLS_SIMPLE) + + self._node_needs_update = True + def _cb_db_max_days_toggled(self, state): self._enable_db_cleaner_options(state, 1) diff --git a/ui/opensnitch/res/preferences.ui b/ui/opensnitch/res/preferences.ui index 3c6d5f0af9..e6c56a5018 100644 --- a/ui/opensnitch/res/preferences.ui +++ b/ui/opensnitch/res/preferences.ui @@ -7,13 +7,90 @@ 0 0 626 - 442 + 503 Preferences + + + + true + + + + + + + + + true + + + + + + + + + + ../../../../../../../../../../.designer/backup../../../../../../../../../../.designer/backup + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Close + + + + ../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../.designer/backup../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../.designer/backup + + + + + + + Apply + + + + ../../../../../../../../../../.designer/backup../../../../../../../../../../.designer/backup + + + + + + + Save + + + + ../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../.designer/backup../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../.designer/backup + + + + + @@ -39,6 +116,94 @@ Pop-ups + + + + + 0 + 0 + + + + <html><head/><body><p>This timeout is the countdown you see when a pop-up dialog is shown.</p><p>If the pop-up is not answered, the default options will be applied.</p></body></html> + + + Default timeout + + + + + + + 0 + + + + + + 0 + 0 + + + + + + + + ../../../../../../../../../../.designer/backup../../../../../../../../../../.designer/backup + + + true + + + + + + + + 0 + 0 + + + + Qt::AlignCenter + + + QAbstractSpinBox::NoButtons + + + true + + + 100 + + + 30 + + + + + + + + 0 + 0 + + + + + + + + ../../../../../../../../../../.designer/backup../../../../../../../../../../.designer/backup + + + true + + + + + @@ -156,7 +321,7 @@ - <html><head/><body><p>Pop-up default action.</p><p>When a new outgoing connection is about to be established, this action will be selected by default, so if the timeout fires, this is the option that will be applied.</p><p><br/></p><p>While a pop-up is asking the user to allow or deny a connection:</p><p>1. new outgoing connections are denied.</p><p>2. known connections are allowed or denied based on the rules defined by the user.</p></body></html> + <html><head/><body><p>Pop-up default action.</p><p>When a new outgoing connection is about to be established, this action will be selected by default, so if the timeout fires, this is the option that will be applied.</p><p>While a pop-up is asking the user to allow or deny a connection:</p><p>1. the daemon's default action will be applied (see Nodes tab).</p><p>2. known connections are allowed or denied based on the rules defined by the user.</p></body></html> Action @@ -382,94 +547,6 @@ - - - - 0 - - - - - - 0 - 0 - - - - - - - - ../../../../../../../../../../.designer/backup../../../../../../../../../../.designer/backup - - - true - - - - - - - - 0 - 0 - - - - Qt::AlignCenter - - - QAbstractSpinBox::NoButtons - - - true - - - 100 - - - 30 - - - - - - - - 0 - 0 - - - - - - - - ../../../../../../../../../../.designer/backup../../../../../../../../../../.designer/backup - - - true - - - - - - - - - - 0 - 0 - - - - <html><head/><body><p>This timeout is the countdown you see when a pop-up dialog is shown.</p><p>If the pop-up is not answered, the default options will be applied.</p></body></html> - - - Default timeout - - - @@ -493,6 +570,14 @@ 0 + + + 0 + 0 + 586 + 270 + + General @@ -564,6 +649,14 @@ + + + 0 + 0 + 586 + 270 + + Server @@ -762,7 +855,7 @@ 0 0 586 - 238 + 209 @@ -1006,69 +1099,44 @@ Temporary rules will still be valid, and you can use them when prompted to allow Nodes - - - + + + - + 0 0 - HostName - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + Apply configuration to all nodes - - - - Qt::Horizontal - - - QSizePolicy::Preferred - - - - 40 - 20 - - - - - - + + - + 0 0 - + Version Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - + + - + 0 0 - - Version - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - @@ -1087,26 +1155,35 @@ Temporary rules will still be valid, and you can use them when prompted to allow - - - - - 0 - 0 - + + + + Qt::Horizontal - + + QSizePolicy::Preferred + + + + 40 + 20 + + + - - + + - + 0 0 - Apply configuration to all nodes + + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop @@ -1121,48 +1198,55 @@ Temporary rules will still be valid, and you can use them when prompted to allow 0 0 586 - 197 + 229 General - - + + - <html><head/><body><p>Address of the node.</p><p>Default: unix:///tmp/osui.sock (unix:// is mandatory if it's a Unix socket)</p><p>It can also be an IP address with the port: 127.0.0.1:50051</p></body></html> + <html><head/><body><p>The default action will be applied to new outbound connections in two scenarios:</p><p>when the daemon is not connected to the UI, or when there's a pop-up running.</p></body></html> - Address + Default action when the GUI is disconnected - - - - - + true - - - unix:///tmp/osui.sock - - - - + + - <html><head/><body><p>The default action will take place when there's no UI connected.</p></body></html> + <html><head/><body><p>The default duration will take place when there's no UI connected.</p></body></html> - Default action when the GUI is disconnected - - - true + Default duration + + + + + once + + + + + until restart + + + + + always + + + + @@ -1188,31 +1272,24 @@ Temporary rules will still be valid, and you can use them when prompted to allow - - - - <html><head/><body><p>The default duration will take place when there's no UI connected.</p></body></html> - - - Default duration + + + + - - - - - once + proc - until restart + ebpf - always + audit @@ -1227,38 +1304,38 @@ Temporary rules will still be valid, and you can use them when prompted to allow - - + + - + Process monitor method - - + + + + <html><head/><body><p>Address of the node.</p><p>Default: unix:///tmp/osui.sock (unix:// is mandatory if it's a Unix socket)</p><p>It can also be an IP address with the port: 127.0.0.1:50051</p></body></html> + - Process monitor method + Address - - - - + + + + + + + + + + + true - proc - - - - - ebpf - - - - - audit + unix:///tmp/osui.sock @@ -1270,8 +1347,8 @@ Temporary rules will still be valid, and you can use them when prompted to allow 0 0 - 376 - 118 + 586 + 229 @@ -1401,6 +1478,146 @@ Temporary rules will still be valid, and you can use them when prompted to allow + + + Authentication + + + + + + Absolute path to the cert file + + + + + + + + + <p>Simple: no authentication, TLS simple/mutual: use SSL certificates to authenticate nodes.</p><p>Visit the wiki for more information.</p> + + + Authentication type + + + + + + + + 0 + 0 + + + + + Simple + + + + + Simple TLS + + + + + Mutual TLS + + + + + + + + + + Absolute path to the CA cert file + + + + + + + + + Don't verify certs + + + + + + + + no-client-cert + + + + + req-cert + + + + + req-any-cert + + + + + verify-cert + + + + + req-and-verify-cert + + + + + + + + + + Absolute path to the cert key file + + + + + + + Absolute path to the server cert file + + + + + + + <html><head/><body><p><a href="https://github.com/evilsocket/opensnitch/wiki/Nodes-authentication#nodes-authentication-added-in-v161"><span style=" text-decoration: underline; color:#0000ff;">More information</span></a></p></body></html> + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + + + + + + 0 + 0 + + + + HostName + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + @@ -1705,83 +1922,6 @@ Temporary rules will still be valid, and you can use them when prompted to allow - - - - true - - - - - - - - - true - - - - - - - - - - ../../../../../../../../../../.designer/backup../../../../../../../../../../.designer/backup - - - true - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Close - - - - ../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../.designer/backup../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../.designer/backup - - - - - - - Apply - - - - ../../../../../../../../../../.designer/backup../../../../../../../../../../.designer/backup - - - - - - - Save - - - - ../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../.designer/backup../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../.designer/backup - - - - -