Openfire and RFC3921 compliancy

I’ve been investigating a bit on OF compliancy with the IM RFC and found some issues that may lead to problematic situations. I wanted to share with you what I found.

Let’s start with a small use case:

  • U1 connects on S and authenticates but does not send its initial presence

  • U2 connects on S and authenticates but does not send its initial presence

  • U1 sends a message to U2 -> U2 does not receive it

  • U2 sends a message to U1 -> U1 does not receive it

  • U1 sends its initial presence, U1 receives one offline message from U2 (provided offline support is activated)

  • U1 sends a message to U2 -> U2 does not receive it

  • U2 sends a message to U1 -> U1 well receive it

  • U2 sends its initial presence, U2 receives two offline messages from U1

  • U1 and U2 can now communicate without troubles

IM RFC says << also stipulates that presence services must be separable from instant messaging services; i.e., it must be possible to use the protocol to provide a presence service, an instant messaging service, or both >> (section 1.2)

In this case OF clearly violates RFC3921 but this can be explained if it was in past based on Jabber protocol where this was not defined clearly.

This is not a big issue since most IM apps implement and use both services at the same time; but this can lead to some edge cases:

  • U1 connects on S1, authenticates and send initial presence

  • U2 connects on S2, authenticates and send initial presence

  • U1 starts a MUC on S2

  • U2 joins MUC room started on S2

  • U1 sends presence unavailable

  • U2 receives presence unavailable from U1 in the MUC room and possibly in its roster if U1 is in.

  • U1 receives nothing -> while he should receive its own presence unavailable within room.

The issue is that OF considers there’s no route to the user until the user sends its initial presence. On receiving presence unavailable, OF destroys the route to the user while it should not.

What happens in this use case is:

  • U1 sends presence unavailable

  • S1 broadcasts it to all contacts in the roster

  • S1 also routes it to MUC component on S2

  • S1 destroys route to U1 because of presence unavailable

  • S2 broadcasts presence unavailable of U1 to all occupants of the MUC room

  • U2 receives it

  • S1 never forward it to the client because route is destroyed

This does not occur when the incriminated MUC service is hosted on the users’s server. In that case, presence from room is broadcasted to client before the route is destroyed.

One can argue that if U1 is sending presence unavailable it is for disconnecting, BUT this can also be used in the privacy stuff to become ‘invisible’:

  • send presence unavailable

  • set privacy list

  • send presence which will not be broadcasted to other clients.

In that precise case, the client would never be notified he’s been disconnected from the MUC room after having sent the presence unavailable.

OK, this looks all of an edge case BUT this was to be mentioned. Patching OF for this is not that complicated