internal: gate auth-agent channel opens on the client's request - #1244
internal: gate auth-agent channel opens on the client's request#1244yosuke-wolfssl wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
An auth-agent open currently logs ssh->agent at INFO with a raw pointer value per request, which can enable log spamming and unnecessarily exposes address data.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR hardens wolfSSH’s handling of auth-agent@openssh.com channel opens by ensuring agent-forwarding channels are only accepted when they are (1) directionally valid and (2) actually requested by the client, closing a server-driven channel-open signing path.
Changes:
- Added endpoint-direction and client-request-state gating for
ID_CHANTYPE_AUTH_AGENTinDoChannelOpen()before any channel allocation or callbacks run. - Added regression tests covering agent channel opens before/after the request state, callback precedence, null-agent behavior, and server-side refusal.
File summaries
| File | Description |
|---|---|
src/internal.c |
Adds pre-ChannelNew() gating for auth-agent channel opens based on endpoint role and connectState. |
tests/regress.c |
Adds an in-memory harness test matrix for agent channel open accept/refuse scenarios and moves the null-agent case into the client harness. |
Review details
- Files reviewed: 2/2 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #1244
Scan targets checked: wolfssh-bugs, wolfssh-src
Fenrir result: Approved ✅
No new issues found in the changed files.
Advisory only — this automated result does not count as a GitHub approval.
- DoChannelOpen refuses an auth-agent open on a server endpoint, and on a client with the agent disabled or connectState below CONNECT_CLIENT_CHANNEL_AGENT_REQUEST_SENT. - Both answer OPEN_ADMINISTRATIVELY_PROHIBITED; the ssh->agent check stays as the resource check behind them. - Cover the refusals before the request, with the agent disabled, over an accepting channelOpenCb, and on a server, plus the accepted open past the request; each refusal asserts ssh->error stays clean. - Move TestAgentChannelNullAgentSendsOpenFail to a client harness, and have the agent tests set the agent flag explicitly. Issue: F-13389
e9b98ca to
dc748ca
Compare
Problem
Finding f-13389. With
WOLFSSH_AGENT,DoChannelOpen()admitted an inboundauth-agent@openssh.comchannel open on the single testssh->agent != NULL.That pointer is not a record of the request. The client allocates it during userauth,
because the same object serves agent-backed publickey authentication, and it sends
auth-agent-req@openssh.comonly after its session channel is confirmed. In between,wolfSSH_connect()sits inDoReceiveHandshake()processing packets, so a maliciousserver can open an agent channel a round trip before the client has asked for
forwarding, and get a confirmation. Applications relay non-session channel data into
wolfSSH_AGENT_Relay()(asexamples/clientdoes), making the channel a signing pathto the user's local agent.
Nothing checked the endpoint role either: a server with
ssh->agentset — which happensonce a client sends
auth-agent-req— accepted anauth-agentopen back from thatclient, the wrong direction per OpenSSH's PROTOCOL, overwriting
ssh->agent->channelwith a peer-chosen id.
The pre-authentication variant of this is not reachable:
IsMessageAllowedClient()already refuses message ids >= 80 until
CONNECT_SERVER_USERAUTH_ACCEPT_DONE.Fix (
src/internal.c)The
ID_CHANTYPE_AUTH_AGENTcase now decides in three steps, ahead ofChannelNew()and any
channelOpenCb, as thesessionandforwarded-tcpipgates beside it do:OPEN_ADMINISTRATIVELY_PROHIBITEDconnectState < CONNECT_CLIENT_CHANNEL_AGENT_REQUEST_SENTOPEN_ADMINISTRATIVELY_PROHIBITEDssh->agent == NULLWS_AGENT_NULL_ENo new session state:
wolfSSH_connect()already advancesconnectStateimmediatelyafter
SendChannelAgentRequest(), and returns without advancing if that send fails.wolfSSH clients never open this channel type, so refusing it on a server is
interop-safe. Refusals log at
WS_LOG_DEBUG, since they fire per peer open request.Closes f-13389.
Tests (
tests/regress.c)Four cases on the existing in-memory channel-open harness: an open before the request is
refused; the gate outranks an accepting
channelOpenCb; an open after the request isconfirmed and wires
agent->channel; a server refuses one.TestAgentChannelNullAgentSendsOpenFailmoves to a client harness, where the
ssh->agentcheck still decides the open, and nowasserts its fail reason.
Verification
--enable-all;regressalso passes with--disable-agent.assertion each makes exactly the intended test fail; forcing the gate to always refuse
fails the accepting test, so it is not vacuous.
-Werrorpreflight clean across 6 configs.