Race-condition in EntityCapabilitiesManager when deleting user
Description
When a user gets deleted, the `userDeleting` event handler in `EntityCapabilitiesManager` is designed to remove all of the user's capabilities from the `entityCapabilitiesUserMap`. It does so by
looking up the matching keys (see if the full JID keys match the user's bare JID), followed by
a removal of the matching entries.
Finally, a check is preformed to see if the 'ver' hash that was associated with them remains in use (by unrelated entries). If not, that can be removed too.
There is a race condition where between 1 and 2, another event might modified the map. For example, deleting a user can go hand-in-hand with sending an unavailable presence for that same user, causing another thread from removing an entry from the map. This can lead to situations where the second step results in a `null` value being passed to the third step, which will then throw a NullPointerException (as it does not allow for null arguments to be used.
java.lang.NullPointerException: Null value is not allowed!
at org.jivesoftware.util.cache.DefaultCache.checkNotNull(DefaultCache.java:608) ~[xmppserver-4.4.4.jar:4.4.4]
at org.jivesoftware.util.cache.DefaultCache.containsValue(DefaultCache.java:304) ~[xmppserver-4.4.4.jar:4.4.4]
at org.jivesoftware.util.cache.CacheWrapper.containsValue(CacheWrapper.java:113) ~[xmppserver-4.4.4.jar:4.4.4]
at org.jivesoftware.openfire.entitycaps.EntityCapabilitiesManager.checkObsolete(EntityCapabilitiesManager.java:518) ~[xmppserver-4.4.4.jar:4.4.4]
at java.lang.Iterable.forEach(Iterable.java:75) ~[?:?]
at org.jivesoftware.openfire.entitycaps.EntityCapabilitiesManager.userDeleting(EntityCapabilitiesManager.java:508) ~[xmppserver-4.4.4.jar:4.4.4]
at org.jivesoftware.openfire.event.UserEventDispatcher.dispatchEvent(UserEventDispatcher.java:134) [xmppserver-4.4.4.jar:4.4.4]
at org.jivesoftware.openfire.user.UserManager.deleteUser(UserManager.java:246) [xmppserver-4.4.4.jar:4.4.4]
When a user gets deleted, the `userDeleting` event handler in `EntityCapabilitiesManager` is designed to remove all of the user's capabilities from the `entityCapabilitiesUserMap`. It does so by
looking up the matching keys (see if the full JID keys match the user's bare JID), followed by
a removal of the matching entries.
Finally, a check is preformed to see if the 'ver' hash that was associated with them remains in use (by unrelated entries). If not, that can be removed too.
There is a race condition where between 1 and 2, another event might modified the map. For example, deleting a user can go hand-in-hand with sending an unavailable presence for that same user, causing another thread from removing an entry from the map. This can lead to situations where the second step results in a `null` value being passed to the third step, which will then throw a NullPointerException (as it does not allow for null arguments to be used.
java.lang.NullPointerException: Null value is not allowed! at org.jivesoftware.util.cache.DefaultCache.checkNotNull(DefaultCache.java:608) ~[xmppserver-4.4.4.jar:4.4.4] at org.jivesoftware.util.cache.DefaultCache.containsValue(DefaultCache.java:304) ~[xmppserver-4.4.4.jar:4.4.4] at org.jivesoftware.util.cache.CacheWrapper.containsValue(CacheWrapper.java:113) ~[xmppserver-4.4.4.jar:4.4.4] at org.jivesoftware.openfire.entitycaps.EntityCapabilitiesManager.checkObsolete(EntityCapabilitiesManager.java:518) ~[xmppserver-4.4.4.jar:4.4.4] at java.lang.Iterable.forEach(Iterable.java:75) ~[?:?] at org.jivesoftware.openfire.entitycaps.EntityCapabilitiesManager.userDeleting(EntityCapabilitiesManager.java:508) ~[xmppserver-4.4.4.jar:4.4.4] at org.jivesoftware.openfire.event.UserEventDispatcher.dispatchEvent(UserEventDispatcher.java:134) [xmppserver-4.4.4.jar:4.4.4] at org.jivesoftware.openfire.user.UserManager.deleteUser(UserManager.java:246) [xmppserver-4.4.4.jar:4.4.4]