Skip to content
Open
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions pkg/session/stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ func stream(ctx context.Context, dir Direction, r, w net.Conn, h Handler, preIc,
switch dir {
case Up:
if err = authorize(ctx, pkt, h); err != nil {
if _, ok := pkt.(*packets.PublishPacket); ok {
pkt = packets.NewControlPacket(packets.Disconnect).(*packets.DisconnectPacket)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First, can we go with just pkt = packets.NewControlPacket(packets.Disconnect)?
Second, is this OK according to the MQTT 3.1.1 spec? I mean, to send a disconnect right after publish and with no any other info (I guess this info is missing since, unlike 5.1, 3.1.1 does not have a disconnect reason code).
Finally, can we replace this with only:

			if err = authorize(ctx, pkt, h); err != nil {
				if _, ok := pkt.(*packets.PublishPacket); ok {
					// In case of unauthorized access, send disconnect.
					pkt = packets.NewControlPacket(packets.Disconnect)
				}
			}

since we have

// Send to another.
		if err := pkt.Write(w); err != nil {
			errs <- wrap(ctx, err, dir)
			return
		}

a few lines outside of this switch-case?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

		// Send to another.
		if err := pkt.Write(w); err != nil {
			errs <- wrap(ctx, err, dir)
			return
		}

This code block write back to the server, not to the client whose authz is incorrect

Copy link
Copy Markdown
Contributor Author

@arvindh123 arvindh123 Aug 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First, can we go with just pkt = packets.NewControlPacket(packets.Disconnect)?
Yes we can go like this

Second, is this OK according to the MQTT 3.1.1 spec?
Yes as per MQTT 3.1.1 server can disconnect at any time when authorization fails

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is OK from the client's perspective, but what about the broker? The broker will never know there was a publish, and will also not gracefully handle client disconnection. For the broker, it would be like if the client's conn is left hanging (reset by peer, I guess), and - what's next? What happens if the client tries to reconnect?

Copy link
Copy Markdown
Contributor Author

@arvindh123 arvindh123 Aug 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about the broker?

This need to be checked, This need to verify and test it
I just followed the logic used in subscription authz failure
https://github.com/absmach/mgate/blob/main/pkg/session/stream.go#L81-L87

What happens if the client tries to reconnect?
We could not prevent the client trying again with same wrong password.
May be we block in ingress if any client tries with same password.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@arvindh123 We need to address this and move on with this PR.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@arvindh123 Any news on this?

if wErr := pkt.Write(w); wErr != nil {
err = errors.Join(err, wErr)
}
}
errs <- wrap(ctx, err, dir)
return
}
Expand Down