Skip to content

Commit

Permalink
Merge branch 'evilsocket:master' into lan_access_control
Browse files Browse the repository at this point in the history
  • Loading branch information
nolancarougepro authored Dec 16, 2024
2 parents fa96aa3 + 80ab972 commit 31da993
Show file tree
Hide file tree
Showing 6 changed files with 395 additions and 174 deletions.
2 changes: 2 additions & 0 deletions daemon/procmon/activepids.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ func MonitorProcEvents(stop <-chan struct{}) {
// we don't receive the path of the process, therefore we need to discover it,
// to check if the PID has replaced the PPID.
proc := NewProcessWithParent(int(ev.PID), int(ev.TGID), "")
proc.GetParent()
proc.BuildTree()

log.Debug("[procmon exec event] %d, pid:%d tgid:%d %s, %s -> %s\n", ev.TimeStamp, ev.PID, ev.TGID, proc.Comm, proc.Path, proc.Parent.Path)
if item, needsUpdate, found := EventsCache.IsInStore(int(ev.PID), proc); found {
Expand Down
85 changes: 59 additions & 26 deletions ui/opensnitch/dialogs/firewall.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,10 +228,11 @@ def _check_fw_status(self):

try:
enableFw = False
if self._nodes.count() == 0:
self.sliderFwEnable.blockSignals(True)
self.sliderFwEnable.setEnabled(False)
self.sliderFwEnable.blockSignals(False)
enableFwBtn = (self._nodes.count() > 0)
self.sliderFwEnable.blockSignals(True)
self.sliderFwEnable.setEnabled(enableFwBtn)
self.sliderFwEnable.blockSignals(False)
if not enableFwBtn:
return

# TODO: handle nodes' firewall properly
Expand Down Expand Up @@ -325,33 +326,65 @@ def change_fw(self, addr, node_cfg):
return False

def enable_fw(self, enable):
self._disable_widgets(not enable)
if enable:
self._set_status_message(QC.translate("firewall", "Enabling firewall..."))
else:
self._set_status_message(QC.translate("firewall", "Disabling firewall..."))
try:
self._disable_widgets(not enable)
if enable:
self._set_status_message(QC.translate("firewall", "Enabling firewall..."))
else:
self._set_status_message(QC.translate("firewall", "Disabling firewall..."))

# if previous input policy was DROP, when disabling the firewall it
# must be ACCEPT to allow output traffic.
if not enable and self.comboInput.currentIndex() == self.POLICY_DROP:
self.comboInput.blockSignals(True)
self.comboInput.setCurrentIndex(self.POLICY_ACCEPT)
self.comboInput.blockSignals(False)
for addr in self._nodes.get():
json_profile = json.dumps(FwProfiles.ProfileAcceptInput.value)
ok, err = self._fw.apply_profile(addr, json_profile)
if not ok:
self._set_status_error(
QC.translate("firewall", "Error applying INPUT ACCEPT profile: {0}".format(err))
)
return

if not enable and self.comboOutput.currentIndex() == self.POLICY_DROP:
self.comboOutput.blockSignals(True)
self.comboOutput.setCurrentIndex(self.POLICY_ACCEPT)
self.comboOutput.blockSignals(False)
for addr in self._nodes.get():
json_profile = json.dumps(FwProfiles.ProfileAcceptOutput.value)
ok, err = self._fw.apply_profile(addr, json_profile)
if not ok:
self._set_status_error(
QC.translate("firewall", "Error applying OUTPUT ACCEPT profile: {0}".format(err))
)
return

# if previous input policy was DROP, when disabling the firewall it
# must be ACCEPT to allow output traffic.
if not enable and self.comboInput.currentIndex() == self.POLICY_DROP:
self.comboInput.blockSignals(True)
self.comboInput.setCurrentIndex(self.POLICY_ACCEPT)
self.comboInput.blockSignals(False)
for addr in self._nodes.get():
json_profile = json.dumps(FwProfiles.ProfileAcceptInput.value)
ok, err = self._fw.apply_profile(addr, json_profile)
if not ok:
print("[firewall] Error applying INPUT ACCEPT profile: {0}".format(err))
# FIXME:
# Due to how the daemon reacts to events when the fw configuration
# is modified, changing the policy + disabling the fw doesn't work
# as expected.
# The daemon detects that the fw is disabled, and it never changes
# the policy.
# As a workaround to this problem, we send 2 fw changes:
# - one for changing the policy
# - another one for disabling the fw

for addr in self._nodes.get():
fwcfg = self._nodes.get_node(addr)['firewall']
fwcfg.Enabled = True if enable else False
self.send_notification(addr, fwcfg)
fwcfg = self._nodes.get_node(addr)['firewall']
self.send_notification(addr, fwcfg)
time.sleep(0.5)
fwcfg.Enabled = True if enable else False
self.send_notification(addr, fwcfg)

self.lblStatusIcon.setEnabled(enable)
self.policiesBox.setEnabled(enable)

self.lblStatusIcon.setEnabled(enable)
self.policiesBox.setEnabled(enable)
time.sleep(0.5)

time.sleep(0.5)
except Exception as e:
QC.translate("firewall", "Error: {0}".format(e))

def load_rule(self, addr, uuid):
self._fwrule_dialog.load(addr, uuid)
Expand Down
119 changes: 84 additions & 35 deletions ui/opensnitch/dialogs/preferences.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,13 +178,17 @@ def showEvent(self, event):
self._load_langs()

self.comboNodeAddress.clear()
self.comboServerAddr.clear()
run_path = "/run/user/{0}/opensnitch/".format(os.getuid())
var_run_path = "/var{0}".format(run_path)
self.comboNodeAddress.addItem("unix:///tmp/osui.sock")
self.comboServerAddr.addItem("unix:///tmp/osui.sock")
if os.path.exists(run_path):
self.comboNodeAddress.addItem("unix://%s/osui.sock" % run_path)
self.comboServerAddr.addItem("unix://%s/osui.sock" % run_path)
if os.path.exists(var_run_path):
self.comboNodeAddress.addItem("unix://%s/osui.sock" % var_run_path)
self.comboServerAddr.addItem("unix://%s/osui.sock" % var_run_path)

self._node_list = self._nodes.get()
for addr in self._node_list:
Expand All @@ -209,6 +213,7 @@ def showEvent(self, event):
self.checkNodeLogUTC.clicked.connect(self._cb_node_needs_update)
self.checkNodeLogMicro.clicked.connect(self._cb_node_needs_update)
self.comboNodeAddress.currentTextChanged.connect(self._cb_node_needs_update)
self.comboServerAddr.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.comboNodeAction.currentIndexChanged.connect(self._cb_node_needs_update)
Expand Down Expand Up @@ -314,23 +319,6 @@ def _load_settings(self):
self.uidCheck.setChecked(self._cfg.getBool(self._cfg.DEFAULT_POPUP_ADVANCED_UID))
self.checkSum.setChecked(self._cfg.getBool(self._cfg.DEFAULT_POPUP_ADVANCED_CHECKSUM))

maxmsgsize = self._cfg.getSettings(Config.DEFAULT_SERVER_MAX_MESSAGE_LENGTH)
if maxmsgsize:
self.comboGrpcMsgSize.setCurrentText(maxmsgsize)
else:
self.comboGrpcMsgSize.setCurrentIndex(0)

self.lineCACertFile.setText(self._cfg.getSettings(Config.AUTH_CA_CERT))
self.lineCertFile.setText(self._cfg.getSettings(Config.AUTH_CERT))
self.lineCertKeyFile.setText(self._cfg.getSettings(Config.AUTH_CERTKEY))
authtype_idx = self.comboAuthType.findData(self._cfg.getSettings(Config.AUTH_TYPE))
if authtype_idx <= 0:
authtype_idx = 0
self.lineCACertFile.setEnabled(False)
self.lineCertFile.setEnabled(False)
self.lineCertKeyFile.setEnabled(False)
self.comboAuthType.setCurrentIndex(authtype_idx)

self.comboUIRules.blockSignals(True)
self.comboUIRules.setCurrentIndex(self._cfg.getInt(self._cfg.DEFAULT_IGNORE_TEMPORARY_RULES))
self.checkUIRules.setChecked(self._cfg.getBool(self._cfg.DEFAULT_IGNORE_RULES))
Expand Down Expand Up @@ -395,6 +383,28 @@ def _load_ui_settings(self):

self.checkAutostart.setChecked(self._autostart.isEnabled())

maxmsgsize = self._cfg.getSettings(Config.DEFAULT_SERVER_MAX_MESSAGE_LENGTH)
if maxmsgsize:
self.comboGrpcMsgSize.setCurrentText(maxmsgsize)
else:
self.comboGrpcMsgSize.setCurrentIndex(0)

server_addr = self._cfg.getSettings(Config.DEFAULT_SERVER_ADDR)
if server_addr == "" or server_addr == None:
server_addr = self.comboServerAddr.itemText(0)
self.comboServerAddr.setCurrentText(server_addr)

self.lineCACertFile.setText(self._cfg.getSettings(Config.AUTH_CA_CERT))
self.lineCertFile.setText(self._cfg.getSettings(Config.AUTH_CERT))
self.lineCertKeyFile.setText(self._cfg.getSettings(Config.AUTH_CERTKEY))
authtype_idx = self.comboAuthType.findData(self._cfg.getSettings(Config.AUTH_TYPE))
if authtype_idx <= 0:
authtype_idx = 0
self.lineCACertFile.setEnabled(False)
self.lineCertFile.setEnabled(False)
self.lineCertKeyFile.setEnabled(False)
self.comboAuthType.setCurrentIndex(authtype_idx)

self._load_ui_columns_config()

def _load_node_settings(self):
Expand Down Expand Up @@ -491,7 +501,6 @@ def _load_node_settings(self):

def _load_node_config(self, addr):
"""load the config of a node before sending it back to the node"""
print("_load_node_config()")
try:
if self.comboNodeAddress.currentText() == "":
return None, QC.translate("preferences", "Server address can not be empty")
Expand All @@ -504,7 +513,10 @@ def _load_node_config(self, addr):

node_duration = Config.DURATION_ONCE

node_config = json.loads(self._nodes.get_node_config(addr))
node_conf = self._nodes.get_node_config(addr)
if node_conf == None:
return None, " "
node_config = json.loads(node_conf)
node_config['DefaultAction'] = node_action
node_config['DefaultDuration'] = node_duration
node_config['ProcMonitorMethod'] = self.comboNodeMonitorMethod.currentText()
Expand Down Expand Up @@ -660,7 +672,7 @@ def _load_ui_columns_config(self):
if cols == None:
return

for c in range(8):
for c in range(13):
checked = str(c) in cols

if c == 0:
Expand All @@ -670,14 +682,26 @@ def _load_ui_columns_config(self):
elif c == 2:
self.checkHideAction.setChecked(checked)
elif c == 3:
self.checkHideDst.setChecked(checked)
self.checkHideSrcPort.setChecked(checked)
elif c == 4:
self.checkHideProto.setChecked(checked)
self.checkHideSrcIP.setChecked(checked)
elif c == 5:
self.checkHideProc.setChecked(checked)
self.checkHideDstIP.setChecked(checked)
elif c == 6:
self.checkHideCmdline.setChecked(checked)
self.checkHideDstHost.setChecked(checked)
elif c == 7:
self.checkHideDstPort.setChecked(checked)
elif c == 8:
self.checkHideProto.setChecked(checked)
elif c == 9:
self.checkHideUID.setChecked(checked)
elif c == 10:
self.checkHidePID.setChecked(checked)
elif c == 11:
self.checkHideProc.setChecked(checked)
elif c == 12:
self.checkHideCmdline.setChecked(checked)
elif c == 13:
self.checkHideRule.setChecked(checked)

def _reset_node_settings(self):
Expand Down Expand Up @@ -706,6 +730,7 @@ def _save_settings(self):
return
self._save_nodes_config()

self._set_status_successful(QC.translate("preferences", "Configuration applied."))
self.saved.emit()
self._settingsSaved = True
self._needs_restart()
Expand Down Expand Up @@ -746,8 +771,10 @@ def _save_ui_config(self):
self._save_ui_columns_config()

maxmsgsize = self.comboGrpcMsgSize.currentText()
if maxmsgsize != "":
mmsize_saved = self._cfg.getSettings(Config.DEFAULT_SERVER_MAX_MESSAGE_LENGTH)
if maxmsgsize != "" and mmsize_saved != maxmsgsize:
self._cfg.setSettings(Config.DEFAULT_SERVER_MAX_MESSAGE_LENGTH, maxmsgsize.replace(" ", ""))
self._changes_needs_restart = QC.translate("preferences", "Server options changed")

savedauthtype = self._cfg.getSettings(Config.AUTH_TYPE)
authtype = self.comboAuthType.itemData(self.comboAuthType.currentIndex())
Expand All @@ -757,6 +784,11 @@ def _save_ui_config(self):
if not self._validate_certs():
return

server_addr = self._cfg.getSettings(Config.DEFAULT_SERVER_ADDR)
if self.comboServerAddr.currentText() != server_addr:
self._cfg.setSettings(Config.DEFAULT_SERVER_ADDR, self.comboServerAddr.currentText())
self._changes_needs_restart = QC.translate("preferences", "Server address changed")

if savedauthtype != authtype or self.lineCertFile.text() != cert or \
self.lineCertKeyFile.text() != certkey or self.lineCACertFile.text() != cacert:
self._changes_needs_restart = QC.translate("preferences", "Certificates changed")
Expand Down Expand Up @@ -827,16 +859,28 @@ def _save_ui_columns_config(self):
cols.append("1")
if self.checkHideAction.isChecked():
cols.append("2")
if self.checkHideDst.isChecked():
if self.checkHideSrcPort.isChecked():
cols.append("3")
if self.checkHideProto.isChecked():
if self.checkHideSrcIP.isChecked():
cols.append("4")
if self.checkHideProc.isChecked():
if self.checkHideDstIP.isChecked():
cols.append("5")
if self.checkHideCmdline.isChecked():
if self.checkHideDstHost.isChecked():
cols.append("6")
if self.checkHideRule.isChecked():
if self.checkHideDstPort.isChecked():
cols.append("7")
if self.checkHideProto.isChecked():
cols.append("8")
if self.checkHideUID.isChecked():
cols.append("9")
if self.checkHidePID.isChecked():
cols.append("10")
if self.checkHideProc.isChecked():
cols.append("11")
if self.checkHideCmdline.isChecked():
cols.append("12")
if self.checkHideRule.isChecked():
cols.append("13")

self._cfg.setSettings(Config.STATS_SHOW_COLUMNS, cols)

Expand Down Expand Up @@ -871,17 +915,17 @@ def _save_nodes_config(self):

def _save_node_config(self, notifObject, addr):
try:
if self._nodes.count() == 0:
return
self._set_status_message(QC.translate("preferences", "Applying configuration on {0} ...").format(addr))
notifObject.data, error = self._load_node_config(addr)
if error != None:
return error

savedAddr = self._cfg.getSettings(Config.DEFAULT_SERVER_ADDR)
# exclude this message if there're more than one node connected
if self.comboNodes.count() == 1 and savedAddr != None and savedAddr != self.comboNodeAddress.currentText():
self._changes_needs_restart = QC.translate("preferences", "Ok")

self._cfg.setSettings(Config.DEFAULT_SERVER_ADDR, self.comboNodeAddress.currentText())
if self.comboNodes.currentText() != self.comboNodeAddress.currentText() or \
self.comboServerAddr.currentText() != self.comboNodeAddress.currentText():
self._changes_needs_restart = QC.translate("preferences", "Node address changed (update GUI address if needed)")

self._nodes.save_node_config(addr, notifObject.data)
nid = self._nodes.send_notification(addr, notifObject, self._notification_callback)
Expand Down Expand Up @@ -955,20 +999,25 @@ def _set_status_error(self, msg):
self._show_status_label()
self.statusLabel.setStyleSheet('color: red')
self.statusLabel.setText(msg)
QtWidgets.QApplication.processEvents()

def _set_status_successful(self, msg):
self._show_status_label()
self.statusLabel.setStyleSheet('color: green')
self.statusLabel.setText(msg)
QtWidgets.QApplication.processEvents()

def _set_status_message(self, msg):
self._show_status_label()
self.statusLabel.setStyleSheet('color: darkorange')
self.statusLabel.setText(msg)
QtWidgets.QApplication.processEvents()

def _reset_status_message(self):
self.statusLabel.setText("")
self._hide_status_label()
# force widgets repainting
QtWidgets.QApplication.processEvents()

def _enable_db_cleaner_options(self, enable, db_max_days):
self.checkDBMaxDays.setChecked(enable)
Expand Down
Loading

0 comments on commit 31da993

Please sign in to comment.