=== modified file 'mandos' --- mandos 2015-03-10 18:03:38 +0000 +++ mandos 2015-04-03 03:01:02 +0000 @@ -11,8 +11,8 @@ # "AvahiService" class, and some lines in "main". # # Everything else is -# Copyright © 2008-2014 Teddy Hogeborn -# Copyright © 2008-2014 Björn Påhlsson +# Copyright © 2008-2015 Teddy Hogeborn +# Copyright © 2008-2015 Björn Påhlsson # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -98,10 +98,10 @@ syslogger = None try: - if_nametoindex = (ctypes.cdll.LoadLibrary - (ctypes.util.find_library("c")) - .if_nametoindex) + if_nametoindex = ctypes.cdll.LoadLibrary( + ctypes.util.find_library("c")).if_nametoindex except (OSError, AttributeError): + def if_nametoindex(interface): "Get an interface index the hard way, i.e. using fcntl()" SIOCGIFINDEX = 0x8933 # From /usr/include/linux/sockios.h @@ -116,10 +116,9 @@ """init logger and add loglevel""" global syslogger - syslogger = (logging.handlers.SysLogHandler - (facility = - logging.handlers.SysLogHandler.LOG_DAEMON, - address = "/dev/log")) + syslogger = (logging.handlers.SysLogHandler( + facility = logging.handlers.SysLogHandler.LOG_DAEMON, + address = "/dev/log")) syslogger.setFormatter(logging.Formatter ('Mandos [%(process)d]: %(levelname)s:' ' %(message)s')) @@ -142,6 +141,7 @@ class PGPEngine(object): """A simple class for OpenPGP symmetric encryption & decryption""" + def __init__(self): self.tempdir = tempfile.mkdtemp(prefix="mandos-") self.gnupgargs = ['--batch', @@ -186,8 +186,8 @@ def encrypt(self, data, password): passphrase = self.password_encode(password) - with tempfile.NamedTemporaryFile(dir=self.tempdir - ) as passfile: + with tempfile.NamedTemporaryFile( + dir=self.tempdir) as passfile: passfile.write(passphrase) passfile.flush() proc = subprocess.Popen(['gpg', '--symmetric', @@ -204,8 +204,8 @@ def decrypt(self, data, password): passphrase = self.password_encode(password) - with tempfile.NamedTemporaryFile(dir = self.tempdir - ) as passfile: + with tempfile.NamedTemporaryFile( + dir = self.tempdir) as passfile: passfile.write(passphrase) passfile.flush() proc = subprocess.Popen(['gpg', '--decrypt', @@ -215,8 +215,7 @@ stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE) - decrypted_plaintext, err = proc.communicate(input - = data) + decrypted_plaintext, err = proc.communicate(input = data) if proc.returncode != 0: raise PGPError(err) return decrypted_plaintext @@ -228,9 +227,11 @@ return super(AvahiError, self).__init__(value, *args, **kwargs) + class AvahiServiceError(AvahiError): pass + class AvahiGroupError(AvahiError): pass @@ -256,10 +257,17 @@ bus: dbus.SystemBus() """ - def __init__(self, interface = avahi.IF_UNSPEC, name = None, - servicetype = None, port = None, TXT = None, - domain = "", host = "", max_renames = 32768, - protocol = avahi.PROTO_UNSPEC, bus = None): + def __init__(self, + interface = avahi.IF_UNSPEC, + name = None, + servicetype = None, + port = None, + TXT = None, + domain = "", + host = "", + max_renames = 32768, + protocol = avahi.PROTO_UNSPEC, + bus = None): self.interface = interface self.name = name self.type = servicetype @@ -282,8 +290,8 @@ " after %i retries, exiting.", self.rename_count) raise AvahiServiceError("Too many renames") - self.name = str(self.server - .GetAlternativeServiceName(self.name)) + self.name = str( + self.server.GetAlternativeServiceName(self.name)) self.rename_count += 1 logger.info("Changing Zeroconf service name to %r ...", self.name) @@ -344,8 +352,7 @@ elif state == avahi.ENTRY_GROUP_FAILURE: logger.critical("Avahi: Error in group state changed %s", str(error)) - raise AvahiGroupError("State changed: {!s}" - .format(error)) + raise AvahiGroupError("State changed: {!s}".format(error)) def cleanup(self): """Derived from the Avahi example code""" @@ -361,13 +368,12 @@ def server_state_changed(self, state, error=None): """Derived from the Avahi example code""" logger.debug("Avahi server state change: %i", state) - bad_states = { avahi.SERVER_INVALID: - "Zeroconf server invalid", - avahi.SERVER_REGISTERING: None, - avahi.SERVER_COLLISION: - "Zeroconf server name collision", - avahi.SERVER_FAILURE: - "Zeroconf server failure" } + bad_states = { + avahi.SERVER_INVALID: "Zeroconf server invalid", + avahi.SERVER_REGISTERING: None, + avahi.SERVER_COLLISION: "Zeroconf server name collision", + avahi.SERVER_FAILURE: "Zeroconf server failure", + } if state in bad_states: if bad_states[state] is not None: if error is None: @@ -392,7 +398,7 @@ follow_name_owner_changes=True), avahi.DBUS_INTERFACE_SERVER) self.server.connect_to_signal("StateChanged", - self.server_state_changed) + self.server_state_changed) self.server_state_changed(self.server.GetState()) @@ -400,10 +406,9 @@ def rename(self, *args, **kwargs): """Add the new name to the syslog messages""" ret = AvahiService.rename(self, *args, **kwargs) - syslogger.setFormatter(logging.Formatter - ('Mandos ({}) [%(process)d]:' - ' %(levelname)s: %(message)s' - .format(self.name))) + syslogger.setFormatter(logging.Formatter( + 'Mandos ({}) [%(process)d]: %(levelname)s: %(message)s' + .format(self.name))) return ret @@ -456,16 +461,17 @@ "fingerprint", "host", "interval", "last_approval_request", "last_checked_ok", "last_enabled", "name", "timeout") - client_defaults = { "timeout": "PT5M", - "extended_timeout": "PT15M", - "interval": "PT2M", - "checker": "fping -q -- %%(host)s", - "host": "", - "approval_delay": "PT0S", - "approval_duration": "PT1S", - "approved_by_default": "True", - "enabled": "True", - } + client_defaults = { + "timeout": "PT5M", + "extended_timeout": "PT15M", + "interval": "PT2M", + "checker": "fping -q -- %%(host)s", + "host": "", + "approval_delay": "PT0S", + "approval_duration": "PT1S", + "approved_by_default": "True", + "enabled": "True", + } @staticmethod def config_parser(config): @@ -549,18 +555,15 @@ self.current_checker_command = None self.approved = None self.approvals_pending = 0 - self.changedstate = (multiprocessing_manager - .Condition(multiprocessing_manager - .Lock())) - self.client_structure = [attr for attr in - self.__dict__.iterkeys() + self.changedstate = multiprocessing_manager.Condition( + multiprocessing_manager.Lock()) + self.client_structure = [attr + for attr in self.__dict__.iterkeys() if not attr.startswith("_")] self.client_structure.append("client_structure") - for name, t in inspect.getmembers(type(self), - lambda obj: - isinstance(obj, - property)): + for name, t in inspect.getmembers( + type(self), lambda obj: isinstance(obj, property)): if not name.startswith("_"): self.client_structure.append(name) @@ -608,17 +611,14 @@ # and every interval from then on. if self.checker_initiator_tag is not None: gobject.source_remove(self.checker_initiator_tag) - self.checker_initiator_tag = (gobject.timeout_add - (int(self.interval - .total_seconds() * 1000), - self.start_checker)) + self.checker_initiator_tag = gobject.timeout_add( + int(self.interval.total_seconds() * 1000), + self.start_checker) # Schedule a disable() when 'timeout' has passed if self.disable_initiator_tag is not None: gobject.source_remove(self.disable_initiator_tag) - self.disable_initiator_tag = (gobject.timeout_add - (int(self.timeout - .total_seconds() * 1000), - self.disable)) + self.disable_initiator_tag = gobject.timeout_add( + int(self.timeout.total_seconds() * 1000), self.disable) # Also start a new checker *right now*. self.start_checker() @@ -633,8 +633,7 @@ vars(self)) self.checked_ok() else: - logger.info("Checker for %(name)s failed", - vars(self)) + logger.info("Checker for %(name)s failed", vars(self)) else: self.last_checker_status = -1 logger.warning("Checker for %(name)s crashed?", @@ -654,9 +653,8 @@ gobject.source_remove(self.disable_initiator_tag) self.disable_initiator_tag = None if getattr(self, "enabled", False): - self.disable_initiator_tag = (gobject.timeout_add - (int(timeout.total_seconds() - * 1000), self.disable)) + self.disable_initiator_tag = gobject.timeout_add( + int(timeout.total_seconds() * 1000), self.disable) self.expires = datetime.datetime.utcnow() + timeout def need_approval(self): @@ -693,19 +691,20 @@ # Start a new checker if needed if self.checker is None: # Escape attributes for the shell - escaped_attrs = { attr: - re.escape(str(getattr(self, attr))) - for attr in self.runtime_expansions } + escaped_attrs = { + attr: re.escape(str(getattr(self, attr))) + for attr in self.runtime_expansions } try: command = self.checker_command % escaped_attrs except TypeError as error: logger.error('Could not format string "%s"', - self.checker_command, exc_info=error) - return True # Try again later + self.checker_command, + exc_info=error) + return True # Try again later self.current_checker_command = command try: - logger.info("Starting checker %r for %s", - command, self.name) + logger.info("Starting checker %r for %s", command, + self.name) # We don't need to redirect stdout and stderr, since # in normal mode, that is already done by daemon(), # and in debug mode we don't want to. (Stdin is @@ -720,16 +719,15 @@ "stderr": wnull }) self.checker = subprocess.Popen(command, close_fds=True, - shell=True, cwd="/", + shell=True, + cwd="/", **popen_args) except OSError as error: logger.error("Failed to start subprocess", exc_info=error) return True - self.checker_callback_tag = (gobject.child_watch_add - (self.checker.pid, - self.checker_callback, - data=command)) + self.checker_callback_tag = gobject.child_watch_add( + self.checker.pid, self.checker_callback, data=command) # The checker may have completed before the gobject # watch was added. Check for this. try: @@ -766,8 +764,10 @@ self.checker = None -def dbus_service_property(dbus_interface, signature="v", - access="readwrite", byte_arrays=False): +def dbus_service_property(dbus_interface, + signature="v", + access="readwrite", + byte_arrays=False): """Decorators for marking methods of a DBusObjectWithProperties to become properties on the D-Bus. @@ -783,6 +783,7 @@ if byte_arrays and signature != "ay": raise ValueError("Byte arrays not supported for non-'ay'" " signature {!r}".format(signature)) + def decorator(func): func._dbus_is_property = True func._dbus_interface = dbus_interface @@ -793,6 +794,7 @@ func._dbus_name = func._dbus_name[:-14] func._dbus_get_args_options = {'byte_arrays': byte_arrays } return func + return decorator @@ -807,11 +809,13 @@ "org.freedesktop.DBus.Property.EmitsChangedSignal": "false"} """ + def decorator(func): func._dbus_is_interface = True func._dbus_interface = dbus_interface func._dbus_name = dbus_interface return func + return decorator @@ -827,9 +831,11 @@ def Property_dbus_property(self): return dbus.Boolean(False) """ + def decorator(func): func._dbus_annotations = annotations return func + return decorator @@ -838,6 +844,7 @@ """ pass + class DBusPropertyAccessException(DBusPropertyException): """A property's access permissions disallows an operation. """ @@ -871,32 +878,29 @@ def _get_all_dbus_things(self, thing): """Returns a generator of (name, attribute) pairs """ - return ((getattr(athing.__get__(self), "_dbus_name", - name), + return ((getattr(athing.__get__(self), "_dbus_name", name), athing.__get__(self)) for cls in self.__class__.__mro__ for name, athing in - inspect.getmembers(cls, - self._is_dbus_thing(thing))) + inspect.getmembers(cls, self._is_dbus_thing(thing))) def _get_dbus_property(self, interface_name, property_name): """Returns a bound method if one exists which is a D-Bus property with the specified name and interface. """ - for cls in self.__class__.__mro__: - for name, value in (inspect.getmembers - (cls, - self._is_dbus_thing("property"))): + for cls in self.__class__.__mro__: + for name, value in inspect.getmembers( + cls, self._is_dbus_thing("property")): if (value._dbus_name == property_name and value._dbus_interface == interface_name): return value.__get__(self) # No such property - raise DBusPropertyNotFound(self.dbus_object_path + ":" - + interface_name + "." - + property_name) + raise DBusPropertyNotFound("{}:{}.{}".format( + self.dbus_object_path, interface_name, property_name)) - @dbus.service.method(dbus.PROPERTIES_IFACE, in_signature="ss", + @dbus.service.method(dbus.PROPERTIES_IFACE, + in_signature="ss", out_signature="v") def Get(self, interface_name, property_name): """Standard D-Bus property Get() method, see D-Bus standard. @@ -927,7 +931,8 @@ for byte in value)) prop(value) - @dbus.service.method(dbus.PROPERTIES_IFACE, in_signature="s", + @dbus.service.method(dbus.PROPERTIES_IFACE, + in_signature="s", out_signature="a{sv}") def GetAll(self, interface_name): """Standard D-Bus property GetAll() method, see D-Bus @@ -948,8 +953,8 @@ if not hasattr(value, "variant_level"): properties[name] = value continue - properties[name] = type(value)(value, variant_level= - value.variant_level+1) + properties[name] = type(value)( + value, variant_level = value.variant_level + 1) return dbus.Dictionary(properties, signature="sv") @dbus.service.signal(dbus.PROPERTIES_IFACE, signature="sa{sv}as") @@ -973,12 +978,14 @@ connection) try: document = xml.dom.minidom.parseString(xmlstring) + def make_tag(document, name, prop): e = document.createElement("property") e.setAttribute("name", name) e.setAttribute("type", prop._dbus_signature) e.setAttribute("access", prop._dbus_access) return e + for if_tag in document.getElementsByTagName("interface"): # Add property tags for tag in (make_tag(document, name, prop) @@ -996,10 +1003,8 @@ if (name == tag.getAttribute("name") and prop._dbus_interface == if_tag.getAttribute("name")): - annots.update(getattr - (prop, - "_dbus_annotations", - {})) + annots.update(getattr( + prop, "_dbus_annotations", {})) for name, value in annots.items(): ann_tag = document.createElement( "annotation") @@ -1010,8 +1015,8 @@ for annotation, value in dict( itertools.chain.from_iterable( annotations().items() - for name, annotations in - self._get_all_dbus_things("interface") + for name, annotations + in self._get_all_dbus_things("interface") if name == if_tag.getAttribute("name") )).items(): ann_tag = document.createElement("annotation") @@ -1046,8 +1051,7 @@ """Convert a UTC datetime.datetime() to a D-Bus type.""" if dt is None: return dbus.String("", variant_level = variant_level) - return dbus.String(dt.isoformat(), - variant_level=variant_level) + return dbus.String(dt.isoformat(), variant_level=variant_level) def alternate_dbus_interfaces(alt_interface_names, deprecate=True): @@ -1073,9 +1077,10 @@ (from DBusObjectWithProperties) and interfaces (from the dbus_interface_annotations decorator). """ + def wrapper(cls): for orig_interface_name, alt_interface_name in ( - alt_interface_names.items()): + alt_interface_names.items()): attr = {} interface_names = set() # Go though all attributes of the class @@ -1083,39 +1088,37 @@ # Ignore non-D-Bus attributes, and D-Bus attributes # with the wrong interface name if (not hasattr(attribute, "_dbus_interface") - or not attribute._dbus_interface - .startswith(orig_interface_name)): + or not attribute._dbus_interface.startswith( + orig_interface_name)): continue # Create an alternate D-Bus interface name based on # the current name - alt_interface = (attribute._dbus_interface - .replace(orig_interface_name, - alt_interface_name)) + alt_interface = attribute._dbus_interface.replace( + orig_interface_name, alt_interface_name) interface_names.add(alt_interface) # Is this a D-Bus signal? if getattr(attribute, "_dbus_is_signal", False): # Extract the original non-method undecorated # function by black magic nonmethod_func = (dict( - zip(attribute.func_code.co_freevars, - attribute.__closure__))["func"] - .cell_contents) + zip(attribute.func_code.co_freevars, + attribute.__closure__)) + ["func"].cell_contents) # Create a new, but exactly alike, function # object, and decorate it to be a new D-Bus signal # with the alternate D-Bus interface name - new_function = (dbus.service.signal - (alt_interface, - attribute._dbus_signature) + new_function = (dbus.service.signal( + alt_interface, attribute._dbus_signature) (types.FunctionType( - nonmethod_func.func_code, - nonmethod_func.func_globals, - nonmethod_func.func_name, - nonmethod_func.func_defaults, - nonmethod_func.func_closure))) + nonmethod_func.func_code, + nonmethod_func.func_globals, + nonmethod_func.func_name, + nonmethod_func.func_defaults, + nonmethod_func.func_closure))) # Copy annotations, if any try: - new_function._dbus_annotations = ( - dict(attribute._dbus_annotations)) + new_function._dbus_annotations = dict( + attribute._dbus_annotations) except AttributeError: pass # Define a creator of a function to call both the @@ -1126,11 +1129,13 @@ """This function is a scope container to pass func1 and func2 to the "call_both" function outside of its arguments""" + def call_both(*args, **kwargs): """This function will emit two D-Bus signals by calling func1 and func2""" func1(*args, **kwargs) func2(*args, **kwargs) + return call_both # Create the "call_both" function and add it to # the class @@ -1141,20 +1146,20 @@ # object. Decorate it to be a new D-Bus method # with the alternate D-Bus interface name. Add it # to the class. - attr[attrname] = (dbus.service.method - (alt_interface, - attribute._dbus_in_signature, - attribute._dbus_out_signature) - (types.FunctionType - (attribute.func_code, - attribute.func_globals, - attribute.func_name, - attribute.func_defaults, - attribute.func_closure))) + attr[attrname] = ( + dbus.service.method( + alt_interface, + attribute._dbus_in_signature, + attribute._dbus_out_signature) + (types.FunctionType(attribute.func_code, + attribute.func_globals, + attribute.func_name, + attribute.func_defaults, + attribute.func_closure))) # Copy annotations, if any try: - attr[attrname]._dbus_annotations = ( - dict(attribute._dbus_annotations)) + attr[attrname]._dbus_annotations = dict( + attribute._dbus_annotations) except AttributeError: pass # Is this a D-Bus property? @@ -1163,23 +1168,21 @@ # object, and decorate it to be a new D-Bus # property with the alternate D-Bus interface # name. Add it to the class. - attr[attrname] = (dbus_service_property - (alt_interface, - attribute._dbus_signature, - attribute._dbus_access, - attribute - ._dbus_get_args_options - ["byte_arrays"]) - (types.FunctionType - (attribute.func_code, - attribute.func_globals, - attribute.func_name, - attribute.func_defaults, - attribute.func_closure))) + attr[attrname] = (dbus_service_property( + alt_interface, attribute._dbus_signature, + attribute._dbus_access, + attribute._dbus_get_args_options + ["byte_arrays"]) + (types.FunctionType( + attribute.func_code, + attribute.func_globals, + attribute.func_name, + attribute.func_defaults, + attribute.func_closure))) # Copy annotations, if any try: - attr[attrname]._dbus_annotations = ( - dict(attribute._dbus_annotations)) + attr[attrname]._dbus_annotations = dict( + attribute._dbus_annotations) except AttributeError: pass # Is this a D-Bus interface? @@ -1188,22 +1191,22 @@ # object. Decorate it to be a new D-Bus interface # with the alternate D-Bus interface name. Add it # to the class. - attr[attrname] = (dbus_interface_annotations - (alt_interface) - (types.FunctionType - (attribute.func_code, - attribute.func_globals, - attribute.func_name, - attribute.func_defaults, - attribute.func_closure))) + attr[attrname] = ( + dbus_interface_annotations(alt_interface) + (types.FunctionType(attribute.func_code, + attribute.func_globals, + attribute.func_name, + attribute.func_defaults, + attribute.func_closure))) if deprecate: # Deprecate all alternate interfaces iname="_AlternateDBusNames_interface_annotation{}" for interface_name in interface_names: + @dbus_interface_annotations(interface_name) def func(self): return { "org.freedesktop.DBus.Deprecated": - "true" } + "true" } # Find an unused name for aname in (iname.format(i) for i in itertools.count()): @@ -1214,13 +1217,14 @@ # Replace the class with a new subclass of it with # methods, signals, etc. as created above. cls = type(b"{}Alternate".format(cls.__name__), - (cls,), attr) + (cls, ), attr) return cls + return wrapper @alternate_dbus_interfaces({"se.recompile.Mandos": - "se.bsnet.fukt.Mandos"}) + "se.bsnet.fukt.Mandos"}) class ClientDBus(Client, DBusObjectWithProperties): """A Client class using D-Bus @@ -1230,7 +1234,7 @@ """ runtime_expansions = (Client.runtime_expansions - + ("dbus_object_path",)) + + ("dbus_object_path", )) _interface = "se.recompile.Mandos.Client" @@ -1244,14 +1248,15 @@ client_object_name = str(self.name).translate( {ord("."): ord("_"), ord("-"): ord("_")}) - self.dbus_object_path = (dbus.ObjectPath - ("/clients/" + client_object_name)) + self.dbus_object_path = dbus.ObjectPath( + "/clients/" + client_object_name) DBusObjectWithProperties.__init__(self, self.bus, self.dbus_object_path) - def notifychangeproperty(transform_func, - dbus_name, type_func=lambda x: x, - variant_level=1, invalidate_only=False, + def notifychangeproperty(transform_func, dbus_name, + type_func=lambda x: x, + variant_level=1, + invalidate_only=False, _interface=_interface): """ Modify a variable so that it's a property which announces its changes to DBus. @@ -1264,26 +1269,27 @@ variant_level: D-Bus variant level. Default: 1 """ attrname = "_{}".format(dbus_name) + def setter(self, value): if hasattr(self, "dbus_object_path"): if (not hasattr(self, attrname) or type_func(getattr(self, attrname, None)) != type_func(value)): if invalidate_only: - self.PropertiesChanged(_interface, - dbus.Dictionary(), - dbus.Array - ((dbus_name,))) + self.PropertiesChanged( + _interface, dbus.Dictionary(), + dbus.Array((dbus_name, ))) else: - dbus_value = transform_func(type_func(value), - variant_level - =variant_level) + dbus_value = transform_func( + type_func(value), + variant_level = variant_level) self.PropertyChanged(dbus.String(dbus_name), dbus_value) - self.PropertiesChanged(_interface, - dbus.Dictionary({ - dbus.String(dbus_name): - dbus_value }), dbus.Array()) + self.PropertiesChanged( + _interface, + dbus.Dictionary({ dbus.String(dbus_name): + dbus_value }), + dbus.Array()) setattr(self, attrname, value) return property(lambda self: getattr(self, attrname), setter) @@ -1295,9 +1301,9 @@ enabled = notifychangeproperty(dbus.Boolean, "Enabled") last_enabled = notifychangeproperty(datetime_to_dbus, "LastEnabled") - checker = notifychangeproperty(dbus.Boolean, "CheckerRunning", - type_func = lambda checker: - checker is not None) + checker = notifychangeproperty( + dbus.Boolean, "CheckerRunning", + type_func = lambda checker: checker is not None) last_checked_ok = notifychangeproperty(datetime_to_dbus, "LastCheckedOK") last_checker_status = notifychangeproperty(dbus.Int16, @@ -1306,26 +1312,22 @@ datetime_to_dbus, "LastApprovalRequest") approved_by_default = notifychangeproperty(dbus.Boolean, "ApprovedByDefault") - approval_delay = notifychangeproperty(dbus.UInt64, - "ApprovalDelay", - type_func = - lambda td: td.total_seconds() - * 1000) + approval_delay = notifychangeproperty( + dbus.UInt64, "ApprovalDelay", + type_func = lambda td: td.total_seconds() * 1000) approval_duration = notifychangeproperty( dbus.UInt64, "ApprovalDuration", type_func = lambda td: td.total_seconds() * 1000) host = notifychangeproperty(dbus.String, "Host") - timeout = notifychangeproperty(dbus.UInt64, "Timeout", - type_func = lambda td: - td.total_seconds() * 1000) + timeout = notifychangeproperty( + dbus.UInt64, "Timeout", + type_func = lambda td: td.total_seconds() * 1000) extended_timeout = notifychangeproperty( dbus.UInt64, "ExtendedTimeout", type_func = lambda td: td.total_seconds() * 1000) - interval = notifychangeproperty(dbus.UInt64, - "Interval", - type_func = - lambda td: td.total_seconds() - * 1000) + interval = notifychangeproperty( + dbus.UInt64, "Interval", + type_func = lambda td: td.total_seconds() * 1000) checker_command = notifychangeproperty(dbus.String, "Checker") secret = notifychangeproperty(dbus.ByteArray, "Secret", invalidate_only=True) @@ -1469,7 +1471,8 @@ return dbus.Boolean(bool(self.approvals_pending)) # ApprovedByDefault - property - @dbus_service_property(_interface, signature="b", + @dbus_service_property(_interface, + signature="b", access="readwrite") def ApprovedByDefault_dbus_property(self, value=None): if value is None: # get @@ -1477,7 +1480,8 @@ self.approved_by_default = bool(value) # ApprovalDelay - property - @dbus_service_property(_interface, signature="t", + @dbus_service_property(_interface, + signature="t", access="readwrite") def ApprovalDelay_dbus_property(self, value=None): if value is None: # get @@ -1486,7 +1490,8 @@ self.approval_delay = datetime.timedelta(0, 0, 0, value) # ApprovalDuration - property - @dbus_service_property(_interface, signature="t", + @dbus_service_property(_interface, + signature="t", access="readwrite") def ApprovalDuration_dbus_property(self, value=None): if value is None: # get @@ -1505,7 +1510,8 @@ return dbus.String(self.fingerprint) # Host - property - @dbus_service_property(_interface, signature="s", + @dbus_service_property(_interface, + signature="s", access="readwrite") def Host_dbus_property(self, value=None): if value is None: # get @@ -1523,7 +1529,8 @@ return datetime_to_dbus(self.last_enabled) # Enabled - property - @dbus_service_property(_interface, signature="b", + @dbus_service_property(_interface, + signature="b", access="readwrite") def Enabled_dbus_property(self, value=None): if value is None: # get @@ -1534,7 +1541,8 @@ self.disable() # LastCheckedOK - property - @dbus_service_property(_interface, signature="s", + @dbus_service_property(_interface, + signature="s", access="readwrite") def LastCheckedOK_dbus_property(self, value=None): if value is not None: @@ -1543,8 +1551,7 @@ return datetime_to_dbus(self.last_checked_ok) # LastCheckerStatus - property - @dbus_service_property(_interface, signature="n", - access="read") + @dbus_service_property(_interface, signature="n", access="read") def LastCheckerStatus_dbus_property(self): return dbus.Int16(self.last_checker_status) @@ -1559,7 +1566,8 @@ return datetime_to_dbus(self.last_approval_request) # Timeout - property - @dbus_service_property(_interface, signature="t", + @dbus_service_property(_interface, + signature="t", access="readwrite") def Timeout_dbus_property(self, value=None): if value is None: # get @@ -1578,13 +1586,13 @@ is None): return gobject.source_remove(self.disable_initiator_tag) - self.disable_initiator_tag = ( - gobject.timeout_add( - int((self.expires - now).total_seconds() - * 1000), self.disable)) + self.disable_initiator_tag = gobject.timeout_add( + int((self.expires - now).total_seconds() * 1000), + self.disable) # ExtendedTimeout - property - @dbus_service_property(_interface, signature="t", + @dbus_service_property(_interface, + signature="t", access="readwrite") def ExtendedTimeout_dbus_property(self, value=None): if value is None: # get @@ -1593,7 +1601,8 @@ self.extended_timeout = datetime.timedelta(0, 0, 0, value) # Interval - property - @dbus_service_property(_interface, signature="t", + @dbus_service_property(_interface, + signature="t", access="readwrite") def Interval_dbus_property(self, value=None): if value is None: # get @@ -1604,12 +1613,13 @@ if self.enabled: # Reschedule checker run gobject.source_remove(self.checker_initiator_tag) - self.checker_initiator_tag = (gobject.timeout_add - (value, self.start_checker)) - self.start_checker() # Start one now, too + self.checker_initiator_tag = gobject.timeout_add( + value, self.start_checker) + self.start_checker() # Start one now, too # Checker - property - @dbus_service_property(_interface, signature="s", + @dbus_service_property(_interface, + signature="s", access="readwrite") def Checker_dbus_property(self, value=None): if value is None: # get @@ -1617,7 +1627,8 @@ self.checker_command = str(value) # CheckerRunning - property - @dbus_service_property(_interface, signature="b", + @dbus_service_property(_interface, + signature="b", access="readwrite") def CheckerRunning_dbus_property(self, value=None): if value is None: # get @@ -1633,8 +1644,10 @@ return self.dbus_object_path # is already a dbus.ObjectPath # Secret = property - @dbus_service_property(_interface, signature="ay", - access="write", byte_arrays=True) + @dbus_service_property(_interface, + signature="ay", + access="write", + byte_arrays=True) def Secret_dbus_property(self, value): self.secret = bytes(value) @@ -1656,9 +1669,11 @@ if data[0] == 'data': return data[1] if data[0] == 'function': + def func(*args, **kwargs): self._pipe.send(('funcall', name, args, kwargs)) return self._pipe.recv()[1] + return func def __setattr__(self, name, value): @@ -1680,10 +1695,8 @@ logger.debug("Pipe FD: %d", self.server.child_pipe.fileno()) - session = (gnutls.connection - .ClientSession(self.request, - gnutls.connection - .X509Credentials())) + session = gnutls.connection.ClientSession( + self.request, gnutls.connection .X509Credentials()) # Note: gnutls.connection.X509Credentials is really a # generic GnuTLS certificate credentials object so long as @@ -1698,9 +1711,8 @@ priority = self.server.gnutls_priority if priority is None: priority = "NORMAL" - (gnutls.library.functions - .gnutls_priority_set_direct(session._c_object, - priority, None)) + gnutls.library.functions.gnutls_priority_set_direct( + session._c_object, priority, None) # Start communication using the Mandos protocol # Get protocol number @@ -1726,8 +1738,8 @@ approval_required = False try: try: - fpr = self.fingerprint(self.peer_certificate - (session)) + fpr = self.fingerprint( + self.peer_certificate(session)) except (TypeError, gnutls.errors.GNUTLSError) as error: logger.warning("Bad certificate: %s", error) @@ -1748,7 +1760,7 @@ while True: if not client.enabled: logger.info("Client %s is disabled", - client.name) + client.name) if self.server.use_dbus: # Emit D-Bus signal client.Rejected("Disabled") @@ -1801,9 +1813,9 @@ logger.warning("gnutls send failed", exc_info=error) return - logger.debug("Sent: %d, remaining: %d", - sent, len(client.secret) - - (sent_size + sent)) + logger.debug("Sent: %d, remaining: %d", sent, + len(client.secret) - (sent_size + + sent)) sent_size += sent logger.info("Sending secret to %s", client.name) @@ -1826,8 +1838,8 @@ def peer_certificate(session): "Return the peer's OpenPGP certificate as a bytestring" # If not an OpenPGP certificate... - if (gnutls.library.functions - .gnutls_certificate_type_get(session._c_object) + if (gnutls.library.functions.gnutls_certificate_type_get( + session._c_object) != gnutls.library.constants.GNUTLS_CRT_OPENPGP): # ...do the normal thing return session.peer_certificate @@ -1847,36 +1859,32 @@ def fingerprint(openpgp): "Convert an OpenPGP bytestring to a hexdigit fingerprint" # New GnuTLS "datum" with the OpenPGP public key - datum = (gnutls.library.types - .gnutls_datum_t(ctypes.cast(ctypes.c_char_p(openpgp), - ctypes.POINTER - (ctypes.c_ubyte)), - ctypes.c_uint(len(openpgp)))) + datum = gnutls.library.types.gnutls_datum_t( + ctypes.cast(ctypes.c_char_p(openpgp), + ctypes.POINTER(ctypes.c_ubyte)), + ctypes.c_uint(len(openpgp))) # New empty GnuTLS certificate crt = gnutls.library.types.gnutls_openpgp_crt_t() - (gnutls.library.functions - .gnutls_openpgp_crt_init(ctypes.byref(crt))) + gnutls.library.functions.gnutls_openpgp_crt_init( + ctypes.byref(crt)) # Import the OpenPGP public key into the certificate - (gnutls.library.functions - .gnutls_openpgp_crt_import(crt, ctypes.byref(datum), - gnutls.library.constants - .GNUTLS_OPENPGP_FMT_RAW)) + gnutls.library.functions.gnutls_openpgp_crt_import( + crt, ctypes.byref(datum), + gnutls.library.constants.GNUTLS_OPENPGP_FMT_RAW) # Verify the self signature in the key crtverify = ctypes.c_uint() - (gnutls.library.functions - .gnutls_openpgp_crt_verify_self(crt, 0, - ctypes.byref(crtverify))) + gnutls.library.functions.gnutls_openpgp_crt_verify_self( + crt, 0, ctypes.byref(crtverify)) if crtverify.value != 0: gnutls.library.functions.gnutls_openpgp_crt_deinit(crt) - raise (gnutls.errors.CertificateSecurityError - ("Verify failed")) + raise gnutls.errors.CertificateSecurityError( + "Verify failed") # New buffer for the fingerprint buf = ctypes.create_string_buffer(20) buf_len = ctypes.c_size_t() # Get the fingerprint from the certificate into the buffer - (gnutls.library.functions - .gnutls_openpgp_crt_get_fingerprint(crt, ctypes.byref(buf), - ctypes.byref(buf_len))) + gnutls.library.functions.gnutls_openpgp_crt_get_fingerprint( + crt, ctypes.byref(buf), ctypes.byref(buf_len)) # Deinit the certificate gnutls.library.functions.gnutls_openpgp_crt_deinit(crt) # Convert the buffer to a Python bytestring @@ -1888,6 +1896,7 @@ class MultiprocessingMixIn(object): """Like socketserver.ThreadingMixIn, but with multiprocessing""" + def sub_process_main(self, request, address): try: self.finish_request(request, address) @@ -1905,6 +1914,7 @@ class MultiprocessingMixInWithPipe(MultiprocessingMixIn, object): """ adds a pipe to the MixIn """ + def process_request(self, request, client_address): """Overrides and wraps the original process_request(). @@ -1931,8 +1941,11 @@ interface: None or a network interface name (string) use_ipv6: Boolean; to use IPv6 or not """ + def __init__(self, server_address, RequestHandlerClass, - interface=None, use_ipv6=True, socketfd=None): + interface=None, + use_ipv6=True, + socketfd=None): """If socketfd is set, use that file descriptor instead of creating a new one with socket.socket(). """ @@ -1979,10 +1992,9 @@ self.interface) else: try: - self.socket.setsockopt(socket.SOL_SOCKET, - SO_BINDTODEVICE, - (self.interface + "\0") - .encode("utf-8")) + self.socket.setsockopt( + socket.SOL_SOCKET, SO_BINDTODEVICE, + (self.interface + "\0").encode("utf-8")) except socket.error as error: if error.errno == errno.EPERM: logger.error("No permission to bind to" @@ -2006,8 +2018,7 @@ self.server_address = (any_address, self.server_address[1]) elif not self.server_address[1]: - self.server_address = (self.server_address[0], - 0) + self.server_address = (self.server_address[0], 0) # if self.interface: # self.server_address = (self.server_address[0], # 0, # port @@ -2027,9 +2038,14 @@ Assumes a gobject.MainLoop event loop. """ + def __init__(self, server_address, RequestHandlerClass, - interface=None, use_ipv6=True, clients=None, - gnutls_priority=None, use_dbus=True, socketfd=None): + interface=None, + use_ipv6=True, + clients=None, + gnutls_priority=None, + use_dbus=True, + socketfd=None): self.enabled = False self.clients = clients if self.clients is None: @@ -2041,6 +2057,7 @@ interface = interface, use_ipv6 = use_ipv6, socketfd = socketfd) + def server_activate(self): if self.enabled: return socketserver.TCPServer.server_activate(self) @@ -2050,15 +2067,17 @@ def add_pipe(self, parent_pipe, proc): # Call "handle_ipc" for both data and EOF events - gobject.io_add_watch(parent_pipe.fileno(), - gobject.IO_IN | gobject.IO_HUP, - functools.partial(self.handle_ipc, - parent_pipe = - parent_pipe, - proc = proc)) + gobject.io_add_watch( + parent_pipe.fileno(), + gobject.IO_IN | gobject.IO_HUP, + functools.partial(self.handle_ipc, + parent_pipe = parent_pipe, + proc = proc)) - def handle_ipc(self, source, condition, parent_pipe=None, - proc = None, client_object=None): + def handle_ipc(self, source, condition, + parent_pipe=None, + proc = None, + client_object=None): # error, or the other end of multiprocessing.Pipe has closed if condition & (gobject.IO_ERR | gobject.IO_HUP): # Wait for other process to exit @@ -2087,14 +2106,13 @@ parent_pipe.send(False) return False - gobject.io_add_watch(parent_pipe.fileno(), - gobject.IO_IN | gobject.IO_HUP, - functools.partial(self.handle_ipc, - parent_pipe = - parent_pipe, - proc = proc, - client_object = - client)) + gobject.io_add_watch( + parent_pipe.fileno(), + gobject.IO_IN | gobject.IO_HUP, + functools.partial(self.handle_ipc, + parent_pipe = parent_pipe, + proc = proc, + client_object = client)) parent_pipe.send(True) # remove the old hook in favor of the new above hook on # same fileno @@ -2106,15 +2124,15 @@ parent_pipe.send(('data', getattr(client_object, funcname)(*args, - **kwargs))) + **kwargs))) if command == 'getattr': attrname = request[1] if callable(client_object.__getattribute__(attrname)): - parent_pipe.send(('function',)) + parent_pipe.send(('function', )) else: - parent_pipe.send(('data', client_object - .__getattribute__(attrname))) + parent_pipe.send(( + 'data', client_object.__getattribute__(attrname))) if command == 'setattr': attrname = request[1] @@ -2160,12 +2178,17 @@ # None "followers")) # Tokens valid after # this token + Token = collections.namedtuple("Token", ( + "regexp", # To match token; if "value" is not None, must have + # a "group" containing digits + "value", # datetime.timedelta or None + "followers")) # Tokens valid after this token # RFC 3339 "duration" tokens, syntax, and semantics; taken from # the "duration" ABNF definition in RFC 3339, Appendix A. token_end = Token(re.compile(r"$"), None, frozenset()) token_second = Token(re.compile(r"(\d+)S"), datetime.timedelta(seconds=1), - frozenset((token_end,))) + frozenset((token_end, ))) token_minute = Token(re.compile(r"(\d+)M"), datetime.timedelta(minutes=1), frozenset((token_second, token_end))) @@ -2187,7 +2210,7 @@ frozenset((token_month, token_end))) token_week = Token(re.compile(r"(\d+)W"), datetime.timedelta(weeks=1), - frozenset((token_end,))) + frozenset((token_end, ))) token_duration = Token(re.compile(r"P"), None, frozenset((token_year, token_month, token_day, token_time, @@ -2261,8 +2284,7 @@ elif suffix == "w": delta = datetime.timedelta(0, 0, 0, 0, 0, 0, value) else: - raise ValueError("Unknown suffix {!r}" - .format(suffix)) + raise ValueError("Unknown suffix {!r}".format(suffix)) except IndexError as e: raise ValueError(*(e.args)) timevalue += delta @@ -2284,7 +2306,8 @@ # Close all standard open file descriptors null = os.open(os.devnull, os.O_NOCTTY | os.O_RDWR) if not stat.S_ISCHR(os.fstat(null).st_mode): - raise OSError(errno.ENODEV, "{} not a character device" + raise OSError(errno.ENODEV, + "{} not a character device" .format(os.devnull)) os.dup2(null, sys.stdin.fileno()) os.dup2(null, sys.stdout.fileno()) @@ -2367,13 +2390,12 @@ "statedir": "/var/lib/mandos", "foreground": "False", "zeroconf": "True", - } + } # Parse config file for server-global settings server_config = configparser.SafeConfigParser(server_defaults) del server_defaults - server_config.read(os.path.join(options.configdir, - "mandos.conf")) + server_config.read(os.path.join(options.configdir, "mandos.conf")) # Convert the SafeConfigParser object to a dict server_settings = server_config.defaults() # Use the appropriate methods on the non-string config options @@ -2397,9 +2419,9 @@ # Override the settings from the config file with command line # options, if set. for option in ("interface", "address", "port", "debug", - "priority", "servicename", "configdir", - "use_dbus", "use_ipv6", "debuglevel", "restore", - "statedir", "socket", "foreground", "zeroconf"): + "priority", "servicename", "configdir", "use_dbus", + "use_ipv6", "debuglevel", "restore", "statedir", + "socket", "foreground", "zeroconf"): value = getattr(options, option) if value is not None: server_settings[option] = value @@ -2420,11 +2442,10 @@ ################################################################## - if (not server_settings["zeroconf"] and - not (server_settings["port"] - or server_settings["socket"] != "")): - parser.error("Needs port or socket to work without" - " Zeroconf") + if (not server_settings["zeroconf"] + and not (server_settings["port"] + or server_settings["socket"] != "")): + parser.error("Needs port or socket to work without Zeroconf") # For convenience debug = server_settings["debug"] @@ -2446,11 +2467,10 @@ initlogger(debug, level) if server_settings["servicename"] != "Mandos": - syslogger.setFormatter(logging.Formatter - ('Mandos ({}) [%(process)d]:' - ' %(levelname)s: %(message)s' - .format(server_settings - ["servicename"]))) + syslogger.setFormatter( + logging.Formatter('Mandos ({}) [%(process)d]:' + ' %(levelname)s: %(message)s'.format( + server_settings["servicename"]))) # Parse config file with clients client_config = configparser.SafeConfigParser(Client @@ -2464,16 +2484,14 @@ socketfd = None if server_settings["socket"] != "": socketfd = server_settings["socket"] - tcp_server = MandosServer((server_settings["address"], - server_settings["port"]), - ClientHandler, - interface=(server_settings["interface"] - or None), - use_ipv6=use_ipv6, - gnutls_priority= - server_settings["priority"], - use_dbus=use_dbus, - socketfd=socketfd) + tcp_server = MandosServer( + (server_settings["address"], server_settings["port"]), + ClientHandler, + interface=(server_settings["interface"] or None), + use_ipv6=use_ipv6, + gnutls_priority=server_settings["priority"], + use_dbus=use_dbus, + socketfd=socketfd) if not foreground: pidfilename = "/run/mandos.pid" if not os.path.isdir("/run/."): @@ -2513,8 +2531,8 @@ def debug_gnutls(level, string): logger.debug("GnuTLS: %s", string[:-1]) - (gnutls.library.functions - .gnutls_global_set_log_function(debug_gnutls)) + gnutls.library.functions.gnutls_global_set_log_function( + debug_gnutls) # Redirect stdin so all checkers get /dev/null null = os.open(os.devnull, os.O_NOCTTY | os.O_RDWR) @@ -2540,10 +2558,11 @@ if use_dbus: try: bus_name = dbus.service.BusName("se.recompile.Mandos", - bus, do_not_queue=True) - old_bus_name = (dbus.service.BusName - ("se.bsnet.fukt.Mandos", bus, - do_not_queue=True)) + bus, + do_not_queue=True) + old_bus_name = dbus.service.BusName( + "se.bsnet.fukt.Mandos", bus, + do_not_queue=True) except dbus.exceptions.NameExistsException as e: logger.error("Disabling D-Bus:", exc_info=e) use_dbus = False @@ -2551,14 +2570,14 @@ tcp_server.use_dbus = False if zeroconf: protocol = avahi.PROTO_INET6 if use_ipv6 else avahi.PROTO_INET - service = AvahiServiceToSyslog(name = - server_settings["servicename"], - servicetype = "_mandos._tcp", - protocol = protocol, bus = bus) + service = AvahiServiceToSyslog( + name = server_settings["servicename"], + servicetype = "_mandos._tcp", + protocol = protocol, + bus = bus) if server_settings["interface"]: - service.interface = (if_nametoindex - (server_settings["interface"] - .encode("utf-8"))) + service.interface = if_nametoindex( + server_settings["interface"].encode("utf-8")) global multiprocessing_manager multiprocessing_manager = multiprocessing.Manager() @@ -2583,20 +2602,21 @@ if server_settings["restore"]: try: with open(stored_state_path, "rb") as stored_state: - clients_data, old_client_settings = (pickle.load - (stored_state)) + clients_data, old_client_settings = pickle.load( + stored_state) os.remove(stored_state_path) except IOError as e: if e.errno == errno.ENOENT: - logger.warning("Could not load persistent state: {}" - .format(os.strerror(e.errno))) + logger.warning("Could not load persistent state:" + " {}".format(os.strerror(e.errno))) else: logger.critical("Could not load persistent state:", exc_info=e) raise except EOFError as e: logger.warning("Could not load persistent state: " - "EOFError:", exc_info=e) + "EOFError:", + exc_info=e) with PGPEngine() as pgp: for client_name, client in clients_data.items(): @@ -2614,9 +2634,9 @@ # For each value in new config, check if it # differs from the old config value (Except for # the "secret" attribute) - if (name != "secret" and - value != old_client_settings[client_name] - [name]): + if (name != "secret" + and (value != + old_client_settings[client_name][name])): client[name] = value except KeyError: pass @@ -2631,34 +2651,34 @@ if not client["last_checked_ok"]: logger.warning( "disabling client {} - Client never " - "performed a successful checker" - .format(client_name)) + "performed a successful checker".format( + client_name)) client["enabled"] = False elif client["last_checker_status"] != 0: logger.warning( "disabling client {} - Client last" - " checker failed with error code {}" - .format(client_name, - client["last_checker_status"])) + " checker failed with error code" + " {}".format( + client_name, + client["last_checker_status"])) client["enabled"] = False else: - client["expires"] = (datetime.datetime - .utcnow() - + client["timeout"]) + client["expires"] = ( + datetime.datetime.utcnow() + + client["timeout"]) logger.debug("Last checker succeeded," - " keeping {} enabled" - .format(client_name)) + " keeping {} enabled".format( + client_name)) try: - client["secret"] = ( - pgp.decrypt(client["encrypted_secret"], - client_settings[client_name] - ["secret"])) + client["secret"] = pgp.decrypt( + client["encrypted_secret"], + client_settings[client_name]["secret"]) except PGPError: # If decryption fails, we use secret from new settings - logger.debug("Failed to decrypt {} old secret" - .format(client_name)) - client["secret"] = ( - client_settings[client_name]["secret"]) + logger.debug("Failed to decrypt {} old secret".format( + client_name)) + client["secret"] = (client_settings[client_name] + ["secret"]) # Add/remove clients based on new changes made to config for client_name in (set(old_client_settings) @@ -2671,7 +2691,8 @@ # Create all client objects for client_name, client in clients_data.items(): tcp_server.clients[client_name] = client_class( - name = client_name, settings = client, + name = client_name, + settings = client, server_settings = server_settings) if not tcp_server.clients: @@ -2693,19 +2714,22 @@ signal.signal(signal.SIGTERM, lambda signum, frame: sys.exit()) if use_dbus: - @alternate_dbus_interfaces({"se.recompile.Mandos": - "se.bsnet.fukt.Mandos"}) + + @alternate_dbus_interfaces( + { "se.recompile.Mandos": "se.bsnet.fukt.Mandos" }) class MandosDBusService(DBusObjectWithProperties): """A D-Bus proxy object""" + def __init__(self): dbus.service.Object.__init__(self, bus, "/") + _interface = "se.recompile.Mandos" @dbus_interface_annotations(_interface) def _foo(self): - return { "org.freedesktop.DBus.Property" - ".EmitsChangedSignal": - "false"} + return { + "org.freedesktop.DBus.Property.EmitsChangedSignal": + "false" } @dbus.service.signal(_interface, signature="o") def ClientAdded(self, objpath): @@ -2725,8 +2749,7 @@ @dbus.service.method(_interface, out_signature="ao") def GetAllClients(self): "D-Bus method" - return dbus.Array(c.dbus_object_path - for c in + return dbus.Array(c.dbus_object_path for c in tcp_server.clients.itervalues()) @dbus.service.method(_interface, @@ -2781,8 +2804,8 @@ # + secret. exclude = { "bus", "changedstate", "secret", "checker", "server_settings" } - for name, typ in (inspect.getmembers - (dbus.service.Object)): + for name, typ in inspect.getmembers(dbus.service + .Object): exclude.add(name) client_dict["encrypted_secret"] = (client @@ -2795,12 +2818,14 @@ del client_settings[client.name]["secret"] try: - with (tempfile.NamedTemporaryFile - (mode='wb', suffix=".pickle", prefix='clients-', - dir=os.path.dirname(stored_state_path), - delete=False)) as stored_state: + with tempfile.NamedTemporaryFile( + mode='wb', + suffix=".pickle", + prefix='clients-', + dir=os.path.dirname(stored_state_path), + delete=False) as stored_state: pickle.dump((clients, client_settings), stored_state) - tempname=stored_state.name + tempname = stored_state.name os.rename(tempname, stored_state_path) except (IOError, OSError) as e: if not debug: @@ -2825,9 +2850,8 @@ client.disable(quiet=True) if use_dbus: # Emit D-Bus signal - mandos_dbus_service.ClientRemoved(client - .dbus_object_path, - client.name) + mandos_dbus_service.ClientRemoved( + client.dbus_object_path, client.name) client_settings.clear() atexit.register(cleanup) @@ -2886,5 +2910,6 @@ # Must run before the D-Bus bus name gets deregistered cleanup() + if __name__ == '__main__': main()