Commit 2fb78fe3 authored by ValdikSS's avatar ValdikSS

Set access_model=open on OMEMO PEP elements. Fixes #444.

OMEMO plugin should set `pubsub#access_model` to `open` for
`eu.siacs.conversations.axolotl.devicelist` and
`eu.siacs.conversations.axolotl.bundles` PEP nodes to allow using OMEMO
between non-subscribers (e.g. in multiuser groups).

If `devicelist` node already exists and not configured with
`pubsub#access_model`, publishing to it with publish-options could return
`precondition-not-met`. The plugin will try to reconfigure this PEP node.

NOTE: this modification does not check the presence of pubsub#config-node
and pubsub#create-and-configure features and tries to use it anyway.

NOTE 2: reconfiguration uses Data Forms protocol but does not
request a Form first, and just tries to reconfigure a single
form element.
parent 13d61751
......@@ -664,7 +664,28 @@ class OMEMOConnection:
# Enable Encryption on receiving first Device List
# TODO
def publish_own_devices_list(self, new=False):
def create_options_node(self):
""" Create PubSub options node with pubsub#access_model = open
"""
options = Node(nbxmpp.NS_DATA + ' x',
attrs={'type': 'submit'})
field = options.addChild('field',
attrs={'var': 'FORM_TYPE', 'type': 'hidden'})
field.setTagData('value', nbxmpp.NS_PUBSUB_PUBLISH_OPTIONS)
field = options.addChild('field', attrs={'var': 'pubsub#access_model'})
field.setTagData('value', 'open')
return options
def pep_reconfigure_open(self, ns, cb):
""" Reconfigure PEP node to make OMEMO keys and device list
accessible without subscription.
"""
con = app.connections[self.account]
con.get_module('PubSub').send_pb_configure(
'', ns, self.create_options_node(),
cb=cb)
def publish_own_devices_list(self, new=False, secondTime=False):
""" Get all currently known own active device ids and publish them
Parameters
......@@ -672,6 +693,8 @@ class OMEMOConnection:
new : bool
if True, a devicelist with only one
(the current id of this instance) device id is pushed
secondTime : bool
if True, no PEP reconfiguration will be performed
"""
if new:
devices_list = [self.omemo.own_device_id]
......@@ -686,9 +709,18 @@ class OMEMOConnection:
list_node.addChild('device').setAttr('id', device)
con = app.connections[self.account]
options = None
if con.get_module('PubSub').publish_options:
options = self.create_options_node()
pub_callback = self.device_list_publish_result_with_check
if secondTime:
pub_callback = self.device_list_publish_result
con.get_module('PubSub').send_pb_publish(
'', NS_DEVICE_LIST, list_node, 'current',
cb=self.device_list_publish_result)
options=options,
cb=pub_callback)
log.info('%s => Publishing own Devices: %s',
self.account, devices_list)
......@@ -698,6 +730,25 @@ class OMEMOConnection:
log.error('%s => Publishing devicelist failed: %s',
self.account, stanza.getError())
def device_list_publish_result_with_check(self, _con, stanza):
if not nbxmpp.isResultNode(stanza):
if (stanza.getError() and stanza.getError() == 'conflict'
and stanza.getTag('error').getTag('precondition-not-met',
namespace=nbxmpp.NS_PUBSUB + '#errors')):
log.info('%s => Publishing devicelist failed: %s, trying to reconfigure',
self.account, stanza.getError())
self.pep_reconfigure_open(NS_DEVICE_LIST, self.device_list_reconfigure_result_with_check)
else:
log.error('%s => Publishing devicelist failed: %s',
self.account, stanza.getError())
def device_list_reconfigure_result_with_check(self, _con, stanza):
if not nbxmpp.isResultNode(stanza):
log.error('%s => Reconfiguring devicelist failed: %s',
self.account, stanza.getError())
else:
self.publish_own_devices_list(secondTime=True)
def are_keys_missing(self, contact_jid):
""" Checks if devicekeys are missing and querys the
bundles
......@@ -812,8 +863,14 @@ class OMEMOConnection:
data={'fetch_bundle': fetch_bundle})
self.query_for_devicelists.append(jid)
def publish_bundle(self):
""" Publish our bundle information to the PEP node """
def publish_bundle(self, secondTime=False):
""" Publish our bundle information to the PEP node
Parameters
----------
secondTime : bool
if True, no PEP reconfiguration will be performed
"""
bundle = make_bundle(self.omemo.bundle)
node = '%s%s' % (NS_BUNDLES, self.omemo.own_device_id)
......@@ -821,8 +878,18 @@ class OMEMOConnection:
log.info('%s => Publishing bundle ...', self.account)
con = app.connections[self.account]
options = None
if con.get_module('PubSub').publish_options:
options = self.create_options_node()
pub_callback = self.handle_publish_result_with_check
if secondTime:
pub_callback = self.handle_publish_result
con.get_module('PubSub').send_pb_publish(
'', node, bundle, 'current', cb=self.handle_publish_result)
'', node, bundle, 'current',
options=options,
cb=pub_callback)
def handle_publish_result(self, _con, stanza):
""" Log if publishing our bundle was successful
......@@ -838,6 +905,35 @@ class OMEMOConnection:
log.error('%s => Publishing bundle was NOT successful',
self.account)
def handle_publish_result_with_check(self, _con, stanza):
""" Check if publishing our bundle was successful and reconfigure if needed
Parameters
----------
stanza : nbxmpp.Iq
The stanza
"""
if successful(stanza):
log.info('%s => Publishing bundle was successful', self.account)
elif (stanza.getError() and stanza.getError() == 'conflict'
and stanza.getTag('error').getTag('precondition-not-met',
namespace=nbxmpp.NS_PUBSUB + '#errors')):
log.info('%s => Publishing bundle was NOT successful, trying to reconfigure',
self.account)
bundle = make_bundle(self.omemo.bundle)
node = '%s%s' % (NS_BUNDLES, self.omemo.own_device_id)
self.pep_reconfigure_open(node, self.handle_publish_reconfigure_result_with_check)
else:
log.error('%s => Publishing bundle was NOT successful',
self.account)
def handle_publish_reconfigure_result_with_check(self, _con, stanza):
if not nbxmpp.isResultNode(stanza):
log.error('%s => Reconfiguring bundle failed: %s',
self.account, stanza.getError())
else:
self.publish_bundle(secondTime=True)
def handle_devicelist_result(self, stanza):
""" If query was successful add own device to the list.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment