983
983
raise DBusPropertyNotFound("{}:{}.{}".format(
984
984
self.dbus_object_path, interface_name, property_name))
987
def _get_all_interface_names(cls):
988
"""Get a sequence of all interfaces supported by an object"""
989
return (name for name in set(getattr(getattr(x, attr),
990
"_dbus_interface", None)
991
for x in (inspect.getmro(cls))
995
986
@dbus.service.method(dbus.PROPERTIES_IFACE,
996
987
in_signature="ss",
997
988
out_signature="v")
1127
1118
exc_info=error)
1128
1119
return xmlstring
1131
dbus.OBJECT_MANAGER_IFACE
1132
except AttributeError:
1133
dbus.OBJECT_MANAGER_IFACE = "org.freedesktop.DBus.ObjectManager"
1135
class DBusObjectWithObjectManager(DBusObjectWithAnnotations):
1136
"""A D-Bus object with an ObjectManager.
1138
Classes inheriting from this exposes the standard
1139
GetManagedObjects call and the InterfacesAdded and
1140
InterfacesRemoved signals on the standard
1141
"org.freedesktop.DBus.ObjectManager" interface.
1143
Note: No signals are sent automatically; they must be sent
1146
@dbus.service.method(dbus.OBJECT_MANAGER_IFACE,
1147
out_signature = "a{oa{sa{sv}}}")
1148
def GetManagedObjects(self):
1149
"""This function must be overridden"""
1150
raise NotImplementedError()
1152
@dbus.service.signal(dbus.OBJECT_MANAGER_IFACE,
1153
signature = "oa{sa{sv}}")
1154
def InterfacesAdded(self, object_path, interfaces_and_properties):
1157
@dbus.service.signal(dbus.OBJECT_MANAGER_IFACE, signature = "oas")
1158
def InterfacesRemoved(self, object_path, interfaces):
1161
@dbus.service.method(dbus.INTROSPECTABLE_IFACE,
1162
out_signature = "s",
1163
path_keyword = 'object_path',
1164
connection_keyword = 'connection')
1165
def Introspect(self, object_path, connection):
1166
"""Overloading of standard D-Bus method.
1168
Override return argument name of GetManagedObjects to be
1169
"objpath_interfaces_and_properties"
1171
xmlstring = DBusObjectWithAnnotations.Introspect(self,
1175
document = xml.dom.minidom.parseString(xmlstring)
1177
for if_tag in document.getElementsByTagName("interface"):
1178
# Fix argument name for the GetManagedObjects method
1179
if (if_tag.getAttribute("name")
1180
== dbus.OBJECT_MANAGER_IFACE):
1181
for cn in if_tag.getElementsByTagName("method"):
1182
if (cn.getAttribute("name")
1183
== "GetManagedObjects"):
1184
for arg in cn.getElementsByTagName("arg"):
1185
if (arg.getAttribute("direction")
1189
"objpath_interfaces"
1191
xmlstring = document.toxml("utf-8")
1193
except (AttributeError, xml.dom.DOMException,
1194
xml.parsers.expat.ExpatError) as error:
1195
logger.error("Failed to override Introspection method",
1199
1122
def datetime_to_dbus(dt, variant_level=0):
1200
1123
"""Convert a UTC datetime.datetime() to a D-Bus type."""
1291
1214
func1 and func2 to the "call_both" function
1292
1215
outside of its arguments"""
1294
@functools.wraps(func2)
1295
1217
def call_both(*args, **kwargs):
1296
1218
"""This function will emit two D-Bus
1297
1219
signals by calling func1 and func2"""
1298
1220
func1(*args, **kwargs)
1299
1221
func2(*args, **kwargs)
1300
# Make wrapper function look like a D-Bus signal
1301
for name, attr in inspect.getmembers(func2):
1302
if name.startswith("_dbus_"):
1303
setattr(call_both, name, attr)
1305
1223
return call_both
1306
1224
# Create the "call_both" function and add it to
2916
@dbus_annotations({"org.freedesktop.DBus.Deprecated":
2918
2834
@dbus.service.signal(_interface, signature="os")
2919
2835
def ClientRemoved(self, objpath, name):
2923
@dbus_annotations({"org.freedesktop.DBus.Deprecated":
2925
2839
@dbus.service.method(_interface, out_signature="ao")
2926
2840
def GetAllClients(self):
2928
2842
return dbus.Array(c.dbus_object_path for c in
2929
2843
tcp_server.clients.itervalues())
2931
@dbus_annotations({"org.freedesktop.DBus.Deprecated":
2933
2845
@dbus.service.method(_interface,
2934
2846
out_signature="a{oa{sv}}")
2935
2847
def GetAllClientsWithProperties(self):
2937
2849
return dbus.Dictionary(
2938
{ c.dbus_object_path: c.GetAll(
2939
"se.recompile.Mandos.Client")
2850
{ c.dbus_object_path: c.GetAll("")
2940
2851
for c in tcp_server.clients.itervalues() },
2941
2852
signature="oa{sv}")
2947
2858
if c.dbus_object_path == object_path:
2948
2859
del tcp_server.clients[c.name]
2949
2860
c.remove_from_connection()
2950
# Don't signal the disabling
2861
# Don't signal anything except ClientRemoved
2951
2862
c.disable(quiet=True)
2952
# Emit D-Bus signal for removal
2953
self.client_removed_signal(c)
2864
self.ClientRemoved(object_path, c.name)
2955
2866
raise KeyError(object_path)
2959
@dbus.service.method(dbus.OBJECT_MANAGER_IFACE,
2960
out_signature = "a{oa{sa{sv}}}")
2961
def GetManagedObjects(self):
2963
return dbus.Dictionary(
2964
{ client.dbus_object_path:
2966
{ interface: client.GetAll(interface)
2968
client._get_all_interface_names()})
2969
for client in tcp_server.clients.values()})
2971
def client_added_signal(self, client):
2972
"""Send the new standard signal and the old signal"""
2974
# New standard signal
2975
self.InterfacesAdded(
2976
client.dbus_object_path,
2978
{ interface: client.GetAll(interface)
2980
client._get_all_interface_names()}))
2982
self.ClientAdded(client.dbus_object_path)
2984
def client_removed_signal(self, client):
2985
"""Send the new standard signal and the old signal"""
2987
# New standard signal
2988
self.InterfacesRemoved(
2989
client.dbus_object_path,
2990
client._get_all_interface_names())
2992
self.ClientRemoved(client.dbus_object_path,
2995
2870
mandos_dbus_service = MandosDBusService()
3061
2936
name, client = tcp_server.clients.popitem()
3063
2938
client.remove_from_connection()
3064
# Don't signal the disabling
2939
# Don't signal anything except ClientRemoved
3065
2940
client.disable(quiet=True)
3066
# Emit D-Bus signal for removal
3067
mandos_dbus_service.client_removed_signal(client)
2943
mandos_dbus_service.ClientRemoved(
2944
client.dbus_object_path, client.name)
3068
2945
client_settings.clear()
3070
2947
atexit.register(cleanup)
3072
2949
for client in tcp_server.clients.itervalues():
3074
# Emit D-Bus signal for adding
3075
mandos_dbus_service.client_added_signal(client)
2952
mandos_dbus_service.ClientAdded(client.dbus_object_path)
3076
2953
# Need to initiate checking of clients
3077
2954
if client.enabled:
3078
2955
client.init_checker()