/mandos/trunk

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/trunk

« back to all changes in this revision

Viewing changes to mandos

  • Committer: Teddy Hogeborn
  • Date: 2009-04-16 19:16:49 UTC
  • Revision ID: teddy@fukt.bsnet.se-20090416191649-stvuj37ts165w5j2
Code cleanup.  Move some global stuff into main.

* mandos (service, bus): No longer global variables.
  (AvahiService.__init__, ClientDBus.__init__): Take new "bus"
                                                argument.  All callers
                                                changed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
74
74
    try:
75
75
        from IN import SO_BINDTODEVICE
76
76
    except ImportError:
77
 
        SO_BINDTODEVICE = None
 
77
        # From /usr/include/asm/socket.h
 
78
        SO_BINDTODEVICE = 25
78
79
 
79
80
 
80
81
version = "1.0.8"
126
127
                  a sensible number of times
127
128
    group: D-Bus Entry Group
128
129
    server: D-Bus Server
129
 
    bus: dbus.SystemBus()
130
130
    """
131
131
    def __init__(self, interface = avahi.IF_UNSPEC, name = None,
132
132
                 servicetype = None, port = None, TXT = None,
312
312
    
313
313
    def enable(self):
314
314
        """Start this client's checker and timeout hooks"""
315
 
        if getattr(self, u"enabled", False):
316
 
            # Already enabled
317
 
            return
318
315
        self.last_enabled = datetime.datetime.utcnow()
319
316
        # Schedule a new checker to be started an 'interval' from now,
320
317
        # and every interval from then on.
481
478
    """A Client class using D-Bus
482
479
    
483
480
    Attributes:
484
 
    dbus_object_path: dbus.ObjectPath
485
 
    bus: dbus.SystemBus()
 
481
    dbus_object_path: dbus.ObjectPath ; only set if self.use_dbus
486
482
    """
487
483
    # dbus.service.Object doesn't use super(), so we can't either.
488
484
    
896
892
 
897
893
 
898
894
class ForkingMixInWithPipe(socketserver.ForkingMixIn, object):
899
 
    """Like socketserver.ForkingMixIn, but also pass a pipe."""
 
895
    """Like socketserver.ForkingMixIn, but also pass a pipe.
 
896
    
 
897
    Assumes a gobject.MainLoop event loop.
 
898
    """
900
899
    def process_request(self, request, client_address):
901
900
        """Overrides and wraps the original process_request().
902
901
        
906
905
        super(ForkingMixInWithPipe,
907
906
              self).process_request(request, client_address)
908
907
        os.close(self.pipe[1])  # close write end
909
 
        self.add_pipe(self.pipe[0])
910
 
    def add_pipe(self, pipe):
 
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,
 
911
                             self.handle_ipc)
 
912
    def handle_ipc(source, condition):
911
913
        """Dummy function; override as necessary"""
912
 
        os.close(pipe)
 
914
        os.close(source)
 
915
        return False
913
916
 
914
917
 
915
918
class IPv6_TCPServer(ForkingMixInWithPipe,
920
923
        enabled:        Boolean; whether this server is activated yet
921
924
        interface:      None or a network interface name (string)
922
925
        use_ipv6:       Boolean; to use IPv6 or not
 
926
        ----
 
927
        clients:        set of Client objects
 
928
        gnutls_priority GnuTLS priority string
 
929
        use_dbus:       Boolean; to emit D-Bus signals or not
923
930
    """
924
931
    def __init__(self, server_address, RequestHandlerClass,
925
 
                 interface=None, use_ipv6=True):
 
932
                 interface=None, use_ipv6=True, clients=None,
 
933
                 gnutls_priority=None, use_dbus=True):
 
934
        self.enabled = False
926
935
        self.interface = interface
927
936
        if use_ipv6:
928
937
            self.address_family = socket.AF_INET6
 
938
        self.clients = clients
 
939
        self.use_dbus = use_dbus
 
940
        self.gnutls_priority = gnutls_priority
929
941
        socketserver.TCPServer.__init__(self, server_address,
930
942
                                        RequestHandlerClass)
931
943
    def server_bind(self):
933
945
        to bind to an interface if one was specified, and also NOT to
934
946
        bind to an address or port if they were not specified."""
935
947
        if self.interface is not None:
936
 
            if SO_BINDTODEVICE is None:
937
 
                logger.error(u"SO_BINDTODEVICE does not exist;"
938
 
                             u" cannot bind to interface %s",
939
 
                             self.interface)
940
 
            else:
941
 
                try:
942
 
                    self.socket.setsockopt(socket.SOL_SOCKET,
943
 
                                           SO_BINDTODEVICE,
944
 
                                           str(self.interface
945
 
                                               + u'\0'))
946
 
                except socket.error, error:
947
 
                    if error[0] == errno.EPERM:
948
 
                        logger.error(u"No permission to"
949
 
                                     u" bind to interface %s",
950
 
                                     self.interface)
951
 
                    elif error[0] == errno.ENOPROTOOPT:
952
 
                        logger.error(u"SO_BINDTODEVICE not available;"
953
 
                                     u" cannot bind to interface %s",
954
 
                                     self.interface)
955
 
                    else:
956
 
                        raise
 
948
            try:
 
949
                self.socket.setsockopt(socket.SOL_SOCKET,
 
950
                                       SO_BINDTODEVICE,
 
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",
 
956
                                 self.interface)
 
957
                else:
 
958
                    raise
957
959
        # Only bind(2) the socket if we really need to.
958
960
        if self.server_address[0] or self.server_address[1]:
959
961
            if not self.server_address[0]:
973
975
#                                            if_nametoindex
974
976
#                                            (self.interface))
975
977
            return socketserver.TCPServer.server_bind(self)
976
 
 
977
 
 
978
 
class MandosServer(IPv6_TCPServer):
979
 
    """Mandos server.
980
 
    
981
 
    Attributes:
982
 
        clients:        set of Client objects
983
 
        gnutls_priority GnuTLS priority string
984
 
        use_dbus:       Boolean; to emit D-Bus signals or not
985
 
        clients:        set of Client objects
986
 
        gnutls_priority GnuTLS priority string
987
 
        use_dbus:       Boolean; to emit D-Bus signals or not
988
 
    
989
 
    Assumes a gobject.MainLoop event loop.
990
 
    """
991
 
    def __init__(self, server_address, RequestHandlerClass,
992
 
                 interface=None, use_ipv6=True, clients=None,
993
 
                 gnutls_priority=None, use_dbus=True):
994
 
        self.enabled = False
995
 
        self.clients = clients
996
 
        if self.clients is None:
997
 
            self.clients = set()
998
 
        self.use_dbus = use_dbus
999
 
        self.gnutls_priority = gnutls_priority
1000
 
        IPv6_TCPServer.__init__(self, server_address,
1001
 
                                RequestHandlerClass,
1002
 
                                interface = interface,
1003
 
                                use_ipv6 = use_ipv6)
1004
978
    def server_activate(self):
1005
979
        if self.enabled:
1006
980
            return socketserver.TCPServer.server_activate(self)
1007
981
    def enable(self):
1008
982
        self.enabled = True
1009
 
    def add_pipe(self, pipe):
1010
 
        # Call "handle_ipc" for both data and EOF events
1011
 
        gobject.io_add_watch(pipe, gobject.IO_IN | gobject.IO_HUP,
1012
 
                             self.handle_ipc)
1013
983
    def handle_ipc(self, source, condition, file_objects={}):
1014
984
        condition_names = {
1015
985
            gobject.IO_IN: u"IN",   # There is data to read.
1279
1249
    global mandos_dbus_service
1280
1250
    mandos_dbus_service = None
1281
1251
    
1282
 
    tcp_server = MandosServer((server_settings[u"address"],
1283
 
                               server_settings[u"port"]),
1284
 
                              ClientHandler,
1285
 
                              interface=server_settings[u"interface"],
1286
 
                              use_ipv6=use_ipv6,
1287
 
                              gnutls_priority=
1288
 
                              server_settings[u"priority"],
1289
 
                              use_dbus=use_dbus)
 
1252
    clients = set()
 
1253
    tcp_server = IPv6_TCPServer((server_settings[u"address"],
 
1254
                                 server_settings[u"port"]),
 
1255
                                ClientHandler,
 
1256
                                interface=
 
1257
                                server_settings[u"interface"],
 
1258
                                use_ipv6=use_ipv6,
 
1259
                                clients=clients,
 
1260
                                gnutls_priority=
 
1261
                                server_settings[u"priority"],
 
1262
                                use_dbus=use_dbus)
1290
1263
    pidfilename = u"/var/run/mandos.pid"
1291
1264
    try:
1292
1265
        pidfile = open(pidfilename, u"w")
1346
1319
    client_class = Client
1347
1320
    if use_dbus:
1348
1321
        client_class = functools.partial(ClientDBus, bus = bus)
1349
 
    tcp_server.clients.update(set(
 
1322
    clients.update(set(
1350
1323
            client_class(name = section,
1351
1324
                         config= dict(client_config.items(section)))
1352
1325
            for section in client_config.sections()))
1353
 
    if not tcp_server.clients:
 
1326
    if not clients:
1354
1327
        logger.warning(u"No clients defined")
1355
1328
    
1356
1329
    if debug:
1382
1355
        "Cleanup function; run on exit"
1383
1356
        service.cleanup()
1384
1357
        
1385
 
        while tcp_server.clients:
1386
 
            client = tcp_server.clients.pop()
 
1358
        while clients:
 
1359
            client = clients.pop()
1387
1360
            client.disable_hook = None
1388
1361
            client.disable()
1389
1362
    
1419
1392
            @dbus.service.method(_interface, out_signature=u"ao")
1420
1393
            def GetAllClients(self):
1421
1394
                "D-Bus method"
1422
 
                return dbus.Array(c.dbus_object_path
1423
 
                                  for c in tcp_server.clients)
 
1395
                return dbus.Array(c.dbus_object_path for c in clients)
1424
1396
            
1425
1397
            @dbus.service.method(_interface,
1426
1398
                                 out_signature=u"a{oa{sv}}")
1428
1400
                "D-Bus method"
1429
1401
                return dbus.Dictionary(
1430
1402
                    ((c.dbus_object_path, c.GetAllProperties())
1431
 
                     for c in tcp_server.clients),
 
1403
                     for c in clients),
1432
1404
                    signature=u"oa{sv}")
1433
1405
            
1434
1406
            @dbus.service.method(_interface, in_signature=u"o")
1435
1407
            def RemoveClient(self, object_path):
1436
1408
                "D-Bus method"
1437
 
                for c in tcp_server.clients:
 
1409
                for c in clients:
1438
1410
                    if c.dbus_object_path == object_path:
1439
 
                        tcp_server.clients.remove(c)
 
1411
                        clients.remove(c)
1440
1412
                        c.remove_from_connection()
1441
1413
                        # Don't signal anything except ClientRemoved
1442
1414
                        c.disable(signal=False)
1449
1421
        
1450
1422
        mandos_dbus_service = MandosDBusService()
1451
1423
    
1452
 
    for client in tcp_server.clients:
 
1424
    for client in clients:
1453
1425
        if use_dbus:
1454
1426
            # Emit D-Bus signal
1455
1427
            mandos_dbus_service.ClientAdded(client.dbus_object_path,