AMQP 1.0: fix sending to a volatile queue's address by lukebakken · Pull Request #17805 · rabbitmq/rabbitmq-server · GitHub
Skip to content

AMQP 1.0: fix sending to a volatile queue's address - #17805

Open
lukebakken wants to merge 2 commits into
rabbitmq:mainfrom
lukebakken:amqp-own-reply-to
Open

lukebakken wants to merge 2 commits into
rabbitmq:mainfrom
lukebakken:amqp-own-reply-to

Conversation

@lukebakken

Copy link
Copy Markdown
Collaborator

Note

This pull request description was written by Claude (Anthropic's Claude Code) under the direction of @lukebakken, who reviewed it before it was opened. The behaviour described was measured on main at a626109 and, where noted, on 4.2.9, 4.3.6 and an earlier main.

Two problems with sender targets that name a direct reply-to (volatile) queue, both there since AMQP 1.0 direct reply-to arrived in 4.2.0. Neither is urgent. Direct reply-to RPC between a requester and a separate responder session is not affected, and neither is a session sending to its own temporary queue (the temporary-queue capability that JMS clients use): that queue is an exclusive classic queue, and a message sent to it on the same session is delivered on main, 4.3.6 and this branch.

A session cannot send to its own reply-to queue through a /queues/ target, or a v1 /amq/queue/ one: the attach is refused with amqp:not-found (main, 4.3.6 and 4.2.9). The existence check, rabbit_volatile_queue:exists/1, asks the owning session with a gen_server:call/2, which fails when the owner is the session doing the attach. An anonymous target with to set to the same address works. This only matters for a session that is both requester and responder, which should be rare, and the refusal is immediate rather than silent. The session now answers from its own queue states for such a name.

The second problem is the more practical one, though it needs the deprecated v1 addresses. A v1 /queue/amq.rabbitmq.reply-to.* target, as a responder would use, declares a classic queue of that name. Lookups and routing resolve the name to the volatile queue, so the message is delivered, but the queue record is left behind. It counts towards queue limits and cannot be deleted with rabbitmqctl delete_queue or the HTTP API (measured on main at b9bd222 and on 4.3.6); this pull request does not remove records already left behind. The name is now checked for existence, as a /queues/ target is, instead of being declared. As a result, a v1 sender to a reply-to name that does not exist is refused with amqp:not-found. It also no longer needs the configure permission on the name: a user without it, replying through v1 /queue/, had its session ended with amqp:unauthorized-access on main and is now delivered.

The first commit adds requester_sends_to_own_volatile_queue and target_v1_reply_to_queue, which fail on main; the second fixes them and adds a check that a v1 /queue target with no name still attaches. Each of five mutations makes at least one of them fail.

These fail on `main`:

* `requester_sends_to_own_volatile_queue`: a session that attaches a
  sender to the `/queues/` address of its own direct reply-to queue is
  refused with `amqp:not-found`
* `target_v1_reply_to_queue`: a v1 `/queue/amq.rabbitmq.reply-to.*`
  target declares a classic queue with that name, so each such sender
  leaves a queue record behind, even though its messages are routed to
  the volatile queue; a v1 `/amq/queue/` target to the session's own
  reply-to queue is refused with `amqp:not-found`
A sender target that names a direct reply-to queue is checked with
`rabbit_volatile_queue:exists/1`, which asks the session that owns the
queue. When that is the attaching session itself, the call fails and
the attach is refused with `amqp:not-found`, so a session could not
send to its own reply-to queue through a `/queues/` or `/amq/queue/`
target. The session now answers from its own queue states for such a
name.

A v1 `/queue/amq.rabbitmq.reply-to.*` target declared a classic queue
of that name, which lookups and routing never reach, so every such
sender left a queue record behind. Such a name is now checked for
existence, as a `/queues/` target is, instead of being declared. This
means a v1 sender to a reply-to name that does not exist is refused
with `amqp:not-found`, and it no longer needs the configure permission
on that name, only write on the default exchange.

`target_v1_reply_to_queue` also checks that a v1 `/queue` target with
no queue name still attaches.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant