FraunhoferIOSB / FROST-Server

A Complete Server implementation of the OGC SensorThings API
https://fraunhoferiosb.github.io/FROST-Server/
GNU Lesser General Public License v3.0
198 stars 74 forks source link

Missing user data results in NullPointerException in MQTT server #2030

Closed byteneumann closed 1 month ago

byteneumann commented 1 month ago

I noticed that subscribing the MQTT server, with authentication enabled, without a user leads to unresponsive behaviour.

Setup

I am using Helm to run FROST-Server and mqtt.js as client. frost.auth.provider is set to de.fraunhofer.iosb.ilt.frostserver.auth.basic.BasicAuthProvider and TLS is configured for MQTT.

Problem

When connecting to the WebSocket (Secure) endpoint and while not providing a user for authentication, the Pod frost-server-mqtt logs the following:

13:21:35.699 [Session Executor 2] ERROR d.f.i.i.f.m.m.MoquetteMqttServer - MQTT Session Loop caused an exception!       
java.lang.RuntimeException: java.util.concurrent.ExecutionException: java.lang.NullPointerException: Cannot invoke "String.equals(Object)" because "user" is null
        at io.moquette.broker.SessionEventLoop.executeTask(SessionEventLoop.java:52)
        at io.moquette.broker.SessionEventLoop.run(SessionEventLoop.java:34)
Caused by: java.util.concurrent.ExecutionException: java.lang.NullPointerException: Cannot invoke "String.equals(Object)" because "user" is null
        at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122)
        at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191)
        at io.moquette.broker.SessionEventLoop.executeTask(SessionEventLoop.java:49)
        ... 1 common frames omitted
Caused by: java.lang.NullPointerException: Cannot invoke "String.equals(Object)" because "user" is null
        at de.fraunhofer.iosb.ilt.frostserver.mqtt.moquette.AuthWrapper.canRead(AuthWrapper.java:183)
        at io.moquette.broker.Authorizator.verifyTopicsReadAccess(Authorizator.java:57)
        at io.moquette.broker.PostOffice.subscribeClientToTopics(PostOffice.java:210)
        at io.moquette.broker.MQTTConnection.lambda$processSubscribe$6(MQTTConnection.java:401)
        at io.moquette.broker.SessionCommand.execute(SessionCommand.java:23)
        at io.moquette.broker.SessionEventLoopGroup.lambda$routeCommand$1(SessionEventLoopGroup.java:73)
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
        at io.moquette.broker.SessionEventLoop.executeTask(SessionEventLoop.java:46)
        ... 1 common frames omitted

After that, the Websocket endpoint seems instable. One or two subscribes may be successful, but for subsequent reconnects the MQTT server appears offline. It may come back, but I also observed a fast change from subscribed to offline.

Only after a kubectl rollout restart, the server is ok, again.

Fix?

Maybe adding user == null || in https://github.com/FraunhoferIOSB/FROST-Server/blob/6a0bb1c6775addf20f3f3bd5120bf6a8fa7b180a/FROST-Server.MQTT.Moquette/src/main/java/de/fraunhofer/iosb/ilt/frostserver/mqtt/moquette/AuthWrapper.java#L183 will be enough to fix this?

hylkevds commented 1 month ago

Thanks for the report. The null-check would probably have been enough, but I added an extra check to make sure that the user is registered as anonymous when the username is null. I also added some tests for this situation.

I'll release a new version with the fix soon.