127
126
a sensible number of times
128
127
group: D-Bus Entry Group
129
128
server: D-Bus Server
129
bus: dbus.SystemBus()
131
131
def __init__(self, interface = avahi.IF_UNSPEC, name = None,
132
132
servicetype = None, port = None, TXT = None,
313
313
def enable(self):
314
314
"""Start this client's checker and timeout hooks"""
315
if getattr(self, u"enabled", False):
315
318
self.last_enabled = datetime.datetime.utcnow()
316
319
# Schedule a new checker to be started an 'interval' from now,
317
320
# and every interval from then on.
478
481
"""A Client class using D-Bus
481
dbus_object_path: dbus.ObjectPath ; only set if self.use_dbus
484
dbus_object_path: dbus.ObjectPath
485
bus: dbus.SystemBus()
483
487
# dbus.service.Object doesn't use super(), so we can't either.
810
ipc.write(u"NOTFOUND %s\n" % fpr)
814
ipc.write(u"NOTFOUND %s %s\n"
815
% (fpr, unicode(self.client_address)))
813
818
# Have to check if client.still_valid(), since it is
894
899
class ForkingMixInWithPipe(socketserver.ForkingMixIn, object):
895
"""Like socketserver.ForkingMixIn, but also pass a pipe.
897
Assumes a gobject.MainLoop event loop.
900
"""Like socketserver.ForkingMixIn, but also pass a pipe."""
899
901
def process_request(self, request, client_address):
900
902
"""Overrides and wraps the original process_request().
902
This function creates a new pipe in self.pipe
904
This function creates a new pipe in self.pipe
904
906
self.pipe = os.pipe()
905
907
super(ForkingMixInWithPipe,
906
908
self).process_request(request, client_address)
907
909
os.close(self.pipe[1]) # close write end
908
# Call "handle_ipc" for both data and EOF events
909
gobject.io_add_watch(self.pipe[0],
910
gobject.IO_IN | gobject.IO_HUP,
912
def handle_ipc(source, condition):
910
self.add_pipe(self.pipe[0])
911
def add_pipe(self, pipe):
913
912
"""Dummy function; override as necessary"""
918
916
class IPv6_TCPServer(ForkingMixInWithPipe,
923
921
enabled: Boolean; whether this server is activated yet
924
922
interface: None or a network interface name (string)
925
923
use_ipv6: Boolean; to use IPv6 or not
927
clients: set of Client objects
928
gnutls_priority GnuTLS priority string
929
use_dbus: Boolean; to emit D-Bus signals or not
931
925
def __init__(self, server_address, RequestHandlerClass,
932
interface=None, use_ipv6=True, clients=None,
933
gnutls_priority=None, use_dbus=True):
926
interface=None, use_ipv6=True):
935
927
self.interface = interface
937
929
self.address_family = socket.AF_INET6
938
self.clients = clients
939
self.use_dbus = use_dbus
940
self.gnutls_priority = gnutls_priority
941
930
socketserver.TCPServer.__init__(self, server_address,
942
931
RequestHandlerClass)
943
932
def server_bind(self):
945
934
to bind to an interface if one was specified, and also NOT to
946
935
bind to an address or port if they were not specified."""
947
936
if self.interface is not None:
949
self.socket.setsockopt(socket.SOL_SOCKET,
951
str(self.interface + u'\0'))
952
except socket.error, error:
953
if error[0] == errno.EPERM:
954
logger.error(u"No permission to"
955
u" bind to interface %s",
937
if SO_BINDTODEVICE is None:
938
logger.error(u"SO_BINDTODEVICE does not exist;"
939
u" cannot bind to interface %s",
943
self.socket.setsockopt(socket.SOL_SOCKET,
947
except socket.error, error:
948
if error[0] == errno.EPERM:
949
logger.error(u"No permission to"
950
u" bind to interface %s",
952
elif error[0] == errno.ENOPROTOOPT:
953
logger.error(u"SO_BINDTODEVICE not available;"
954
u" cannot bind to interface %s",
959
958
# Only bind(2) the socket if we really need to.
960
959
if self.server_address[0] or self.server_address[1]:
961
960
if not self.server_address[0]:
976
975
# (self.interface))
977
976
return socketserver.TCPServer.server_bind(self)
979
class MandosServer(IPv6_TCPServer):
983
clients: set of Client objects
984
gnutls_priority GnuTLS priority string
985
use_dbus: Boolean; to emit D-Bus signals or not
986
clients: set of Client objects
987
gnutls_priority GnuTLS priority string
988
use_dbus: Boolean; to emit D-Bus signals or not
990
Assumes a gobject.MainLoop event loop.
992
def __init__(self, server_address, RequestHandlerClass,
993
interface=None, use_ipv6=True, clients=None,
994
gnutls_priority=None, use_dbus=True):
996
self.clients = clients
997
if self.clients is None:
999
self.use_dbus = use_dbus
1000
self.gnutls_priority = gnutls_priority
1001
IPv6_TCPServer.__init__(self, server_address,
1002
RequestHandlerClass,
1003
interface = interface,
1004
use_ipv6 = use_ipv6)
978
1005
def server_activate(self):
979
1006
if self.enabled:
980
1007
return socketserver.TCPServer.server_activate(self)
981
1008
def enable(self):
982
1009
self.enabled = True
1010
def add_pipe(self, pipe):
1011
# Call "handle_ipc" for both data and EOF events
1012
gobject.io_add_watch(pipe, gobject.IO_IN | gobject.IO_HUP,
983
1014
def handle_ipc(self, source, condition, file_objects={}):
984
1015
condition_names = {
985
1016
gobject.IO_IN: u"IN", # There is data to read.
1249
1280
global mandos_dbus_service
1250
1281
mandos_dbus_service = None
1253
tcp_server = IPv6_TCPServer((server_settings[u"address"],
1254
server_settings[u"port"]),
1257
server_settings[u"interface"],
1261
server_settings[u"priority"],
1283
tcp_server = MandosServer((server_settings[u"address"],
1284
server_settings[u"port"]),
1286
interface=server_settings[u"interface"],
1289
server_settings[u"priority"],
1263
1291
pidfilename = u"/var/run/mandos.pid"
1265
1293
pidfile = open(pidfilename, u"w")
1319
1347
client_class = Client
1321
1349
client_class = functools.partial(ClientDBus, bus = bus)
1350
tcp_server.clients.update(set(
1323
1351
client_class(name = section,
1324
1352
config= dict(client_config.items(section)))
1325
1353
for section in client_config.sections()))
1354
if not tcp_server.clients:
1327
1355
logger.warning(u"No clients defined")
1392
1420
@dbus.service.method(_interface, out_signature=u"ao")
1393
1421
def GetAllClients(self):
1395
return dbus.Array(c.dbus_object_path for c in clients)
1423
return dbus.Array(c.dbus_object_path
1424
for c in tcp_server.clients)
1397
1426
@dbus.service.method(_interface,
1398
1427
out_signature=u"a{oa{sv}}")
1401
1430
return dbus.Dictionary(
1402
1431
((c.dbus_object_path, c.GetAllProperties())
1432
for c in tcp_server.clients),
1404
1433
signature=u"oa{sv}")
1406
1435
@dbus.service.method(_interface, in_signature=u"o")
1407
1436
def RemoveClient(self, object_path):
1438
for c in tcp_server.clients:
1410
1439
if c.dbus_object_path == object_path:
1440
tcp_server.clients.remove(c)
1412
1441
c.remove_from_connection()
1413
1442
# Don't signal anything except ClientRemoved
1414
1443
c.disable(signal=False)