mirror of
https://github.com/evilsocket/opensnitch.git
synced 2025-03-04 00:24:40 +01:00
xdg updates + autostart + lockfile (#964)
* require pyxdg * extend xdg, introduce autostart * use xdg_current_desktop from opensnitch.utils.xdg * control autostart in tray * dont use pkill anymore * check if os-ui is already running * don't require pyxdg (for now) * simplify xdg_current_desktop * do not use pyxdg (for now), use some code from there * update autostart status when menu is open * fix possible SameFileError
This commit is contained in:
parent
6e61958c23
commit
59621017e9
5 changed files with 205 additions and 74 deletions
|
@ -40,11 +40,13 @@ if dist_path not in sys.path:
|
|||
from opensnitch.service import UIService
|
||||
from opensnitch.config import Config
|
||||
from opensnitch.utils import Themes, Utils, Versions
|
||||
from opensnitch.utils.xdg import xdg_runtime_dir
|
||||
import opensnitch.ui_pb2
|
||||
from opensnitch.ui_pb2_grpc import add_UIServicer_to_server
|
||||
|
||||
def on_exit():
|
||||
server.stop(0)
|
||||
lockfile.unlock()
|
||||
app.quit()
|
||||
sys.exit(0)
|
||||
|
||||
|
@ -92,75 +94,91 @@ Examples:
|
|||
except Exception:
|
||||
pass
|
||||
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
if hasattr(QtCore.Qt, 'AA_UseHighDpiPixmaps'):
|
||||
app.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True)
|
||||
thm = Themes.instance()
|
||||
thm.load_theme(app)
|
||||
|
||||
Utils.create_socket_dirs()
|
||||
cfg = Config.get()
|
||||
if args.socket == None:
|
||||
# default
|
||||
args.socket = "unix:///tmp/osui.sock"
|
||||
|
||||
addr = cfg.getSettings(Config.DEFAULT_SERVER_ADDR)
|
||||
if addr != None and addr != "":
|
||||
if addr.startswith("unix://"):
|
||||
if not os.path.exists(os.path.dirname(addr[7:])):
|
||||
print("WARNING: unix socket path does not exist, using unix:///tmp/osui.sock, ", addr)
|
||||
else:
|
||||
args.socket = addr
|
||||
else:
|
||||
args.socket = addr
|
||||
|
||||
print("Using server address:", args.socket)
|
||||
|
||||
maxmsglencfg = cfg.getSettings(Config.DEFAULT_SERVER_MAX_MESSAGE_LENGTH)
|
||||
if maxmsglencfg == '4MiB':
|
||||
maxmsglen = 4194304
|
||||
elif maxmsglencfg == '8MiB':
|
||||
maxmsglen = 8388608
|
||||
elif maxmsglencfg == '16MiB':
|
||||
maxmsglen = 16777216
|
||||
else:
|
||||
maxmsglen = 4194304
|
||||
|
||||
print("gRPC Max Message Length:", maxmsglencfg)
|
||||
print(" Bytes:", maxmsglen)
|
||||
|
||||
service = UIService(app, on_exit)
|
||||
# @doc: https://grpc.github.io/grpc/python/grpc.html#server-object
|
||||
server = grpc.server(futures.ThreadPoolExecutor(),
|
||||
options=(
|
||||
# https://github.com/grpc/grpc/blob/master/doc/keepalive.md
|
||||
# https://grpc.github.io/grpc/core/group__grpc__arg__keys.html
|
||||
# send keepalive ping every 5 second, default is 2 hours)
|
||||
('grpc.keepalive_time_ms', 5000),
|
||||
# after 5s of inactivity, wait 20s and close the connection if
|
||||
# there's no response.
|
||||
('grpc.keepalive_timeout_ms', 20000),
|
||||
('grpc.keepalive_permit_without_calls', True),
|
||||
('grpc.max_send_message_length', maxmsglen),
|
||||
('grpc.max_receive_message_length', maxmsglen),
|
||||
))
|
||||
|
||||
add_UIServicer_to_server(service, server)
|
||||
|
||||
if args.socket.startswith("unix://"):
|
||||
socket = args.socket[7:]
|
||||
socket = os.path.abspath(socket)
|
||||
server.add_insecure_port("unix:%s" % socket)
|
||||
else:
|
||||
server.add_insecure_port(args.socket)
|
||||
|
||||
# https://stackoverflow.com/questions/5160577/ctrl-c-doesnt-work-with-pyqt
|
||||
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
||||
|
||||
try:
|
||||
# print "OpenSnitch UI service running on %s ..." % socket
|
||||
server.start()
|
||||
app.exec_()
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
lockfile = QtCore.QLockFile(os.path.join(xdg_runtime_dir, 'osui.lock'))
|
||||
|
||||
if lockfile.tryLock(100):
|
||||
if hasattr(QtCore.Qt, 'AA_UseHighDpiPixmaps'):
|
||||
app.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True)
|
||||
thm = Themes.instance()
|
||||
thm.load_theme(app)
|
||||
|
||||
Utils.create_socket_dirs()
|
||||
cfg = Config.get()
|
||||
if args.socket == None:
|
||||
# default
|
||||
args.socket = "unix:///tmp/osui.sock"
|
||||
|
||||
addr = cfg.getSettings(Config.DEFAULT_SERVER_ADDR)
|
||||
if addr != None and addr != "":
|
||||
if addr.startswith("unix://"):
|
||||
if not os.path.exists(os.path.dirname(addr[7:])):
|
||||
print("WARNING: unix socket path does not exist, using unix:///tmp/osui.sock, ", addr)
|
||||
else:
|
||||
args.socket = addr
|
||||
else:
|
||||
args.socket = addr
|
||||
|
||||
print("Using server address:", args.socket)
|
||||
|
||||
maxmsglencfg = cfg.getSettings(Config.DEFAULT_SERVER_MAX_MESSAGE_LENGTH)
|
||||
if maxmsglencfg == '4MiB':
|
||||
maxmsglen = 4194304
|
||||
elif maxmsglencfg == '8MiB':
|
||||
maxmsglen = 8388608
|
||||
elif maxmsglencfg == '16MiB':
|
||||
maxmsglen = 16777216
|
||||
else:
|
||||
maxmsglen = 4194304
|
||||
|
||||
print("gRPC Max Message Length:", maxmsglencfg)
|
||||
print(" Bytes:", maxmsglen)
|
||||
|
||||
service = UIService(app, on_exit)
|
||||
# @doc: https://grpc.github.io/grpc/python/grpc.html#server-object
|
||||
server = grpc.server(futures.ThreadPoolExecutor(),
|
||||
options=(
|
||||
# https://github.com/grpc/grpc/blob/master/doc/keepalive.md
|
||||
# https://grpc.github.io/grpc/core/group__grpc__arg__keys.html
|
||||
# send keepalive ping every 5 second, default is 2 hours)
|
||||
('grpc.keepalive_time_ms', 5000),
|
||||
# after 5s of inactivity, wait 20s and close the connection if
|
||||
# there's no response.
|
||||
('grpc.keepalive_timeout_ms', 20000),
|
||||
('grpc.keepalive_permit_without_calls', True),
|
||||
('grpc.max_send_message_length', maxmsglen),
|
||||
('grpc.max_receive_message_length', maxmsglen),
|
||||
))
|
||||
|
||||
add_UIServicer_to_server(service, server)
|
||||
|
||||
if args.socket.startswith("unix://"):
|
||||
socket = args.socket[7:]
|
||||
socket = os.path.abspath(socket)
|
||||
server.add_insecure_port("unix:%s" % socket)
|
||||
else:
|
||||
server.add_insecure_port(args.socket)
|
||||
|
||||
# https://stackoverflow.com/questions/5160577/ctrl-c-doesnt-work-with-pyqt
|
||||
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
||||
|
||||
# print "OpenSnitch UI service running on %s ..." % socket
|
||||
server.start()
|
||||
app.exec_()
|
||||
|
||||
else:
|
||||
errortxt = "OpenSnitch UI is already running!"
|
||||
print(errortxt, "\n")
|
||||
errormsg = QtWidgets.QMessageBox()
|
||||
errormsg.setIcon(QtWidgets.QMessageBox.Warning)
|
||||
errormsg.setWindowTitle("Error")
|
||||
errormsg.setText(errortxt)
|
||||
errormsg.setStandardButtons(QtWidgets.QMessageBox.Ok)
|
||||
errormsg.exec()
|
||||
|
||||
except KeyboardInterrupt:
|
||||
on_exit()
|
||||
|
||||
finally:
|
||||
lockfile.unlock()
|
||||
|
|
|
@ -23,6 +23,7 @@ from opensnitch.customwidgets.firewalltableview import FirewallTableModel
|
|||
from opensnitch.customwidgets.generictableview import GenericTableModel
|
||||
from opensnitch.customwidgets.addresstablemodel import AddressTableModel
|
||||
from opensnitch.utils import Message, QuickHelp, AsnDB, Icons
|
||||
from opensnitch.utils.xdg import xdg_current_desktop
|
||||
from opensnitch.actions import Actions
|
||||
from opensnitch.rules import Rule, Rules
|
||||
|
||||
|
@ -277,8 +278,6 @@ class StatsDialog(QtWidgets.QDialog, uic.loadUiType(DIALOG_UI_PATH)[0]):
|
|||
def __init__(self, parent=None, address=None, db=None, dbname="db", appicon=None):
|
||||
super(StatsDialog, self).__init__(parent)
|
||||
|
||||
self._current_desktop = os.environ['XDG_CURRENT_DESKTOP'] if os.environ.get("XDG_CURRENT_DESKTOP") != None else None
|
||||
|
||||
self.setWindowFlags(QtCore.Qt.Window)
|
||||
self.setupUi(self)
|
||||
self.setWindowIcon(appicon)
|
||||
|
@ -625,7 +624,7 @@ class StatsDialog(QtWidgets.QDialog, uic.loadUiType(DIALOG_UI_PATH)[0]):
|
|||
if event.type() == QtCore.QEvent.WindowStateChange:
|
||||
if event.oldState() & QtCore.Qt.WindowMinimized and event.oldState() & QtCore.Qt.WindowMaximized:
|
||||
#a previously minimized maximized window ...
|
||||
if self.windowState() ^ QtCore.Qt.WindowMinimized and self._current_desktop == "KDE":
|
||||
if self.windowState() ^ QtCore.Qt.WindowMinimized and xdg_current_desktop == "KDE":
|
||||
# is not minimized anymore, i.e. it was unminimized
|
||||
# docs: https://doc.qt.io/qt-5/qwidget.html#setWindowState
|
||||
self.setWindowState(self.windowState() & ~QtCore.Qt.WindowMinimized | QtCore.Qt.WindowActive)
|
||||
|
|
|
@ -26,6 +26,7 @@ from opensnitch.version import version
|
|||
from opensnitch.database import Database
|
||||
from opensnitch.utils import Utils, CleanerTask, Themes
|
||||
from opensnitch.utils import Message, languages
|
||||
from opensnitch.utils.xdg import Autostart
|
||||
|
||||
class UIService(ui_pb2_grpc.UIServicer, QtWidgets.QGraphicsObject):
|
||||
_new_remote_trigger = QtCore.pyqtSignal(str, ui_pb2.PingRequest)
|
||||
|
@ -87,6 +88,7 @@ class UIService(ui_pb2_grpc.UIServicer, QtWidgets.QGraphicsObject):
|
|||
self._msg = QtWidgets.QMessageBox()
|
||||
self._remote_lock = Lock()
|
||||
self._remote_stats = {}
|
||||
self._autostart = Autostart()
|
||||
|
||||
self.translator = None
|
||||
self._init_translation()
|
||||
|
@ -181,11 +183,27 @@ class UIService(ui_pb2_grpc.UIServicer, QtWidgets.QGraphicsObject):
|
|||
self._menu_enable_fw = self._menu.addAction(self.MENU_ENTRY_FW_DISABLE)
|
||||
self._menu_enable_fw.setEnabled(False)
|
||||
self._menu_enable_fw.triggered.connect(self._on_enable_interception_clicked)
|
||||
|
||||
self._menu.addSeparator()
|
||||
self._menu_autostart = self._menu.addAction("Autostart")
|
||||
self._menu_autostart.setCheckable(True)
|
||||
self._menu_autostart.setChecked(self._autostart.isEnabled())
|
||||
self._menu_autostart.triggered.connect(self._on_switch_autostart)
|
||||
self._menu.addSeparator()
|
||||
|
||||
self._menu.addAction(self.MENU_ENTRY_HELP).triggered.connect(
|
||||
lambda: QtGui.QDesktopServices.openUrl(QtCore.QUrl(Config.HELP_CONFIG_URL))
|
||||
)
|
||||
self._menu.addAction(self.MENU_ENTRY_CLOSE).triggered.connect(self._on_close)
|
||||
|
||||
self._menu.aboutToShow.connect(self._on_show_menu)
|
||||
|
||||
def _on_switch_autostart(self):
|
||||
self._autostart.enable(self._menu_autostart.isChecked())
|
||||
|
||||
def _on_show_menu(self):
|
||||
self._menu_autostart.setChecked(self._autostart.isEnabled())
|
||||
|
||||
def _show_gui_if_tray_not_available(self):
|
||||
"""If the system tray is not available or ready, show the GUI after
|
||||
10s. This delay helps to skip showing up the GUI when DEs' autologin is on.
|
||||
|
|
|
@ -1,5 +1,101 @@
|
|||
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
|
||||
_user_home = os.path.expanduser('~')
|
||||
xdg_config_home = os.environ.get('XDG_CONFIG_HOME') or os.path.join(_user_home, '.config')
|
||||
# https://github.com/takluyver/pyxdg/blob/1d23e483ae869ee9532aca43b133cc43f63626a3/xdg/BaseDirectory.py
|
||||
def get_runtime_dir(strict=True):
|
||||
try:
|
||||
return os.environ['XDG_RUNTIME_DIR']
|
||||
except KeyError:
|
||||
if strict:
|
||||
raise
|
||||
|
||||
import getpass
|
||||
fallback = '/tmp/opensnitch-' + getpass.getuser()
|
||||
create = False
|
||||
|
||||
try:
|
||||
# This must be a real directory, not a symlink, so attackers can't
|
||||
# point it elsewhere. So we use lstat to check it.
|
||||
st = os.lstat(fallback)
|
||||
except OSError as e:
|
||||
import errno
|
||||
if e.errno == errno.ENOENT:
|
||||
create = True
|
||||
else:
|
||||
raise
|
||||
else:
|
||||
# The fallback must be a directory
|
||||
if not stat.S_ISDIR(st.st_mode):
|
||||
os.unlink(fallback)
|
||||
create = True
|
||||
# Must be owned by the user and not accessible by anyone else
|
||||
elif (st.st_uid != os.getuid()) \
|
||||
or (st.st_mode & (stat.S_IRWXG | stat.S_IRWXO)):
|
||||
os.rmdir(fallback)
|
||||
create = True
|
||||
|
||||
if create:
|
||||
os.mkdir(fallback, 0o700)
|
||||
|
||||
return fallback
|
||||
|
||||
|
||||
class Autostart():
|
||||
def __init__(self):
|
||||
desktopFile = 'opensnitch_ui.desktop'
|
||||
self.systemDesktop = os.path.join('/usr/share/applications', desktopFile)
|
||||
self.systemAutostart = os.path.join('/etc/xdg/autostart', desktopFile)
|
||||
if not os.path.isfile(self.systemAutostart) and os.path.isfile('/usr' + self.systemAutostart):
|
||||
self.systemAutostart = '/usr' + self.systemAutostart
|
||||
self.userAutostart = os.path.join(xdg_config_home, 'autostart', desktopFile)
|
||||
|
||||
def createUserDir(self):
|
||||
if not os.path.isdir(xdg_config_home):
|
||||
os.makedirs(xdg_config_home, 0o700)
|
||||
if not os.path.isdir(os.path.dirname(self.userAutostart)):
|
||||
os.makedirs(os.path.dirname(self.userAutostart), 0o755)
|
||||
|
||||
def isEnabled(self):
|
||||
ret = False
|
||||
if os.path.isfile(self.userAutostart):
|
||||
ret = True
|
||||
lines = open(self.userAutostart, 'r').readlines()
|
||||
for line in lines:
|
||||
if re.search("^Hidden=true", line, re.IGNORECASE):
|
||||
ret = False
|
||||
break
|
||||
elif os.path.isfile(self.systemAutostart):
|
||||
ret = True
|
||||
return ret
|
||||
|
||||
def enable(self, mode=True):
|
||||
self.createUserDir()
|
||||
if mode == True:
|
||||
if os.path.isfile(self.systemAutostart) and os.path.isfile(self.userAutostart):
|
||||
os.remove(self.userAutostart)
|
||||
elif os.path.isfile(self.systemDesktop):
|
||||
try:
|
||||
shutil.copyfile(self.systemDesktop, self.userAutostart)
|
||||
except shutil.SameFileError:
|
||||
pass
|
||||
else:
|
||||
if os.path.isfile(self.systemAutostart):
|
||||
try:
|
||||
shutil.copyfile(self.systemAutostart, self.userAutostart)
|
||||
except shutil.SameFileError:
|
||||
pass
|
||||
with open(self.userAutostart, 'a') as f:
|
||||
f.write('Hidden=true\n')
|
||||
elif os.path.isfile(self.userAutostart):
|
||||
os.remove(self.userAutostart)
|
||||
|
||||
def disable(self):
|
||||
self.enable(False)
|
||||
|
||||
|
||||
_home = os.path.expanduser('~')
|
||||
xdg_config_home = os.environ.get('XDG_CONFIG_HOME') or os.path.join(_home, '.config')
|
||||
xdg_runtime_dir = get_runtime_dir(False)
|
||||
xdg_current_desktop = os.environ.get('XDG_CURRENT_DESKTOP')
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=OpenSnitch
|
||||
Exec=/bin/sh -c "pkill -15 opensnitch-ui; opensnitch-ui"
|
||||
Exec=opensnitch-ui
|
||||
Icon=opensnitch-ui
|
||||
GenericName=OpenSnitch Firewall
|
||||
GenericName[hu]=OpenSnitch-tűzfal
|
||||
|
|
Loading…
Add table
Reference in a new issue