/mandos/release

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

« back to all changes in this revision

Viewing changes to mandos

  • Committer: Teddy Hogeborn
  • Date: 2012-01-08 10:19:33 UTC
  • Revision ID: teddy@recompile.se-20120108101933-xbtodqgepxax8hn1
Tags: version-1.5.2-1
* Makefile (version): Changed to "1.5.2".
* NEWS (Version 1.5.2): New entry.
* debian/changelog (1.5.2-1): - '' -

Show diffs side-by-side

added added

removed removed

Lines of Context:
65
65
import types
66
66
import binascii
67
67
import tempfile
68
 
import itertools
69
68
 
70
69
import dbus
71
70
import dbus.service
86
85
    except ImportError:
87
86
        SO_BINDTODEVICE = None
88
87
 
89
 
version = "1.5.3"
 
88
version = "1.5.2"
90
89
stored_state_file = "clients.pickle"
91
90
 
92
91
logger = logging.getLogger()
176
175
    
177
176
    def encrypt(self, data, password):
178
177
        self.gnupg.passphrase = self.password_encode(password)
179
 
        with open(os.devnull, "w") as devnull:
 
178
        with open(os.devnull) as devnull:
180
179
            try:
181
180
                proc = self.gnupg.run(['--symmetric'],
182
181
                                      create_fhs=['stdin', 'stdout'],
193
192
    
194
193
    def decrypt(self, data, password):
195
194
        self.gnupg.passphrase = self.password_encode(password)
196
 
        with open(os.devnull, "w") as devnull:
 
195
        with open(os.devnull) as devnull:
197
196
            try:
198
197
                proc = self.gnupg.run(['--decrypt'],
199
198
                                      create_fhs=['stdin', 'stdout'],
200
199
                                      attach_fhs={'stderr': devnull})
201
 
                with contextlib.closing(proc.handles['stdin']) as f:
 
200
                with contextlib.closing(proc.handles['stdin'] ) as f:
202
201
                    f.write(data)
203
202
                with contextlib.closing(proc.handles['stdout']) as f:
204
203
                    decrypted_plaintext = f.read()
277
276
        try:
278
277
            self.add()
279
278
        except dbus.exceptions.DBusException as error:
280
 
            logger.critical("D-Bus Exception", exc_info=error)
 
279
            logger.critical("DBusException: %s", error)
281
280
            self.cleanup()
282
281
            os._exit(1)
283
282
        self.rename_count += 1
322
321
        elif state == avahi.ENTRY_GROUP_FAILURE:
323
322
            logger.critical("Avahi: Error in group state changed %s",
324
323
                            unicode(error))
325
 
            raise AvahiGroupError("State changed: {0!s}"
326
 
                                  .format(error))
 
324
            raise AvahiGroupError("State changed: %s"
 
325
                                  % unicode(error))
327
326
    def cleanup(self):
328
327
        """Derived from the Avahi example code"""
329
328
        if self.group is not None:
375
374
        """Add the new name to the syslog messages"""
376
375
        ret = AvahiService.rename(self)
377
376
        syslogger.setFormatter(logging.Formatter
378
 
                               ('Mandos ({0}) [%(process)d]:'
379
 
                                ' %(levelname)s: %(message)s'
380
 
                                .format(self.name)))
 
377
                               ('Mandos (%s) [%%(process)d]:'
 
378
                                ' %%(levelname)s: %%(message)s'
 
379
                                % self.name))
381
380
        return ret
382
381
 
383
382
def timedelta_to_milliseconds(td):
416
415
    last_checked_ok: datetime.datetime(); (UTC) or None
417
416
    last_checker_status: integer between 0 and 255 reflecting exit
418
417
                         status of last checker. -1 reflects crashed
419
 
                         checker, -2 means no checker completed yet.
 
418
                         checker, or None.
420
419
    last_enabled: datetime.datetime(); (UTC) or None
421
420
    name:       string; from the config file, used in log messages and
422
421
                        D-Bus identifiers
489
488
                          "rb") as secfile:
490
489
                    client["secret"] = secfile.read()
491
490
            else:
492
 
                raise TypeError("No secret or secfile for section {0}"
493
 
                                .format(section))
 
491
                raise TypeError("No secret or secfile for section %s"
 
492
                                % section)
494
493
            client["timeout"] = string_to_delta(section["timeout"])
495
494
            client["extended_timeout"] = string_to_delta(
496
495
                section["extended_timeout"])
502
501
            client["checker_command"] = section["checker"]
503
502
            client["last_approval_request"] = None
504
503
            client["last_checked_ok"] = None
505
 
            client["last_checker_status"] = -2
 
504
            client["last_checker_status"] = None
506
505
        
507
506
        return settings
508
507
        
627
626
            logger.warning("Checker for %(name)s crashed?",
628
627
                           vars(self))
629
628
    
630
 
    def checked_ok(self):
631
 
        """Assert that the client has been seen, alive and well."""
632
 
        self.last_checked_ok = datetime.datetime.utcnow()
633
 
        self.last_checker_status = 0
634
 
        self.bump_timeout()
635
 
    
636
 
    def bump_timeout(self, timeout=None):
637
 
        """Bump up the timeout for this client."""
 
629
    def checked_ok(self, timeout=None):
 
630
        """Bump up the timeout for this client.
 
631
        
 
632
        This should only be called when the client has been seen,
 
633
        alive and well.
 
634
        """
638
635
        if timeout is None:
639
636
            timeout = self.timeout
 
637
        self.last_checked_ok = datetime.datetime.utcnow()
640
638
        if self.disable_initiator_tag is not None:
641
639
            gobject.source_remove(self.disable_initiator_tag)
642
640
        if getattr(self, "enabled", False):
693
691
                try:
694
692
                    command = self.checker_command % escaped_attrs
695
693
                except TypeError as error:
696
 
                    logger.error('Could not format string "%s"',
697
 
                                 self.checker_command, exc_info=error)
 
694
                    logger.error('Could not format string "%s":'
 
695
                                 ' %s', self.checker_command, error)
698
696
                    return True # Try again later
699
697
            self.current_checker_command = command
700
698
            try:
718
716
                    gobject.source_remove(self.checker_callback_tag)
719
717
                    self.checker_callback(pid, status, command)
720
718
            except OSError as error:
721
 
                logger.error("Failed to start subprocess",
722
 
                             exc_info=error)
 
719
                logger.error("Failed to start subprocess: %s",
 
720
                             error)
723
721
        # Re-run this periodically if run by gobject.timeout_add
724
722
        return True
725
723
    
732
730
            return
733
731
        logger.debug("Stopping checker for %(name)s", vars(self))
734
732
        try:
735
 
            self.checker.terminate()
 
733
            os.kill(self.checker.pid, signal.SIGTERM)
736
734
            #time.sleep(0.5)
737
735
            #if self.checker.poll() is None:
738
 
            #    self.checker.kill()
 
736
            #    os.kill(self.checker.pid, signal.SIGKILL)
739
737
        except OSError as error:
740
738
            if error.errno != errno.ESRCH: # No such process
741
739
                raise
758
756
    # "Set" method, so we fail early here:
759
757
    if byte_arrays and signature != "ay":
760
758
        raise ValueError("Byte arrays not supported for non-'ay'"
761
 
                         " signature {0!r}".format(signature))
 
759
                         " signature %r" % signature)
762
760
    def decorator(func):
763
761
        func._dbus_is_property = True
764
762
        func._dbus_interface = dbus_interface
772
770
    return decorator
773
771
 
774
772
 
775
 
def dbus_interface_annotations(dbus_interface):
776
 
    """Decorator for marking functions returning interface annotations.
777
 
    
778
 
    Usage:
779
 
    
780
 
    @dbus_interface_annotations("org.example.Interface")
781
 
    def _foo(self):  # Function name does not matter
782
 
        return {"org.freedesktop.DBus.Deprecated": "true",
783
 
                "org.freedesktop.DBus.Property.EmitsChangedSignal":
784
 
                    "false"}
785
 
    """
786
 
    def decorator(func):
787
 
        func._dbus_is_interface = True
788
 
        func._dbus_interface = dbus_interface
789
 
        func._dbus_name = dbus_interface
790
 
        return func
791
 
    return decorator
792
 
 
793
 
 
794
 
def dbus_annotations(annotations):
795
 
    """Decorator to annotate D-Bus methods, signals or properties
796
 
    Usage:
797
 
    
798
 
    @dbus_service_property("org.example.Interface", signature="b",
799
 
                           access="r")
800
 
    @dbus_annotations({{"org.freedesktop.DBus.Deprecated": "true",
801
 
                        "org.freedesktop.DBus.Property."
802
 
                        "EmitsChangedSignal": "false"})
803
 
    def Property_dbus_property(self):
804
 
        return dbus.Boolean(False)
805
 
    """
806
 
    def decorator(func):
807
 
        func._dbus_annotations = annotations
808
 
        return func
809
 
    return decorator
810
 
 
811
 
 
812
773
class DBusPropertyException(dbus.exceptions.DBusException):
813
774
    """A base class for D-Bus property-related exceptions
814
775
    """
837
798
    """
838
799
    
839
800
    @staticmethod
840
 
    def _is_dbus_thing(thing):
841
 
        """Returns a function testing if an attribute is a D-Bus thing
842
 
        
843
 
        If called like _is_dbus_thing("method") it returns a function
844
 
        suitable for use as predicate to inspect.getmembers().
845
 
        """
846
 
        return lambda obj: getattr(obj, "_dbus_is_{0}".format(thing),
847
 
                                   False)
 
801
    def _is_dbus_property(obj):
 
802
        return getattr(obj, "_dbus_is_property", False)
848
803
    
849
 
    def _get_all_dbus_things(self, thing):
 
804
    def _get_all_dbus_properties(self):
850
805
        """Returns a generator of (name, attribute) pairs
851
806
        """
852
 
        return ((getattr(athing.__get__(self), "_dbus_name",
853
 
                         name),
854
 
                 athing.__get__(self))
 
807
        return ((prop.__get__(self)._dbus_name, prop.__get__(self))
855
808
                for cls in self.__class__.__mro__
856
 
                for name, athing in
857
 
                inspect.getmembers(cls,
858
 
                                   self._is_dbus_thing(thing)))
 
809
                for name, prop in
 
810
                inspect.getmembers(cls, self._is_dbus_property))
859
811
    
860
812
    def _get_dbus_property(self, interface_name, property_name):
861
813
        """Returns a bound method if one exists which is a D-Bus
863
815
        """
864
816
        for cls in  self.__class__.__mro__:
865
817
            for name, value in (inspect.getmembers
866
 
                                (cls,
867
 
                                 self._is_dbus_thing("property"))):
 
818
                                (cls, self._is_dbus_property)):
868
819
                if (value._dbus_name == property_name
869
820
                    and value._dbus_interface == interface_name):
870
821
                    return value.__get__(self)
912
863
        Note: Will not include properties with access="write".
913
864
        """
914
865
        properties = {}
915
 
        for name, prop in self._get_all_dbus_things("property"):
 
866
        for name, prop in self._get_all_dbus_properties():
916
867
            if (interface_name
917
868
                and interface_name != prop._dbus_interface):
918
869
                # Interface non-empty but did not match
933
884
                         path_keyword='object_path',
934
885
                         connection_keyword='connection')
935
886
    def Introspect(self, object_path, connection):
936
 
        """Overloading of standard D-Bus method.
937
 
        
938
 
        Inserts property tags and interface annotation tags.
 
887
        """Standard D-Bus method, overloaded to insert property tags.
939
888
        """
940
889
        xmlstring = dbus.service.Object.Introspect(self, object_path,
941
890
                                                   connection)
948
897
                e.setAttribute("access", prop._dbus_access)
949
898
                return e
950
899
            for if_tag in document.getElementsByTagName("interface"):
951
 
                # Add property tags
952
900
                for tag in (make_tag(document, name, prop)
953
901
                            for name, prop
954
 
                            in self._get_all_dbus_things("property")
 
902
                            in self._get_all_dbus_properties()
955
903
                            if prop._dbus_interface
956
904
                            == if_tag.getAttribute("name")):
957
905
                    if_tag.appendChild(tag)
958
 
                # Add annotation tags
959
 
                for typ in ("method", "signal", "property"):
960
 
                    for tag in if_tag.getElementsByTagName(typ):
961
 
                        annots = dict()
962
 
                        for name, prop in (self.
963
 
                                           _get_all_dbus_things(typ)):
964
 
                            if (name == tag.getAttribute("name")
965
 
                                and prop._dbus_interface
966
 
                                == if_tag.getAttribute("name")):
967
 
                                annots.update(getattr
968
 
                                              (prop,
969
 
                                               "_dbus_annotations",
970
 
                                               {}))
971
 
                        for name, value in annots.iteritems():
972
 
                            ann_tag = document.createElement(
973
 
                                "annotation")
974
 
                            ann_tag.setAttribute("name", name)
975
 
                            ann_tag.setAttribute("value", value)
976
 
                            tag.appendChild(ann_tag)
977
 
                # Add interface annotation tags
978
 
                for annotation, value in dict(
979
 
                    itertools.chain(
980
 
                        *(annotations().iteritems()
981
 
                          for name, annotations in
982
 
                          self._get_all_dbus_things("interface")
983
 
                          if name == if_tag.getAttribute("name")
984
 
                          ))).iteritems():
985
 
                    ann_tag = document.createElement("annotation")
986
 
                    ann_tag.setAttribute("name", annotation)
987
 
                    ann_tag.setAttribute("value", value)
988
 
                    if_tag.appendChild(ann_tag)
989
906
                # Add the names to the return values for the
990
907
                # "org.freedesktop.DBus.Properties" methods
991
908
                if (if_tag.getAttribute("name")
1006
923
        except (AttributeError, xml.dom.DOMException,
1007
924
                xml.parsers.expat.ExpatError) as error:
1008
925
            logger.error("Failed to override Introspection method",
1009
 
                         exc_info=error)
 
926
                         error)
1010
927
        return xmlstring
1011
928
 
1012
929
 
1026
943
    def __new__(mcs, name, bases, attr):
1027
944
        # Go through all the base classes which could have D-Bus
1028
945
        # methods, signals, or properties in them
1029
 
        old_interface_names = []
1030
946
        for base in (b for b in bases
1031
947
                     if issubclass(b, dbus.service.Object)):
1032
948
            # Go though all attributes of the base class
1042
958
                alt_interface = (attribute._dbus_interface
1043
959
                                 .replace("se.recompile.Mandos",
1044
960
                                          "se.bsnet.fukt.Mandos"))
1045
 
                if alt_interface != attribute._dbus_interface:
1046
 
                    old_interface_names.append(alt_interface)
1047
961
                # Is this a D-Bus signal?
1048
962
                if getattr(attribute, "_dbus_is_signal", False):
1049
963
                    # Extract the original non-method function by
1064
978
                                nonmethod_func.func_name,
1065
979
                                nonmethod_func.func_defaults,
1066
980
                                nonmethod_func.func_closure)))
1067
 
                    # Copy annotations, if any
1068
 
                    try:
1069
 
                        new_function._dbus_annotations = (
1070
 
                            dict(attribute._dbus_annotations))
1071
 
                    except AttributeError:
1072
 
                        pass
1073
981
                    # Define a creator of a function to call both the
1074
982
                    # old and new functions, so both the old and new
1075
983
                    # signals gets sent when the function is called
1103
1011
                                        attribute.func_name,
1104
1012
                                        attribute.func_defaults,
1105
1013
                                        attribute.func_closure)))
1106
 
                    # Copy annotations, if any
1107
 
                    try:
1108
 
                        attr[attrname]._dbus_annotations = (
1109
 
                            dict(attribute._dbus_annotations))
1110
 
                    except AttributeError:
1111
 
                        pass
1112
1014
                # Is this a D-Bus property?
1113
1015
                elif getattr(attribute, "_dbus_is_property", False):
1114
1016
                    # Create a new, but exactly alike, function
1128
1030
                                        attribute.func_name,
1129
1031
                                        attribute.func_defaults,
1130
1032
                                        attribute.func_closure)))
1131
 
                    # Copy annotations, if any
1132
 
                    try:
1133
 
                        attr[attrname]._dbus_annotations = (
1134
 
                            dict(attribute._dbus_annotations))
1135
 
                    except AttributeError:
1136
 
                        pass
1137
 
                # Is this a D-Bus interface?
1138
 
                elif getattr(attribute, "_dbus_is_interface", False):
1139
 
                    # Create a new, but exactly alike, function
1140
 
                    # object.  Decorate it to be a new D-Bus interface
1141
 
                    # with the alternate D-Bus interface name.  Add it
1142
 
                    # to the class.
1143
 
                    attr[attrname] = (dbus_interface_annotations
1144
 
                                      (alt_interface)
1145
 
                                      (types.FunctionType
1146
 
                                       (attribute.func_code,
1147
 
                                        attribute.func_globals,
1148
 
                                        attribute.func_name,
1149
 
                                        attribute.func_defaults,
1150
 
                                        attribute.func_closure)))
1151
 
        # Deprecate all old interfaces
1152
 
        basename="_AlternateDBusNamesMetaclass_interface_annotation{0}"
1153
 
        for old_interface_name in old_interface_names:
1154
 
            @dbus_interface_annotations(old_interface_name)
1155
 
            def func(self):
1156
 
                return { "org.freedesktop.DBus.Deprecated": "true" }
1157
 
            # Find an unused name
1158
 
            for aname in (basename.format(i) for i in
1159
 
                          itertools.count()):
1160
 
                if aname not in attr:
1161
 
                    attr[aname] = func
1162
 
                    break
1163
1033
        return type.__new__(mcs, name, bases, attr)
1164
1034
 
1165
1035
 
1230
1100
                                       checker is not None)
1231
1101
    last_checked_ok = notifychangeproperty(datetime_to_dbus,
1232
1102
                                           "LastCheckedOK")
1233
 
    last_checker_status = notifychangeproperty(dbus.Int16,
1234
 
                                               "LastCheckerStatus")
1235
1103
    last_approval_request = notifychangeproperty(
1236
1104
        datetime_to_dbus, "LastApprovalRequest")
1237
1105
    approved_by_default = notifychangeproperty(dbus.Boolean,
1315
1183
    ## D-Bus methods, signals & properties
1316
1184
    _interface = "se.recompile.Mandos.Client"
1317
1185
    
1318
 
    ## Interfaces
1319
 
    
1320
 
    @dbus_interface_annotations(_interface)
1321
 
    def _foo(self):
1322
 
        return { "org.freedesktop.DBus.Property.EmitsChangedSignal":
1323
 
                     "false"}
1324
 
    
1325
1186
    ## Signals
1326
1187
    
1327
1188
    # CheckerCompleted - signal
1478
1339
            return
1479
1340
        return datetime_to_dbus(self.last_checked_ok)
1480
1341
    
1481
 
    # LastCheckerStatus - property
1482
 
    @dbus_service_property(_interface, signature="n",
1483
 
                           access="read")
1484
 
    def LastCheckerStatus_dbus_property(self):
1485
 
        return dbus.Int16(self.last_checker_status)
1486
 
    
1487
1342
    # Expires - property
1488
1343
    @dbus_service_property(_interface, signature="s", access="read")
1489
1344
    def Expires_dbus_property(self):
1750
1605
                
1751
1606
                logger.info("Sending secret to %s", client.name)
1752
1607
                # bump the timeout using extended_timeout
1753
 
                client.bump_timeout(client.extended_timeout)
 
1608
                client.checked_ok(client.extended_timeout)
1754
1609
                if self.server.use_dbus:
1755
1610
                    # Emit D-Bus signal
1756
1611
                    client.GotSecret()
2079
1934
            elif suffix == "w":
2080
1935
                delta = datetime.timedelta(0, 0, 0, 0, 0, 0, value)
2081
1936
            else:
2082
 
                raise ValueError("Unknown suffix {0!r}"
2083
 
                                 .format(suffix))
 
1937
                raise ValueError("Unknown suffix %r" % suffix)
2084
1938
        except (ValueError, IndexError) as e:
2085
1939
            raise ValueError(*(e.args))
2086
1940
        timevalue += delta
2100
1954
        sys.exit()
2101
1955
    if not noclose:
2102
1956
        # Close all standard open file descriptors
2103
 
        null = os.open(os.devnull, os.O_NOCTTY | os.O_RDWR)
 
1957
        null = os.open(os.path.devnull, os.O_NOCTTY | os.O_RDWR)
2104
1958
        if not stat.S_ISCHR(os.fstat(null).st_mode):
2105
1959
            raise OSError(errno.ENODEV,
2106
 
                          "{0} not a character device"
2107
 
                          .format(os.devnull))
 
1960
                          "%s not a character device"
 
1961
                          % os.path.devnull)
2108
1962
        os.dup2(null, sys.stdin.fileno())
2109
1963
        os.dup2(null, sys.stdout.fileno())
2110
1964
        os.dup2(null, sys.stderr.fileno())
2119
1973
    
2120
1974
    parser = argparse.ArgumentParser()
2121
1975
    parser.add_argument("-v", "--version", action="version",
2122
 
                        version = "%(prog)s {0}".format(version),
 
1976
                        version = "%%(prog)s %s" % version,
2123
1977
                        help="show version number and exit")
2124
1978
    parser.add_argument("-i", "--interface", metavar="IF",
2125
1979
                        help="Bind to interface IF")
2228
2082
    
2229
2083
    if server_settings["servicename"] != "Mandos":
2230
2084
        syslogger.setFormatter(logging.Formatter
2231
 
                               ('Mandos ({0}) [%(process)d]:'
2232
 
                                ' %(levelname)s: %(message)s'
2233
 
                                .format(server_settings
2234
 
                                        ["servicename"])))
 
2085
                               ('Mandos (%s) [%%(process)d]:'
 
2086
                                ' %%(levelname)s: %%(message)s'
 
2087
                                % server_settings["servicename"]))
2235
2088
    
2236
2089
    # Parse config file with clients
2237
2090
    client_config = configparser.SafeConfigParser(Client
2258
2111
        except IOError:
2259
2112
            logger.error("Could not open file %r", pidfilename)
2260
2113
    
2261
 
    for name in ("_mandos", "mandos", "nobody"):
 
2114
    try:
 
2115
        uid = pwd.getpwnam("_mandos").pw_uid
 
2116
        gid = pwd.getpwnam("_mandos").pw_gid
 
2117
    except KeyError:
2262
2118
        try:
2263
 
            uid = pwd.getpwnam(name).pw_uid
2264
 
            gid = pwd.getpwnam(name).pw_gid
2265
 
            break
 
2119
            uid = pwd.getpwnam("mandos").pw_uid
 
2120
            gid = pwd.getpwnam("mandos").pw_gid
2266
2121
        except KeyError:
2267
 
            continue
2268
 
    else:
2269
 
        uid = 65534
2270
 
        gid = 65534
 
2122
            try:
 
2123
                uid = pwd.getpwnam("nobody").pw_uid
 
2124
                gid = pwd.getpwnam("nobody").pw_gid
 
2125
            except KeyError:
 
2126
                uid = 65534
 
2127
                gid = 65534
2271
2128
    try:
2272
2129
        os.setgid(gid)
2273
2130
        os.setuid(uid)
2290
2147
         .gnutls_global_set_log_function(debug_gnutls))
2291
2148
        
2292
2149
        # Redirect stdin so all checkers get /dev/null
2293
 
        null = os.open(os.devnull, os.O_NOCTTY | os.O_RDWR)
 
2150
        null = os.open(os.path.devnull, os.O_NOCTTY | os.O_RDWR)
2294
2151
        os.dup2(null, sys.stdin.fileno())
2295
2152
        if null > 2:
2296
2153
            os.close(null)
2304
2161
    
2305
2162
    global main_loop
2306
2163
    # From the Avahi example code
2307
 
    DBusGMainLoop(set_as_default=True)
 
2164
    DBusGMainLoop(set_as_default=True )
2308
2165
    main_loop = gobject.MainLoop()
2309
2166
    bus = dbus.SystemBus()
2310
2167
    # End of Avahi example code
2451
2308
    signal.signal(signal.SIGTERM, lambda signum, frame: sys.exit())
2452
2309
    
2453
2310
    if use_dbus:
2454
 
        class MandosDBusService(DBusObjectWithProperties):
 
2311
        class MandosDBusService(dbus.service.Object):
2455
2312
            """A D-Bus proxy object"""
2456
2313
            def __init__(self):
2457
2314
                dbus.service.Object.__init__(self, bus, "/")
2458
2315
            _interface = "se.recompile.Mandos"
2459
2316
            
2460
 
            @dbus_interface_annotations(_interface)
2461
 
            def _foo(self):
2462
 
                return { "org.freedesktop.DBus.Property"
2463
 
                         ".EmitsChangedSignal":
2464
 
                             "false"}
2465
 
            
2466
2317
            @dbus.service.signal(_interface, signature="o")
2467
2318
            def ClientAdded(self, objpath):
2468
2319
                "D-Bus signal"
2601
2452
    service.port = tcp_server.socket.getsockname()[1]
2602
2453
    if use_ipv6:
2603
2454
        logger.info("Now listening on address %r, port %d,"
2604
 
                    " flowinfo %d, scope_id %d",
2605
 
                    *tcp_server.socket.getsockname())
 
2455
                    " flowinfo %d, scope_id %d"
 
2456
                    % tcp_server.socket.getsockname())
2606
2457
    else:                       # IPv4
2607
 
        logger.info("Now listening on address %r, port %d",
2608
 
                    *tcp_server.socket.getsockname())
 
2458
        logger.info("Now listening on address %r, port %d"
 
2459
                    % tcp_server.socket.getsockname())
2609
2460
    
2610
2461
    #service.interface = tcp_server.socket.getsockname()[3]
2611
2462
    
2614
2465
        try:
2615
2466
            service.activate()
2616
2467
        except dbus.exceptions.DBusException as error:
2617
 
            logger.critical("D-Bus Exception", exc_info=error)
 
2468
            logger.critical("DBusException: %s", error)
2618
2469
            cleanup()
2619
2470
            sys.exit(1)
2620
2471
        # End of Avahi example code
2627
2478
        logger.debug("Starting main loop")
2628
2479
        main_loop.run()
2629
2480
    except AvahiError as error:
2630
 
        logger.critical("Avahi Error", exc_info=error)
 
2481
        logger.critical("AvahiError: %s", error)
2631
2482
        cleanup()
2632
2483
        sys.exit(1)
2633
2484
    except KeyboardInterrupt: