Skip to content

ssh: add generic request callbacks - #1236

Open
ejohnstown wants to merge 2 commits into
wolfSSL:masterfrom
ejohnstown:ccb-phase2-6
Open

ejohnstown wants to merge 2 commits into
wolfSSL:masterfrom
ejohnstown:ccb-phase2-6

Conversation

@ejohnstown

@ejohnstown ejohnstown commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

wolfSSH_CTX_SetChannelReqCb() and wolfSSH_CTX_SetGlobalReqCb() register a callback consulted first for every channel and global request, with the name and the type-specific part to parse.

  • A tri-state answer grants, refuses, or leaves the request to the callbacks and handling already there, so a policy reaches the types with no hook of their own.
  • A grant still parses and records what the library needs, so a granted session request commits the session and the shell, exec and subsystem callbacks are not consulted.
  • A type the library does not know is answered CHANNEL_SUCCESS on a grant; a granted port-0 tcpip-forward is refused, per RFC 4254 7.1.
  • regress.c covers the answers, the data delivered, and which callbacks each answer leaves out.

Copilot AI left a comment

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.

🟡 Changes recommended

There are confirmed correctness/security issues around silently truncated request names/types being passed to the new generic callbacks (and a readiness-state bug in wolfSSH_SFTP_accept() under app-driven mode) that should be addressed before approval.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR adds “generic” (any-name) callbacks for SSH channel requests and global requests, enabling centralized policy decisions (accept/reject/unhandled) before the existing type-specific callbacks and built-in handling. It also introduces an application-driven channel mode that stops wolfSSH_accept() after authentication so applications can drive channel open/request handling via wolfSSH_worker(), with accompanying agent-channel and SFTP adjustments plus expanded unit/regression coverage.

Changes:

  • Add wolfSSH_CTX_SetChannelReqCb() and wolfSSH_CTX_SetGlobalReqCb() to allow first-pass policy decisions for all channel/global requests.
  • Add wolfSSH_{CTX_,}SetAppChannels() and update accept/worker flows to support application-driven channel handling.
  • Add wolfSSH_AGENT_ChannelOpen() helper and extend tests (unit.c, regress.c) to validate callback interactions and app-driven semantics.
File summaries
File Description
wolfssh/ssh.h Public API additions: generic request callback types, tri-state result enum, and app-driven channel mode API/docs.
wolfssh/internal.h Extend WOLFSSH_CTX/WOLFSSH with generic callback pointers and appChannels flags.
wolfssh/agent.h Add public API for server-side agent channel opening in app-driven mode.
src/ssh.c Implement new setters and modify wolfSSH_accept() to support stopping at authenticated state when app-driven.
src/internal.c Route channel/global requests through new generic callbacks; refactor session request handling.
src/wolfsftp.c Adjust SFTP accept logic to account for app-driven accept state behavior.
src/agent.c Implement wolfSSH_AGENT_ChannelOpen() and refactor agent channel open path.
tests/unit.c Add unit coverage around session-request rejection and app-driven “no default callback acceptance” behavior.
tests/regress.c Add regression tests for generic callbacks, app-driven accept stopping point, and callback bypass rules.
Review details
  • Files reviewed: 9/9 changed files
  • Comments generated: 3
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/internal.c Outdated
Comment thread src/internal.c
Comment thread src/wolfsftp.c Outdated

@wolfSSL-Fenrir-bot wolfSSL-Fenrir-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Fenrir Automated Review — PR #1236

Scan targets checked: wolfssh-src, wolfssh-bugs

Findings: 1
1 finding(s) posted as inline comments (see file-level comments below)

This review was generated automatically by Fenrir. Reported findings require changes before merge.

Comment thread src/internal.c Outdated
@ejohnstown
ejohnstown force-pushed the ccb-phase2-6 branch 2 times, most recently from 5ce4c71 to 591ea7d Compare September 14, 2026 22:03
@ejohnstown
ejohnstown marked this pull request as ready for review September 14, 2026 22:06

@wolfSSL-Fenrir-bot wolfSSL-Fenrir-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Fenrir Automated Review — PR #1236

Scan targets checked: wolfssh-src, wolfssh-bugs

Findings: 2
2 finding(s) posted as inline comments (see file-level comments below)

This review was generated automatically by Fenrir. Reported findings require changes before merge.

Comment thread src/internal.c Outdated
Comment thread src/internal.c
wolfSSH_CTX_SetChannelReqAnyCb() and wolfSSH_CTX_SetGlobalReqAnyCb()
register a callback consulted first for a channel or global request,
with the name, the type-specific part, and whether a reply is wanted. A
tri-state answer grants, refuses, or leaves it to the handling already
there, so a policy reaches the types with no hook of their own.

- the name is the one that arrived, since a copy into a buffer truncates
  a long name and ends it at an embedded NUL, and a policy has to answer
  on what the peer sent
- a grant still parses and records what the library needs, so a granted
  session request commits the session, the typed callbacks are not
  consulted, and a granted unknown type is answered CHANNEL_SUCCESS
- a port-0 tcpip-forward skips the callback, since only the forward
  callback can report the port bound and a policy that had bound a
  listener would then have to be refused, per RFC 4254 7.1
- a client refuses tcpip-forward and cancel-tcpip-forward ahead of any
  policy, matched on the name that arrived so it holds in a build with
  no forwarding, where neither name is in the name table
- window-change, exit-status and exit-signal are cleared of a reply
  before the handling runs, so a refusal leaves them unanswered too, per
  RFC 4254 6.7 and 6.10
- regress.c covers the answers, the data delivered, the names that do
  not fit a copy, and which callbacks each answer leaves out
The generic channel request callback may free the channel it was handed,
so DoChannelRequest() looks it up again before the type handling reads
it. Gone, the request ends there, and a reply the peer wanted fails on
the missing channel the way one after a typed session callback does.

- ssh.h says the callback may free its channel and what the request does
  from there
- regress.c frees the channel from the callback on each of the three
  answers, and on a pty-req, the type that wrote to the channel outside
  a session request

@wolfSSL-Fenrir-bot wolfSSL-Fenrir-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Fenrir Automated Review — PR #1236

Scan targets checked: wolfssh-src, wolfssh-bugs

Fenrir result: Approved ✅

No new issues found in the changed files.

Advisory only — this automated result does not count as a GitHub approval.

@wolfSSL-Fenrir-bot
wolfSSL-Fenrir-bot dismissed stale reviews from themself September 14, 2026 22:47

Fenrir's latest completed scan found no issues; clearing the prior automated change request.

@ejohnstown ejohnstown assigned wolfSSL-Bot and unassigned ejohnstown Sep 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants