Packet Filter for the initial presence when joining a MUC room

When joining a room using MultiUserChat?.join the responses are not always correctly handled

Test case:

f.i. User wants to join a room that is blocked for him

<presence id="3SWrl-51" to="blockedroom@huis.straat.stad/User"> <x xmlns="http://jabber.org/protocol/muc"> <password/> </x> </presence>

The server (M-Link) returns a response with a non expected From Adress:

<presence id="3SWrl-51" to="anno@test.xmpp/resource" from="blockedroom@huis.straat.stad" type="error"> <x xmlns="http://jabber.org/protocol/muc"/> <error type="auth"> <registration-required xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/> </error> </presence>

The Smack code does not recognise the response in this case while it is waiting for a response with the complete RoomJID + nickname as the from address and returns with a NoResponseException.

A possible solution is:

Take also the PacketID in account.

diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChat.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChat.java
index cd3b26d..068a221 100644
--- a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChat.java
+++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChat.java
@@ -47,8 +47,10 @@ import org.jivesoftware.smack.filter.MessageTypeFilter; import org.jivesoftware.smack.filter.MessageWithSubjectFilter; import org.jivesoftware.smack.filter.NotFilter;
+import org.jivesoftware.smack.filter.OrFilter; import org.jivesoftware.smack.filter.PacketExtensionFilter; import org.jivesoftware.smack.filter.PacketFilter;
+import org.jivesoftware.smack.filter.PacketIDFilter; import org.jivesoftware.smack.filter.PacketTypeFilter; import org.jivesoftware.smack.filter.ToFilter; import org.jivesoftware.smack.packet.IQ;
@@ -284,8 +286,8 @@
         joinPresence.addExtension(mucInitialPresence);          // Wait for a presence packet back from the server.
-        PacketFilter responseFilter = new AndFilter(FromMatchesFilter.createFull(room + "/"
-                        + nickname), new PacketTypeFilter(Presence.class));
+        PacketFilter responseFilter = new AndFilter(new OrFilter(new PacketIDFilter(joinPresence.getPacketID()),
+                        FromMatchesFilter.createFull(room + "/" + nickname)), new PacketTypeFilter(Presence.class));          // Setup the messageListeners and presenceListeners *before* the join presence is send.
         connection.addPacketListener(messageListener, fromRoomGroupchatFilter);

Thanks for the detailed report!

Most (all?) examples (e.g 7.2.6 - 7.2.10) in XEP-45 have a full JID as from value. But examples are not authoritative with regard to the specification.

But I don’t think that modifying the filter by or-ing a packet id filter is a good idea, especially from a security POV. MUC uses here similar semantics like IQ, but using Presence stanzas. And this was done wrong and therefore vulnerable for years in Smack, see SMACK-533. I think the correct solution would be

    •    PacketFilter responseFilter = new AndFilter(new PacketIDFilter(joinPresence.getPacketID()), 
      
    •                    FromMatchesFilter.createBare(room), new PacketTypeFilter(Presence.class));
      

What do think?

Logged as SMACK-618

From the spec point of view, it’s not guaranteed, that the MUC service includes the id:

This helps the client know when it has received the complete “room roster”. For tracking purposes, the room might also reflect the original ‘id’ value if provided in the presence stanza sent by the user.

The description is a little bit weak here, but “might” is not “MUST”.

Maybe it’s sufficient to just check if the bare JIDs matches, i.e. the room address without nickname?

In my case (using M-Link as XMPP server) the problem occurs when an error occurs during joining which prevents joining,

Like trying to join with a already used nickname or a nickname which is not permitted. In these cases the server for sure will not respond with the nickname as the resource in its from address.

Maybe, if security is an issue, make some refinements: check for ‘id’ in case of errors, check for full ‘roomjid’ when no errors.

Good point. Given that M-Link will send from the full JID in a future version (at least that is what I was told), I don’t see any actions required on Smack’s side. But XEP-45 seems to be underspecified regarding this, i.e. it would be nice if it clearly states that the error presences must have a full JID as ‘from’ attribute. RFC 6120 8.3 only states that errors “typically swaps the ‘from’ and ‘to’ addresses of the generated stanza”.