1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
|
#!/usr/bin/python3
# This file is part of Epoptes, https://epoptes.org
# Copyright 2010-2023 the Epoptes team, see AUTHORS.
# SPDX-License-Identifier: GPL-3.0-or-later
"""
Communicate with epoptes-clients on SSL 789
and with GUIs on /run/epoptes/epoptes.socket.
Communication flow:
epoptesd.py imports bashplex.py <=SSL=> epoptes-client.
epoptesd.py imports guiplex.py <=UNIX=> uiconnection imported by gui.py.
So, epoptesd, guiplex, bashplex and exchange run as root.
"""
import grp
import os
from OpenSSL import SSL
from zope.interface import implementer
from twisted.application import internet, service
from twisted.application.service import IServiceMaker
from twisted.internet import ssl
from twisted.python import usage
from twisted.plugin import IPlugin
from epoptes.common import config
from epoptes.daemon import bashplex, guiplex
class Options(usage.Options):
"""Define the epoptes service command line parameters."""
optParameters = [
("client-port", "p", 789, "Client Port"),
('ping-interval', 'i', 10),
('ping-timeout', 't', 10)
]
class ServerContextFactory(ssl.ContextFactory):
"""Provide the SSL context."""
def getContext(self):
ctx = SSL.Context(SSL.SSLv23_METHOD)
ctx.use_certificate_file("/etc/epoptes/server.crt")
ctx.use_privatekey_file("/etc/epoptes/server.key")
return ctx
def filter_bash(script):
"""Strip comments from client-functions, to save some bandwidth."""
with open(script) as file:
functions = file.readlines()
result = ''
for line in functions:
if line.strip() != '' and line.strip()[0] == '#':
continue
result += line
return result
@implementer(IServiceMaker, IPlugin)
class ServiceMaker(object):
"""Communicate with epoptes-clients on SSL 789
and with GUIs on /run/epoptes/epoptes.socket.
"""
tapname = "epoptes"
description = "Epoptes Daemon"
options = Options
def makeService(self, options):
"""Override IServiceMaker.makeService."""
factory = bashplex.DelimitedBashReceiverFactory()
factory.ping_interval = int(options['ping-interval'])
factory.ping_timeout = int(options['ping-timeout'])
factory.startup_commands = filter_bash(
'/usr/share/epoptes/client-functions')
if config.system['ENCRYPTION']:
client_service = internet.SSLServer(
int(config.system['PORT']), factory, ServerContextFactory())
else:
client_service = internet.TCPServer(
int(config.system['PORT']), factory)
gid = grp.getgrnam(config.system['SOCKET_GROUP'])[2]
if not os.path.isdir(config.system['DIR']):
# `man 2 mkdir` cannot set the sticky bit, a chmod is needed
os.makedirs(config.system['DIR'], 0o2770)
os.chmod(config.system['DIR'], 0o2770)
os.chown(config.system['DIR'], -1, gid)
gui_service = internet.UNIXServer(
"%s/epoptes.socket" % config.system['DIR'],
guiplex.GUIFactory())
top_service = service.MultiService()
top_service.addService(client_service)
top_service.addService(gui_service)
return top_service
serviceMaker = ServiceMaker()
|