/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: 2011-09-26 21:12:40 UTC
  • mfrom: (502.1.1 teddy)
  • Revision ID: teddy@fukt.bsnet.se-20110926211240-qahsqx7nvx5ktjyn
Merge inconsequential change

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
# along with this program.  If not, see
29
29
# <http://www.gnu.org/licenses/>.
30
30
31
 
# Contact the authors at <mandos@recompile.se>.
 
31
# Contact the authors at <mandos@fukt.bsnet.se>.
32
32
33
33
 
34
34
from __future__ import (division, absolute_import, print_function,
62
62
import functools
63
63
import cPickle as pickle
64
64
import multiprocessing
65
 
import types
66
65
 
67
66
import dbus
68
67
import dbus.service
83
82
        SO_BINDTODEVICE = None
84
83
 
85
84
 
86
 
version = "1.4.0"
 
85
version = "1.3.1"
87
86
 
88
87
#logger = logging.getLogger('mandos')
89
88
logger = logging.Logger('mandos')
160
159
                            " after %i retries, exiting.",
161
160
                            self.rename_count)
162
161
            raise AvahiServiceError("Too many renames")
163
 
        self.name = unicode(self.server
164
 
                            .GetAlternativeServiceName(self.name))
 
162
        self.name = unicode(self.server.GetAlternativeServiceName(self.name))
165
163
        logger.info("Changing Zeroconf service name to %r ...",
166
164
                    self.name)
167
165
        syslogger.setFormatter(logging.Formatter
322
320
    
323
321
    def extended_timeout_milliseconds(self):
324
322
        "Return the 'extended_timeout' attribute in milliseconds"
325
 
        return _timedelta_to_milliseconds(self.extended_timeout)
 
323
        return _timedelta_to_milliseconds(self.extended_timeout)    
326
324
    
327
325
    def interval_milliseconds(self):
328
326
        "Return the 'interval' attribute in milliseconds"
362
360
        self.last_enabled = None
363
361
        self.last_checked_ok = None
364
362
        self.timeout = string_to_delta(config["timeout"])
365
 
        self.extended_timeout = string_to_delta(config
366
 
                                                ["extended_timeout"])
 
363
        self.extended_timeout = string_to_delta(config["extended_timeout"])
367
364
        self.interval = string_to_delta(config["interval"])
368
365
        self.disable_hook = disable_hook
369
366
        self.checker = None
382
379
            config["approval_delay"])
383
380
        self.approval_duration = string_to_delta(
384
381
            config["approval_duration"])
385
 
        self.changedstate = (multiprocessing_manager
386
 
                             .Condition(multiprocessing_manager
387
 
                                        .Lock()))
 
382
        self.changedstate = multiprocessing_manager.Condition(multiprocessing_manager.Lock())
388
383
    
389
384
    def send_changedstate(self):
390
385
        self.changedstate.acquire()
391
386
        self.changedstate.notify_all()
392
387
        self.changedstate.release()
393
 
    
 
388
        
394
389
    def enable(self):
395
390
        """Start this client's checker and timeout hooks"""
396
391
        if getattr(self, "enabled", False):
465
460
            timeout = self.timeout
466
461
        self.last_checked_ok = datetime.datetime.utcnow()
467
462
        gobject.source_remove(self.disable_initiator_tag)
468
 
        self.disable_initiator_tag = (gobject.timeout_add
469
 
                                      (_timedelta_to_milliseconds
470
 
                                       (timeout), self.disable))
471
463
        self.expires = datetime.datetime.utcnow() + timeout
 
464
        self.disable_initiator_tag = (gobject.timeout_add
 
465
                                      (_timedelta_to_milliseconds(timeout),
 
466
                                       self.disable))
472
467
    
473
468
    def need_approval(self):
474
469
        self.last_approval_request = datetime.datetime.utcnow()
631
626
    def _get_all_dbus_properties(self):
632
627
        """Returns a generator of (name, attribute) pairs
633
628
        """
634
 
        return ((prop.__get__(self)._dbus_name, prop.__get__(self))
635
 
                for cls in self.__class__.__mro__
 
629
        return ((prop._dbus_name, prop)
636
630
                for name, prop in
637
 
                inspect.getmembers(cls, self._is_dbus_property))
 
631
                inspect.getmembers(self, self._is_dbus_property))
638
632
    
639
633
    def _get_dbus_property(self, interface_name, property_name):
640
634
        """Returns a bound method if one exists which is a D-Bus
641
635
        property with the specified name and interface.
642
636
        """
643
 
        for cls in  self.__class__.__mro__:
644
 
            for name, value in (inspect.getmembers
645
 
                                (cls, self._is_dbus_property)):
646
 
                if (value._dbus_name == property_name
647
 
                    and value._dbus_interface == interface_name):
648
 
                    return value.__get__(self)
649
 
        
 
637
        for name in (property_name,
 
638
                     property_name + "_dbus_property"):
 
639
            prop = getattr(self, name, None)
 
640
            if (prop is None
 
641
                or not self._is_dbus_property(prop)
 
642
                or prop._dbus_name != property_name
 
643
                or (interface_name and prop._dbus_interface
 
644
                    and interface_name != prop._dbus_interface)):
 
645
                continue
 
646
            return prop
650
647
        # No such property
651
648
        raise DBusPropertyNotFound(self.dbus_object_path + ":"
652
649
                                   + interface_name + "."
761
758
    return dbus.String(dt.isoformat(),
762
759
                       variant_level=variant_level)
763
760
 
764
 
class AlternateDBusNamesMetaclass(DBusObjectWithProperties
765
 
                                  .__metaclass__):
766
 
    """Applied to an empty subclass of a D-Bus object, this metaclass
767
 
    will add additional D-Bus attributes matching a certain pattern.
768
 
    """
769
 
    def __new__(mcs, name, bases, attr):
770
 
        # Go through all the base classes which could have D-Bus
771
 
        # methods, signals, or properties in them
772
 
        for base in (b for b in bases
773
 
                     if issubclass(b, dbus.service.Object)):
774
 
            # Go though all attributes of the base class
775
 
            for attrname, attribute in inspect.getmembers(base):
776
 
                # Ignore non-D-Bus attributes, and D-Bus attributes
777
 
                # with the wrong interface name
778
 
                if (not hasattr(attribute, "_dbus_interface")
779
 
                    or not attribute._dbus_interface
780
 
                    .startswith("se.recompile.Mandos")):
781
 
                    continue
782
 
                # Create an alternate D-Bus interface name based on
783
 
                # the current name
784
 
                alt_interface = (attribute._dbus_interface
785
 
                                 .replace("se.recompile.Mandos",
786
 
                                          "se.bsnet.fukt.Mandos"))
787
 
                # Is this a D-Bus signal?
788
 
                if getattr(attribute, "_dbus_is_signal", False):
789
 
                    # Extract the original non-method function by
790
 
                    # black magic
791
 
                    nonmethod_func = (dict(
792
 
                            zip(attribute.func_code.co_freevars,
793
 
                                attribute.__closure__))["func"]
794
 
                                      .cell_contents)
795
 
                    # Create a new, but exactly alike, function
796
 
                    # object, and decorate it to be a new D-Bus signal
797
 
                    # with the alternate D-Bus interface name
798
 
                    new_function = (dbus.service.signal
799
 
                                    (alt_interface,
800
 
                                     attribute._dbus_signature)
801
 
                                    (types.FunctionType(
802
 
                                nonmethod_func.func_code,
803
 
                                nonmethod_func.func_globals,
804
 
                                nonmethod_func.func_name,
805
 
                                nonmethod_func.func_defaults,
806
 
                                nonmethod_func.func_closure)))
807
 
                    # Define a creator of a function to call both the
808
 
                    # old and new functions, so both the old and new
809
 
                    # signals gets sent when the function is called
810
 
                    def fixscope(func1, func2):
811
 
                        """This function is a scope container to pass
812
 
                        func1 and func2 to the "call_both" function
813
 
                        outside of its arguments"""
814
 
                        def call_both(*args, **kwargs):
815
 
                            """This function will emit two D-Bus
816
 
                            signals by calling func1 and func2"""
817
 
                            func1(*args, **kwargs)
818
 
                            func2(*args, **kwargs)
819
 
                        return call_both
820
 
                    # Create the "call_both" function and add it to
821
 
                    # the class
822
 
                    attr[attrname] = fixscope(attribute,
823
 
                                              new_function)
824
 
                # Is this a D-Bus method?
825
 
                elif getattr(attribute, "_dbus_is_method", False):
826
 
                    # Create a new, but exactly alike, function
827
 
                    # object.  Decorate it to be a new D-Bus method
828
 
                    # with the alternate D-Bus interface name.  Add it
829
 
                    # to the class.
830
 
                    attr[attrname] = (dbus.service.method
831
 
                                      (alt_interface,
832
 
                                       attribute._dbus_in_signature,
833
 
                                       attribute._dbus_out_signature)
834
 
                                      (types.FunctionType
835
 
                                       (attribute.func_code,
836
 
                                        attribute.func_globals,
837
 
                                        attribute.func_name,
838
 
                                        attribute.func_defaults,
839
 
                                        attribute.func_closure)))
840
 
                # Is this a D-Bus property?
841
 
                elif getattr(attribute, "_dbus_is_property", False):
842
 
                    # Create a new, but exactly alike, function
843
 
                    # object, and decorate it to be a new D-Bus
844
 
                    # property with the alternate D-Bus interface
845
 
                    # name.  Add it to the class.
846
 
                    attr[attrname] = (dbus_service_property
847
 
                                      (alt_interface,
848
 
                                       attribute._dbus_signature,
849
 
                                       attribute._dbus_access,
850
 
                                       attribute
851
 
                                       ._dbus_get_args_options
852
 
                                       ["byte_arrays"])
853
 
                                      (types.FunctionType
854
 
                                       (attribute.func_code,
855
 
                                        attribute.func_globals,
856
 
                                        attribute.func_name,
857
 
                                        attribute.func_defaults,
858
 
                                        attribute.func_closure)))
859
 
        return type.__new__(mcs, name, bases, attr)
860
761
 
861
762
class ClientDBus(Client, DBusObjectWithProperties):
862
763
    """A Client class using D-Bus
888
789
    def notifychangeproperty(transform_func,
889
790
                             dbus_name, type_func=lambda x: x,
890
791
                             variant_level=1):
891
 
        """ Modify a variable so that it's a property which announces
892
 
        its changes to DBus.
893
 
 
894
 
        transform_fun: Function that takes a value and a variant_level
895
 
                       and transforms it to a D-Bus type.
896
 
        dbus_name: D-Bus name of the variable
 
792
        """ Modify a variable so that its a property that announce its
 
793
        changes to DBus.
 
794
        transform_fun: Function that takes a value and transform it to
 
795
                       DBus type.
 
796
        dbus_name: DBus name of the variable
897
797
        type_func: Function that transform the value before sending it
898
 
                   to the D-Bus.  Default: no transform
899
 
        variant_level: D-Bus variant level.  Default: 1
 
798
                   to DBus
 
799
        variant_level: DBus variant level. default: 1
900
800
        """
901
 
        attrname = "_{0}".format(dbus_name)
 
801
        real_value = [None,]
902
802
        def setter(self, value):
 
803
            old_value = real_value[0]
 
804
            real_value[0] = value
903
805
            if hasattr(self, "dbus_object_path"):
904
 
                if (not hasattr(self, attrname) or
905
 
                    type_func(getattr(self, attrname, None))
906
 
                    != type_func(value)):
907
 
                    dbus_value = transform_func(type_func(value),
908
 
                                                variant_level
909
 
                                                =variant_level)
 
806
                if type_func(old_value) != type_func(real_value[0]):
 
807
                    dbus_value = transform_func(type_func(real_value[0]),
 
808
                                                variant_level)
910
809
                    self.PropertyChanged(dbus.String(dbus_name),
911
810
                                         dbus_value)
912
 
            setattr(self, attrname, value)
913
811
        
914
 
        return property(lambda self: getattr(self, attrname), setter)
 
812
        return property(lambda self: real_value[0], setter)
915
813
    
916
814
    
917
815
    expires = notifychangeproperty(datetime_to_dbus, "Expires")
922
820
    last_enabled = notifychangeproperty(datetime_to_dbus,
923
821
                                        "LastEnabled")
924
822
    checker = notifychangeproperty(dbus.Boolean, "CheckerRunning",
925
 
                                   type_func = lambda checker:
926
 
                                       checker is not None)
 
823
                                   type_func = lambda checker: checker is not None)
927
824
    last_checked_ok = notifychangeproperty(datetime_to_dbus,
928
825
                                           "LastCheckedOK")
929
 
    last_approval_request = notifychangeproperty(
930
 
        datetime_to_dbus, "LastApprovalRequest")
 
826
    last_approval_request = notifychangeproperty(datetime_to_dbus,
 
827
                                                 "LastApprovalRequest")
931
828
    approved_by_default = notifychangeproperty(dbus.Boolean,
932
829
                                               "ApprovedByDefault")
933
 
    approval_delay = notifychangeproperty(dbus.UInt16,
934
 
                                          "ApprovalDelay",
935
 
                                          type_func =
936
 
                                          _timedelta_to_milliseconds)
937
 
    approval_duration = notifychangeproperty(
938
 
        dbus.UInt16, "ApprovalDuration",
939
 
        type_func = _timedelta_to_milliseconds)
 
830
    approval_delay = notifychangeproperty(dbus.UInt16, "ApprovalDelay",
 
831
                                          type_func = _timedelta_to_milliseconds)
 
832
    approval_duration = notifychangeproperty(dbus.UInt16, "ApprovalDuration",
 
833
                                             type_func = _timedelta_to_milliseconds)
940
834
    host = notifychangeproperty(dbus.String, "Host")
941
835
    timeout = notifychangeproperty(dbus.UInt16, "Timeout",
942
 
                                   type_func =
943
 
                                   _timedelta_to_milliseconds)
944
 
    extended_timeout = notifychangeproperty(
945
 
        dbus.UInt16, "ExtendedTimeout",
946
 
        type_func = _timedelta_to_milliseconds)
947
 
    interval = notifychangeproperty(dbus.UInt16,
948
 
                                    "Interval",
949
 
                                    type_func =
950
 
                                    _timedelta_to_milliseconds)
 
836
                                   type_func = _timedelta_to_milliseconds)
 
837
    extended_timeout = notifychangeproperty(dbus.UInt16, "ExtendedTimeout",
 
838
                                            type_func = _timedelta_to_milliseconds)
 
839
    interval = notifychangeproperty(dbus.UInt16, "Interval",
 
840
                                    type_func = _timedelta_to_milliseconds)
951
841
    checker_command = notifychangeproperty(dbus.String, "Checker")
952
842
    
953
843
    del notifychangeproperty
1007
897
    
1008
898
    
1009
899
    ## D-Bus methods, signals & properties
1010
 
    _interface = "se.recompile.Mandos.Client"
 
900
    _interface = "se.bsnet.fukt.Mandos.Client"
1011
901
    
1012
902
    ## Signals
1013
903
    
1188
1078
        gobject.source_remove(self.disable_initiator_tag)
1189
1079
        self.disable_initiator_tag = None
1190
1080
        self.expires = None
1191
 
        time_to_die = _timedelta_to_milliseconds((self
1192
 
                                                  .last_checked_ok
1193
 
                                                  + self.timeout)
1194
 
                                                 - datetime.datetime
1195
 
                                                 .utcnow())
 
1081
        time_to_die = (self.
 
1082
                       _timedelta_to_milliseconds((self
 
1083
                                                   .last_checked_ok
 
1084
                                                   + self.timeout)
 
1085
                                                  - datetime.datetime
 
1086
                                                  .utcnow()))
1196
1087
        if time_to_die <= 0:
1197
1088
            # The timeout has passed
1198
1089
            self.disable()
1199
1090
        else:
1200
1091
            self.expires = (datetime.datetime.utcnow()
1201
 
                            + datetime.timedelta(milliseconds =
1202
 
                                                 time_to_die))
 
1092
                            + datetime.timedelta(milliseconds = time_to_die))
1203
1093
            self.disable_initiator_tag = (gobject.timeout_add
1204
1094
                                          (time_to_die, self.disable))
1205
1095
    
1284
1174
            return super(ProxyClient, self).__setattr__(name, value)
1285
1175
        self._pipe.send(('setattr', name, value))
1286
1176
 
1287
 
class ClientDBusTransitional(ClientDBus):
1288
 
    __metaclass__ = AlternateDBusNamesMetaclass
1289
1177
 
1290
1178
class ClientHandler(socketserver.BaseRequestHandler, object):
1291
1179
    """A class to handle client connections.
1371
1259
                                       client.name)
1372
1260
                        if self.server.use_dbus:
1373
1261
                            # Emit D-Bus signal
1374
 
                            client.Rejected("Disabled")
 
1262
                            client.Rejected("Disabled")                    
1375
1263
                        return
1376
1264
                    
1377
1265
                    if client._approved or not client.approval_delay:
1394
1282
                        return
1395
1283
                    
1396
1284
                    #wait until timeout or approved
 
1285
                    #x = float(client._timedelta_to_milliseconds(delay))
1397
1286
                    time = datetime.datetime.now()
1398
1287
                    client.changedstate.acquire()
1399
 
                    (client.changedstate.wait
1400
 
                     (float(client._timedelta_to_milliseconds(delay)
1401
 
                            / 1000)))
 
1288
                    client.changedstate.wait(float(client._timedelta_to_milliseconds(delay) / 1000))
1402
1289
                    client.changedstate.release()
1403
1290
                    time2 = datetime.datetime.now()
1404
1291
                    if (time2 - time) >= delay:
1428
1315
                    sent_size += sent
1429
1316
                
1430
1317
                logger.info("Sending secret to %s", client.name)
1431
 
                # bump the timeout using extended_timeout
 
1318
                # bump the timeout as if seen
1432
1319
                client.checked_ok(client.extended_timeout)
1433
1320
                if self.server.use_dbus:
1434
1321
                    # Emit D-Bus signal
1514
1401
        except:
1515
1402
            self.handle_error(request, address)
1516
1403
        self.close_request(request)
1517
 
    
 
1404
            
1518
1405
    def process_request(self, request, address):
1519
1406
        """Start a new process to process the request."""
1520
 
        proc = multiprocessing.Process(target = self.sub_process_main,
1521
 
                                       args = (request,
1522
 
                                               address))
1523
 
        proc.start()
1524
 
        return proc
 
1407
        multiprocessing.Process(target = self.sub_process_main,
 
1408
                                args = (request, address)).start()
1525
1409
 
1526
1410
 
1527
1411
class MultiprocessingMixInWithPipe(MultiprocessingMixIn, object):
1533
1417
        """
1534
1418
        parent_pipe, self.child_pipe = multiprocessing.Pipe()
1535
1419
        
1536
 
        proc = MultiprocessingMixIn.process_request(self, request,
1537
 
                                                    client_address)
 
1420
        super(MultiprocessingMixInWithPipe,
 
1421
              self).process_request(request, client_address)
1538
1422
        self.child_pipe.close()
1539
 
        self.add_pipe(parent_pipe, proc)
 
1423
        self.add_pipe(parent_pipe)
1540
1424
    
1541
 
    def add_pipe(self, parent_pipe, proc):
 
1425
    def add_pipe(self, parent_pipe):
1542
1426
        """Dummy function; override as necessary"""
1543
1427
        raise NotImplementedError
1544
1428
 
1632
1516
    def server_activate(self):
1633
1517
        if self.enabled:
1634
1518
            return socketserver.TCPServer.server_activate(self)
1635
 
    
1636
1519
    def enable(self):
1637
1520
        self.enabled = True
1638
 
    
1639
 
    def add_pipe(self, parent_pipe, proc):
 
1521
    def add_pipe(self, parent_pipe):
1640
1522
        # Call "handle_ipc" for both data and EOF events
1641
1523
        gobject.io_add_watch(parent_pipe.fileno(),
1642
1524
                             gobject.IO_IN | gobject.IO_HUP,
1643
1525
                             functools.partial(self.handle_ipc,
1644
 
                                               parent_pipe =
1645
 
                                               parent_pipe,
1646
 
                                               proc = proc))
1647
 
    
 
1526
                                               parent_pipe = parent_pipe))
 
1527
        
1648
1528
    def handle_ipc(self, source, condition, parent_pipe=None,
1649
 
                   proc = None, client_object=None):
 
1529
                   client_object=None):
1650
1530
        condition_names = {
1651
1531
            gobject.IO_IN: "IN",   # There is data to read.
1652
1532
            gobject.IO_OUT: "OUT", # Data can be written (without
1661
1541
                                       for cond, name in
1662
1542
                                       condition_names.iteritems()
1663
1543
                                       if cond & condition)
1664
 
        # error, or the other end of multiprocessing.Pipe has closed
 
1544
        # error or the other end of multiprocessing.Pipe has closed
1665
1545
        if condition & (gobject.IO_ERR | condition & gobject.IO_HUP):
1666
 
            # Wait for other process to exit
1667
 
            proc.join()
1668
1546
            return False
1669
1547
        
1670
1548
        # Read a request from the child
1684
1562
                            "dress: %s", fpr, address)
1685
1563
                if self.use_dbus:
1686
1564
                    # Emit D-Bus signal
1687
 
                    mandos_dbus_service.ClientNotFound(fpr,
1688
 
                                                       address[0])
 
1565
                    mandos_dbus_service.ClientNotFound(fpr, address[0])
1689
1566
                parent_pipe.send(False)
1690
1567
                return False
1691
1568
            
1692
1569
            gobject.io_add_watch(parent_pipe.fileno(),
1693
1570
                                 gobject.IO_IN | gobject.IO_HUP,
1694
1571
                                 functools.partial(self.handle_ipc,
1695
 
                                                   parent_pipe =
1696
 
                                                   parent_pipe,
1697
 
                                                   proc = proc,
1698
 
                                                   client_object =
1699
 
                                                   client))
 
1572
                                                   parent_pipe = parent_pipe,
 
1573
                                                   client_object = client))
1700
1574
            parent_pipe.send(True)
1701
 
            # remove the old hook in favor of the new above hook on
1702
 
            # same fileno
 
1575
            # remove the old hook in favor of the new above hook on same fileno
1703
1576
            return False
1704
1577
        if command == 'funcall':
1705
1578
            funcname = request[1]
1706
1579
            args = request[2]
1707
1580
            kwargs = request[3]
1708
1581
            
1709
 
            parent_pipe.send(('data', getattr(client_object,
1710
 
                                              funcname)(*args,
1711
 
                                                         **kwargs)))
 
1582
            parent_pipe.send(('data', getattr(client_object, funcname)(*args, **kwargs)))
1712
1583
        
1713
1584
        if command == 'getattr':
1714
1585
            attrname = request[1]
1715
1586
            if callable(client_object.__getattribute__(attrname)):
1716
1587
                parent_pipe.send(('function',))
1717
1588
            else:
1718
 
                parent_pipe.send(('data', client_object
1719
 
                                  .__getattribute__(attrname)))
 
1589
                parent_pipe.send(('data', client_object.__getattribute__(attrname)))
1720
1590
        
1721
1591
        if command == 'setattr':
1722
1592
            attrname = request[1]
2011
1881
    # End of Avahi example code
2012
1882
    if use_dbus:
2013
1883
        try:
2014
 
            bus_name = dbus.service.BusName("se.recompile.Mandos",
 
1884
            bus_name = dbus.service.BusName("se.bsnet.fukt.Mandos",
2015
1885
                                            bus, do_not_queue=True)
2016
 
            old_bus_name = (dbus.service.BusName
2017
 
                            ("se.bsnet.fukt.Mandos", bus,
2018
 
                             do_not_queue=True))
2019
1886
        except dbus.exceptions.NameExistsException as e:
2020
1887
            logger.error(unicode(e) + ", disabling D-Bus")
2021
1888
            use_dbus = False
2034
1901
    
2035
1902
    client_class = Client
2036
1903
    if use_dbus:
2037
 
        client_class = functools.partial(ClientDBusTransitional,
2038
 
                                         bus = bus)
 
1904
        client_class = functools.partial(ClientDBus, bus = bus)
2039
1905
    def client_config_items(config, section):
2040
1906
        special_settings = {
2041
1907
            "approved_by_default":
2080
1946
            """A D-Bus proxy object"""
2081
1947
            def __init__(self):
2082
1948
                dbus.service.Object.__init__(self, bus, "/")
2083
 
            _interface = "se.recompile.Mandos"
 
1949
            _interface = "se.bsnet.fukt.Mandos"
2084
1950
            
2085
1951
            @dbus.service.signal(_interface, signature="o")
2086
1952
            def ClientAdded(self, objpath):
2128
1994
            
2129
1995
            del _interface
2130
1996
        
2131
 
        class MandosDBusServiceTransitional(MandosDBusService):
2132
 
            __metaclass__ = AlternateDBusNamesMetaclass
2133
 
        mandos_dbus_service = MandosDBusServiceTransitional()
 
1997
        mandos_dbus_service = MandosDBusService()
2134
1998
    
2135
1999
    def cleanup():
2136
2000
        "Cleanup function; run on exit"
2137
2001
        service.cleanup()
2138
2002
        
2139
 
        multiprocessing.active_children()
2140
2003
        while tcp_server.clients:
2141
2004
            client = tcp_server.clients.pop()
2142
2005
            if use_dbus:
2146
2009
            client.disable(quiet=True)
2147
2010
            if use_dbus:
2148
2011
                # Emit D-Bus signal
2149
 
                mandos_dbus_service.ClientRemoved(client
2150
 
                                                  .dbus_object_path,
 
2012
                mandos_dbus_service.ClientRemoved(client.dbus_object_path,
2151
2013
                                                  client.name)
2152
2014
    
2153
2015
    atexit.register(cleanup)