feat(dispatch): land the parse-only dispatch + the fail-closed decline core (w2-dispatch-decline-core)
- src/dispatch.rs: the ExecRoute decision, the skeleton exec-parse probe (service prefix + path shape; wave 3 replaces with the full grammar), the wire-reason shapers (AdministrativelyProhibited for unfeatured/never-feature opens, ConnectFailed for the tunnel seam stub), 7 probe unit rows - src/handler.rs: channel_open_* gates per the feature graph (session ∨ git; tunnel; x11/auth-agent never), parse-only exec_request dispatch before any allocation, session-row routes, request-level declines (subsystem all-names with the sftp OQ-13 and git named classes, env per OQ-09, x11/agent, the four listen requests), the named wave-3 seam stubs; decline-first-alloc-never structural; module docs carry the decline-core contract incl. the inherited auth-agent-open upstream note - tests/dispatch_core.rs: 26 Contract-stamped decline-matrix rows per feature build driven through the loopback harness (none / git-only / session-only / tunnel-only / all-features + shared never-feature rows) - tests/common/harness.rs: extended helper vocabulary (tunnel/x11 opens, pty/env/x11/agent requests, listen requests) — discharges the w2-loopback-harness live-rows note - tests/loopback_harness.rs: the skeleton decline-only session-open row cfg-pinned to the featureless builds it describes Verification: cargo test (91 rows, default build); per-feature dispatch_core rows (git 11 / session 10 / tunnel 4 / all 8 / sftp 3); cargo test --all-features; cargo clippy --all-targets -- -D warnings (and --all-features); cargo fmt --check; cargo doc --no-deps
This commit is contained in:
1 parent
3b77193e85
commit
68d3723f6a
7 files changed
+1543
-12
No files matched your search
@@ -56,6 +56,16 @@
|
||||
//! russh-verbatim shape ([`AuthResult`], [`Error`],
|
||||
//! [`ChannelMsg`]) the rows match on directly.
|
||||
//!
|
||||
//! The helper set grows with the rows it serves: `w2-loopback-harness`
|
||||
//! landed the auth/session/exec/shell/subsystem vocabulary, and
|
||||
//! `w2-dispatch-decline-core` extended it with the decline-matrix
|
||||
//! vocabulary (the tunnel/x11 opens, the pty/env/x11/agent-forward
|
||||
//! requests, the listen requests) — its recorded expectation that the
|
||||
//! "session-request and exit-status/close helpers are exercised by
|
||||
//! construction this wave ... their live rows arrive with
|
||||
//! `w2-dispatch-decline-core`" is discharged by exactly that
|
||||
//! extension, not by a harness rewrite.
|
||||
//!
|
||||
//! Like the doubles: test functions are *rows* carrying the greppable
|
||||
//! **`Contract stamp:`** doc markers (see the common module's doc).
|
||||
|
||||
@@ -264,6 +274,40 @@ pub async fn open_session_channel(
|
||||
client.channel_open_session().await
|
||||
}
|
||||
|
||||
/// Opens a `direct-tcpip` channel — the tunnel open helper (`ssh -L`
|
||||
/// / `ssh -D` traffic). The open-failure shape is the `Err` verbatim,
|
||||
/// the decline-matrix rows' reason surface.
|
||||
pub async fn open_direct_tcpip(
|
||||
client: &Handle<HarnessClientHandler>,
|
||||
host_to_connect: &str,
|
||||
port_to_connect: u32,
|
||||
) -> Result<Channel<Msg>, Error> {
|
||||
client
|
||||
.channel_open_direct_tcpip(host_to_connect, port_to_connect, "harness-originator", 0)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Opens a `direct-streamlocal` channel — the unix-socket forward
|
||||
/// helper. The open-failure shape is the `Err` verbatim.
|
||||
pub async fn open_direct_streamlocal(
|
||||
client: &Handle<HarnessClientHandler>,
|
||||
socket_path: &str,
|
||||
) -> Result<Channel<Msg>, Error> {
|
||||
client.channel_open_direct_streamlocal(socket_path).await
|
||||
}
|
||||
|
||||
/// Opens an x11 channel — the never-feature open helper (ADR-003 §5).
|
||||
/// The open-failure shape is the `Err` verbatim.
|
||||
pub async fn open_x11_channel(
|
||||
client: &Handle<HarnessClientHandler>,
|
||||
originator_address: &str,
|
||||
originator_port: u32,
|
||||
) -> Result<Channel<Msg>, Error> {
|
||||
client
|
||||
.channel_open_x11(originator_address, originator_port)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Sends an exec request over a channel (`want_reply` set — the
|
||||
/// success/failure shape rides [`ChannelMsg::Success`]/[`ChannelMsg::Failure`]
|
||||
/// through [`next_message`]).
|
||||
@@ -281,6 +325,43 @@ pub async fn request_subsystem(channel: &Channel<Msg>, name: &str) -> Result<(),
|
||||
channel.request_subsystem(true, name).await
|
||||
}
|
||||
|
||||
/// Sends a pty request over a channel (`want_reply` set — the pty row
|
||||
/// rides the standard success/failure observation).
|
||||
pub async fn request_pty(channel: &Channel<Msg>) -> Result<(), Error> {
|
||||
channel.request_pty(true, "xterm", 80, 24, 0, 0, &[]).await
|
||||
}
|
||||
|
||||
/// Sends an env request over a channel (`want_reply` set — the OQ-09
|
||||
/// unconditional-decline rows' observation).
|
||||
pub async fn request_env(channel: &Channel<Msg>, name: &str, value: &str) -> Result<(), Error> {
|
||||
channel.set_env(true, name, value).await
|
||||
}
|
||||
|
||||
/// Sends an x11-req request over a channel (`want_reply` set — the
|
||||
/// never-feature request rows).
|
||||
pub async fn request_x11(channel: &Channel<Msg>) -> Result<(), Error> {
|
||||
channel
|
||||
.request_x11(true, false, "MIT-MAGIC-COOKIE-1", "harness-cookie", 0)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Sends an agent-forwarding request over a channel (`want_reply` set
|
||||
/// — the never-feature request rows; ADR-003 §5).
|
||||
pub async fn request_agent_forward(channel: &Channel<Msg>) -> Result<(), Error> {
|
||||
channel.agent_forward(true).await
|
||||
}
|
||||
|
||||
/// Requests a `tcpip-forward` listen (`-R` ingress) — the
|
||||
/// success/failure shape is the result verbatim
|
||||
/// ([`Error::RequestDenied`] on a declined listen).
|
||||
pub async fn tcpip_forward(
|
||||
client: &Handle<HarnessClientHandler>,
|
||||
address: &str,
|
||||
port: u32,
|
||||
) -> Result<u32, Error> {
|
||||
client.tcpip_forward(address, port).await
|
||||
}
|
||||
|
||||
/// Observes the next channel message — `None` after the channel has
|
||||
/// closed (russh's EOF-of-conversation shape).
|
||||
pub async fn next_message(channel: &mut Channel<Msg>) -> Option<ChannelMsg> {
|
||||
|
||||
Reference in new issue
Block a user