core (memory/encryption): new encryptionNamespaceGet and encryptionTrustUIGet methods:
- encryptionNamespaceGet retrieves algorithm namespace from its short name - encryptionTrustUIGet retrieves trust mangement XMLUI from encryption plugin - new markAsUntrusted internal helper method, to add untrusted flag to message data
This commit is contained in:
parent
93a73aec45
commit
24468a9138
6 changed files with 174 additions and 41 deletions
|
|
@ -60,7 +60,7 @@ category=core
|
|||
sig_in=sss
|
||||
doc=A message encryption session has been started
|
||||
doc_param_0=to_jid: JID of the recipient (bare jid if it's encrypted for all devices)
|
||||
doc_param_1=encryption_data: [JSON_OBJ] data of the encryption algorithm used, encoded as a json object.
|
||||
doc_param_1=encryption_data: (JSON_OBJ) data of the encryption algorithm used, encoded as a json object.
|
||||
it always has the following keys:
|
||||
- name: human readable name of the algorithm
|
||||
- namespace: namespace of the encryption plugin
|
||||
|
|
@ -445,8 +445,8 @@ param_2_default=False
|
|||
param_3_default="@NONE@"
|
||||
doc=Start an encryption session
|
||||
doc_param_0=to_jid: JID of the recipient (bare jid if it must be encrypted for all devices)
|
||||
doc_param_1=encryption_ns: Namespace of the encryption algorithm to use
|
||||
doc_param_2=replace: If True and an encryption session already exists, it will be replaced by this one
|
||||
doc_param_1=namespace: namespace of the encryption algorithm to use
|
||||
doc_param_2=replace: if True and an encryption session already exists, it will be replaced by this one
|
||||
else a ConflictError will be raised
|
||||
doc_param_3=%(doc_profile_key)s
|
||||
|
||||
|
|
@ -455,7 +455,7 @@ type=method
|
|||
category=core
|
||||
sig_in=ss
|
||||
sig_out=
|
||||
doc=Start an encryption session
|
||||
doc=Stop an encryption session
|
||||
doc_param_0=to_jid: JID of the recipient (full jid if encryption must be stopped for one device only)
|
||||
doc_param_1=%(doc_profile_key)s
|
||||
|
||||
|
|
@ -467,13 +467,20 @@ sig_out=s
|
|||
doc=Retrieve encryption data for a given entity
|
||||
doc_param_0=to_jid: bare JID of the recipient
|
||||
doc_param_1=%(doc_profile_key)s
|
||||
doc_return=[JSON_OBJ] empty string if session is unencrypted, else a json encoded objects.
|
||||
doc_return=(JSON_OBJ) empty string if session is unencrypted, else a json encoded objects.
|
||||
In case of dict, following keys are always present:
|
||||
- name: human readable name of the encryption algorithm
|
||||
- namespace: namespace of the plugin
|
||||
following key can be present if suitable:
|
||||
- directed_devices: list or resource where session is encrypted
|
||||
|
||||
[encryptionNamespaceGet]
|
||||
type=method
|
||||
category=core
|
||||
sig_in=s
|
||||
sig_out=s
|
||||
doc=Get algorithm namespace from its name
|
||||
|
||||
[encryptionPluginsGet]
|
||||
type=method
|
||||
category=core
|
||||
|
|
@ -481,6 +488,18 @@ sig_in=
|
|||
sig_out=aa{ss}
|
||||
doc=Retrieve registered plugins for encryption
|
||||
|
||||
[encryptionTrustUIGet]
|
||||
async=
|
||||
type=method
|
||||
category=core
|
||||
sig_in=sss
|
||||
sig_out=s
|
||||
doc=Get XMLUI to manage trust for given encryption algorithm
|
||||
doc_param_0=to_jid: bare JID of entity to manage
|
||||
doc_param_0=namespace: namespace of the algorithm to manage
|
||||
doc_param_2=%(doc_profile_key)s
|
||||
doc_return=(XMLUI) UI of the trust management
|
||||
|
||||
[setPresence]
|
||||
type=method
|
||||
category=core
|
||||
|
|
|
|||
|
|
@ -271,12 +271,24 @@ class DbusObject(dbus.service.Object):
|
|||
def disconnect(self, profile_key="@DEFAULT@", callback=None, errback=None):
|
||||
return self._callback("disconnect", unicode(profile_key), callback=callback, errback=errback)
|
||||
|
||||
@dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
|
||||
in_signature='s', out_signature='s',
|
||||
async_callbacks=None)
|
||||
def encryptionNamespaceGet(self, arg_0):
|
||||
return self._callback("encryptionNamespaceGet", unicode(arg_0))
|
||||
|
||||
@dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
|
||||
in_signature='', out_signature='aa{ss}',
|
||||
async_callbacks=None)
|
||||
def encryptionPluginsGet(self, ):
|
||||
return self._callback("encryptionPluginsGet", )
|
||||
|
||||
@dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
|
||||
in_signature='sss', out_signature='s',
|
||||
async_callbacks=('callback', 'errback'))
|
||||
def encryptionTrustUIGet(self, namespace, arg_1, profile_key, callback=None, errback=None):
|
||||
return self._callback("encryptionTrustUIGet", unicode(namespace), unicode(arg_1), unicode(profile_key), callback=callback, errback=errback)
|
||||
|
||||
@dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
|
||||
in_signature='ss', out_signature='s',
|
||||
async_callbacks=None)
|
||||
|
|
@ -412,8 +424,8 @@ class DbusObject(dbus.service.Object):
|
|||
@dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
|
||||
in_signature='ssbs', out_signature='',
|
||||
async_callbacks=None)
|
||||
def messageEncryptionStart(self, to_jid, encryption_ns='', replace=False, profile_key="@NONE@"):
|
||||
return self._callback("messageEncryptionStart", unicode(to_jid), unicode(encryption_ns), replace, unicode(profile_key))
|
||||
def messageEncryptionStart(self, to_jid, namespace='', replace=False, profile_key="@NONE@"):
|
||||
return self._callback("messageEncryptionStart", unicode(to_jid), unicode(namespace), replace, unicode(profile_key))
|
||||
|
||||
@dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
|
||||
in_signature='ss', out_signature='',
|
||||
|
|
|
|||
|
|
@ -122,7 +122,10 @@ class SAT(service.Service):
|
|||
self._messageEncryptionStop)
|
||||
self.bridge.register_method("messageEncryptionGet",
|
||||
self._messageEncryptionGet)
|
||||
self.bridge.register_method("encryptionNamespaceGet",
|
||||
self._encryptionNamespaceGet)
|
||||
self.bridge.register_method("encryptionPluginsGet", self._encryptionPluginsGet)
|
||||
self.bridge.register_method("encryptionTrustUIGet", self._encryptionTrustUIGet)
|
||||
self.bridge.register_method("getConfig", self._getConfig)
|
||||
self.bridge.register_method("setParam", self.setParam)
|
||||
self.bridge.register_method("getParamA", self.memory.getStringParamA)
|
||||
|
|
@ -670,6 +673,26 @@ class SAT(service.Service):
|
|||
def registerEncryptionPlugin(self, *args, **kwargs):
|
||||
return encryption.EncryptionHandler.registerPlugin(*args, **kwargs)
|
||||
|
||||
def _messageEncryptionStart(self, to_jid_s, namespace, replace=False,
|
||||
profile_key=C.PROF_KEY_NONE):
|
||||
client = self.getClient(profile_key)
|
||||
to_jid = jid.JID(to_jid_s)
|
||||
return client.encryption.start(to_jid, namespace or None, replace)
|
||||
|
||||
def _messageEncryptionStop(self, to_jid_s, profile_key=C.PROF_KEY_NONE):
|
||||
client = self.getClient(profile_key)
|
||||
to_jid = jid.JID(to_jid_s)
|
||||
return client.encryption.stop(to_jid)
|
||||
|
||||
def _messageEncryptionGet(self, to_jid_s, profile_key=C.PROF_KEY_NONE):
|
||||
client = self.getClient(profile_key)
|
||||
to_jid = jid.JID(to_jid_s)
|
||||
session_data = client.encryption.getSession(to_jid)
|
||||
return client.encryption.getBridgeData(session_data)
|
||||
|
||||
def _encryptionNamespaceGet(self, name):
|
||||
return encryption.EncryptionHandler.getNSFromName(name)
|
||||
|
||||
def _encryptionPluginsGet(self):
|
||||
plugins = encryption.EncryptionHandler.getPlugins()
|
||||
ret = []
|
||||
|
|
@ -681,6 +704,13 @@ class SAT(service.Service):
|
|||
})
|
||||
return ret
|
||||
|
||||
def _encryptionTrustUIGet(self, to_jid_s, namespace, profile_key):
|
||||
client = self.getClient(profile_key)
|
||||
to_jid = jid.JID(to_jid_s)
|
||||
d = client.encryption.getTrustUI(to_jid, namespace=namespace or None)
|
||||
d.addCallback(lambda xmlui: xmlui.toXml())
|
||||
return d
|
||||
|
||||
## XMPP methods ##
|
||||
|
||||
def _messageSend(self, to_jid_s, message, subject=None, mess_type="auto", extra=None,
|
||||
|
|
@ -697,23 +727,6 @@ class SAT(service.Service):
|
|||
{unicode(key): unicode(value) for key, value in extra.items()},
|
||||
)
|
||||
|
||||
def _messageEncryptionStart(self, to_jid_s, encryption_ns, replace=False,
|
||||
profile_key=C.PROF_KEY_NONE):
|
||||
client = self.getClient(profile_key)
|
||||
to_jid = jid.JID(to_jid_s)
|
||||
return client.encryption.start(to_jid, encryption_ns.strip() or None, replace)
|
||||
|
||||
def _messageEncryptionStop(self, to_jid_s, profile_key=C.PROF_KEY_NONE):
|
||||
client = self.getClient(profile_key)
|
||||
to_jid = jid.JID(to_jid_s)
|
||||
return client.encryption.stop(to_jid)
|
||||
|
||||
def _messageEncryptionGet(self, to_jid_s, profile_key=C.PROF_KEY_NONE):
|
||||
client = self.getClient(profile_key)
|
||||
to_jid = jid.JID(to_jid_s)
|
||||
session_data = client.encryption.getSession(to_jid)
|
||||
return client.encryption.getBridgeData(session_data)
|
||||
|
||||
def _setPresence(self, to="", show="", statuses=None, profile_key=C.PROF_KEY_NONE):
|
||||
return self.setPresence(jid.JID(to) if to else None, show, statuses, profile_key)
|
||||
|
||||
|
|
@ -1051,7 +1064,7 @@ class SAT(service.Service):
|
|||
with_data(bool): True if the callback use the optional data dict
|
||||
force_id(unicode): id to avoid generated id. Can lead to name conflict, avoid
|
||||
if possible
|
||||
one_shot(bool): True to delete callback once it have been called
|
||||
one_shot(bool): True to delete callback once it has been called
|
||||
@return: id of the registered callback
|
||||
"""
|
||||
callback_id = kwargs.pop("force_id", None)
|
||||
|
|
|
|||
|
|
@ -51,8 +51,10 @@ class EncryptionHandler(object):
|
|||
|
||||
@param plg_instance(object): instance of the plugin
|
||||
it must have the following methods:
|
||||
- startEncryption(jid.JID): start an encryption session with a bare jid
|
||||
- stopEncryption(jid.JID): stop an encryption session with a bare jid
|
||||
- getTrustUI(entity): return a XMLUI for trust management
|
||||
entity(jid.JID): entity to manage
|
||||
The returned XMLUI must be a form
|
||||
|
||||
@param name(unicode): human readable name of the encryption algorithm
|
||||
@param namespace(unicode): namespace of the encryption algorithm
|
||||
@param priority(int): priority of this plugin to encrypt an message when not
|
||||
|
|
@ -83,6 +85,15 @@ class EncryptionHandler(object):
|
|||
def getPlugins(cls):
|
||||
return cls.plugins
|
||||
|
||||
@classmethod
|
||||
def getPlugin(cls, namespace):
|
||||
try:
|
||||
return next(p for p in cls.plugins if p.namespace == namespace)
|
||||
except StopIteration:
|
||||
raise exceptions.NotFound(_(
|
||||
u"Can't find requested encryption plugin: {namespace}").format(
|
||||
namespace=namespace))
|
||||
|
||||
@classmethod
|
||||
def getNSFromName(cls, name):
|
||||
"""Retrieve plugin namespace from its name
|
||||
|
|
@ -94,7 +105,9 @@ class EncryptionHandler(object):
|
|||
for p in cls.plugins:
|
||||
if p.name.lower() == name.lower():
|
||||
return p.namespace
|
||||
raise exceptions.NotFound
|
||||
raise exceptions.NotFound(_(
|
||||
u"Can't find a plugin with the name \"{name}\".".format(
|
||||
name=name)))
|
||||
|
||||
def getBridgeData(self, session):
|
||||
"""Retrieve session data serialized for bridge.
|
||||
|
|
@ -117,7 +130,8 @@ class EncryptionHandler(object):
|
|||
|
||||
@param entity(jid.JID): entity to start an encryption session with
|
||||
must be bare jid is the algorithm encrypt for all devices
|
||||
@param namespace(unicode, None): namespace of the encryption algorithm to use
|
||||
@param namespace(unicode, None): namespace of the encryption algorithm
|
||||
to use.
|
||||
None to select automatically an algorithm
|
||||
@param replace(bool): if True and an encrypted session already exists,
|
||||
it will be replaced by the new one
|
||||
|
|
@ -129,12 +143,7 @@ class EncryptionHandler(object):
|
|||
if namespace is None:
|
||||
plugin = self.plugins[0]
|
||||
else:
|
||||
try:
|
||||
plugin = next(p for p in self.plugins if p.namespace == namespace)
|
||||
except StopIteration:
|
||||
raise exceptions.NotFound(_(
|
||||
u"Can't find requested encryption plugin: {namespace}").format(
|
||||
namespace=namespace))
|
||||
plugin = self.getPlugin(namespace)
|
||||
|
||||
bare_jid = entity.userhostJID()
|
||||
if bare_jid in self._sessions:
|
||||
|
|
@ -142,7 +151,8 @@ class EncryptionHandler(object):
|
|||
former_plugin = self._sessions[bare_jid]['plugin']
|
||||
if former_plugin.namespace == namespace:
|
||||
log.info(_(u"Session with {bare_jid} is already encrypted with {name}. "
|
||||
u"Nothing to do.").format(bare_jid=bare_jid, name=plugin.name))
|
||||
u"Nothing to do.").format(
|
||||
bare_jid=bare_jid, name=former_plugin.name))
|
||||
return
|
||||
|
||||
if replace:
|
||||
|
|
@ -255,9 +265,39 @@ class EncryptionHandler(object):
|
|||
None if there is not encryption for this session with this jid
|
||||
"""
|
||||
if entity.resource:
|
||||
raise exceptions.InternalError(u"Full jid given when expecting bare jid")
|
||||
raise ValueError(u"Full jid given when expecting bare jid")
|
||||
return self._sessions.get(entity)
|
||||
|
||||
def getTrustUI(self, entity_jid, namespace=None):
|
||||
"""Retrieve encryption UI
|
||||
|
||||
@param entity_jid(jid.JID): get the UI for this entity
|
||||
must be a bare jid
|
||||
@param namespace(unicode): namespace of the algorithm to manage
|
||||
if None use current algorithm
|
||||
@return D(xmlui): XMLUI for trust management
|
||||
the xmlui is a form
|
||||
None if there is not encryption for this session with this jid
|
||||
@raise exceptions.NotFound: no algorithm/plugin found
|
||||
@raise NotImplementedError: plugin doesn't handle UI management
|
||||
"""
|
||||
if namespace is None:
|
||||
session = self.getSession(entity_jid)
|
||||
if not session:
|
||||
raise exceptions.NotFound(
|
||||
u"No encryption session currently active for {entity_jid}"
|
||||
.format(entity_jid=entity_jid.full()))
|
||||
plugin = session['plugin']
|
||||
else:
|
||||
plugin = self.getPlugin(namespace)
|
||||
try:
|
||||
get_trust_ui = plugin.instance.getTrustUI
|
||||
except AttributeError:
|
||||
raise NotImplementedError(
|
||||
u"Encryption plugin doesn't handle trust management UI")
|
||||
else:
|
||||
return get_trust_ui(self.client, entity_jid)
|
||||
|
||||
## Triggers ##
|
||||
|
||||
def setEncryptionFlag(self, mess_data):
|
||||
|
|
@ -283,3 +323,13 @@ class EncryptionHandler(object):
|
|||
"""
|
||||
mess_data['encrypted'] = True
|
||||
return mess_data
|
||||
|
||||
def markAsUntrusted(self, mess_data):
|
||||
"""Helper methor to mark a message as sent from an untrusted entity.
|
||||
|
||||
This should be used in the post_treat workflow of MessageReceived trigger of
|
||||
the plugin
|
||||
@param mess_data(dict): message data as used in post treat workflow
|
||||
"""
|
||||
mess_data['untrusted'] = True
|
||||
return mess_data
|
||||
|
|
|
|||
|
|
@ -245,6 +245,20 @@ class Bridge(object):
|
|||
error_handler = lambda err:errback(dbus_to_bridge_exception(err))
|
||||
return self.db_core_iface.disconnect(profile_key, timeout=const_TIMEOUT, reply_handler=callback, error_handler=error_handler)
|
||||
|
||||
def encryptionNamespaceGet(self, arg_0, callback=None, errback=None):
|
||||
if callback is None:
|
||||
error_handler = None
|
||||
else:
|
||||
if errback is None:
|
||||
errback = log.error
|
||||
error_handler = lambda err:errback(dbus_to_bridge_exception(err))
|
||||
kwargs={}
|
||||
if callback is not None:
|
||||
kwargs['timeout'] = const_TIMEOUT
|
||||
kwargs['reply_handler'] = callback
|
||||
kwargs['error_handler'] = error_handler
|
||||
return unicode(self.db_core_iface.encryptionNamespaceGet(arg_0, **kwargs))
|
||||
|
||||
def encryptionPluginsGet(self, callback=None, errback=None):
|
||||
if callback is None:
|
||||
error_handler = None
|
||||
|
|
@ -259,6 +273,15 @@ class Bridge(object):
|
|||
kwargs['error_handler'] = error_handler
|
||||
return self.db_core_iface.encryptionPluginsGet(**kwargs)
|
||||
|
||||
def encryptionTrustUIGet(self, namespace, arg_1, profile_key, callback=None, errback=None):
|
||||
if callback is None:
|
||||
error_handler = None
|
||||
else:
|
||||
if errback is None:
|
||||
errback = log.error
|
||||
error_handler = lambda err:errback(dbus_to_bridge_exception(err))
|
||||
return unicode(self.db_core_iface.encryptionTrustUIGet(namespace, arg_1, profile_key, timeout=const_TIMEOUT, reply_handler=callback, error_handler=error_handler))
|
||||
|
||||
def getConfig(self, section, name, callback=None, errback=None):
|
||||
if callback is None:
|
||||
error_handler = None
|
||||
|
|
@ -532,7 +555,7 @@ class Bridge(object):
|
|||
kwargs['error_handler'] = error_handler
|
||||
return unicode(self.db_core_iface.messageEncryptionGet(to_jid, profile_key, **kwargs))
|
||||
|
||||
def messageEncryptionStart(self, to_jid, encryption_ns='', replace=False, profile_key="@NONE@", callback=None, errback=None):
|
||||
def messageEncryptionStart(self, to_jid, namespace='', replace=False, profile_key="@NONE@", callback=None, errback=None):
|
||||
if callback is None:
|
||||
error_handler = None
|
||||
else:
|
||||
|
|
@ -544,7 +567,7 @@ class Bridge(object):
|
|||
kwargs['timeout'] = const_TIMEOUT
|
||||
kwargs['reply_handler'] = callback
|
||||
kwargs['error_handler'] = error_handler
|
||||
return self.db_core_iface.messageEncryptionStart(to_jid, encryption_ns, replace, profile_key, **kwargs)
|
||||
return self.db_core_iface.messageEncryptionStart(to_jid, namespace, replace, profile_key, **kwargs)
|
||||
|
||||
def messageEncryptionStop(self, to_jid, profile_key, callback=None, errback=None):
|
||||
if callback is None:
|
||||
|
|
|
|||
|
|
@ -214,6 +214,14 @@ class Bridge(object):
|
|||
errback = self._generic_errback
|
||||
d.addErrback(errback)
|
||||
|
||||
def encryptionNamespaceGet(self, arg_0, callback=None, errback=None):
|
||||
d = self.root.callRemote("encryptionNamespaceGet", arg_0)
|
||||
if callback is not None:
|
||||
d.addCallback(callback)
|
||||
if errback is None:
|
||||
errback = self._generic_errback
|
||||
d.addErrback(errback)
|
||||
|
||||
def encryptionPluginsGet(self, callback=None, errback=None):
|
||||
d = self.root.callRemote("encryptionPluginsGet")
|
||||
if callback is not None:
|
||||
|
|
@ -222,6 +230,14 @@ class Bridge(object):
|
|||
errback = self._generic_errback
|
||||
d.addErrback(errback)
|
||||
|
||||
def encryptionTrustUIGet(self, namespace, arg_1, profile_key, callback=None, errback=None):
|
||||
d = self.root.callRemote("encryptionTrustUIGet", namespace, arg_1, profile_key)
|
||||
if callback is not None:
|
||||
d.addCallback(callback)
|
||||
if errback is None:
|
||||
errback = self._generic_errback
|
||||
d.addErrback(errback)
|
||||
|
||||
def getConfig(self, section, name, callback=None, errback=None):
|
||||
d = self.root.callRemote("getConfig", section, name)
|
||||
if callback is not None:
|
||||
|
|
@ -398,8 +414,8 @@ class Bridge(object):
|
|||
errback = self._generic_errback
|
||||
d.addErrback(errback)
|
||||
|
||||
def messageEncryptionStart(self, to_jid, encryption_ns='', replace=False, profile_key="@NONE@", callback=None, errback=None):
|
||||
d = self.root.callRemote("messageEncryptionStart", to_jid, encryption_ns, replace, profile_key)
|
||||
def messageEncryptionStart(self, to_jid, namespace='', replace=False, profile_key="@NONE@", callback=None, errback=None):
|
||||
d = self.root.callRemote("messageEncryptionStart", to_jid, namespace, replace, profile_key)
|
||||
if callback is not None:
|
||||
d.addCallback(lambda dummy: callback())
|
||||
if errback is None:
|
||||
|
|
|
|||
Loading…
Reference in a new issue