(
&mut self,
channel: ChannelId,
name: &str,
session: &mut Session,
)
| 446 | } |
| 447 | |
| 448 | async fn subsystem_request( |
| 449 | &mut self, |
| 450 | channel: ChannelId, |
| 451 | name: &str, |
| 452 | session: &mut Session, |
| 453 | ) -> Result<(), Self::Error> { |
| 454 | if name == "sftp" { |
| 455 | session.channel_success(channel)?; |
| 456 | // sftp-server speaks the SFTP binary protocol over stdin/stdout, |
| 457 | // which is exactly what spawn_pipe_exec wires up. This enables |
| 458 | // modern scp (SFTP-based, OpenSSH 9.0+) and SFTP clients to |
| 459 | // transfer files into and out of the sandbox. |
| 460 | let input_sender = spawn_pipe_exec( |
| 461 | &self.policy, |
| 462 | self.workdir.clone(), |
| 463 | Some("/usr/lib/openssh/sftp-server".to_string()), |
| 464 | session.handle(), |
| 465 | channel, |
| 466 | self.netns_fd, |
| 467 | self.proxy_url.clone(), |
| 468 | self.ca_file_paths.clone(), |
| 469 | &self.provider_credentials.child_env_with_gcp_resolved(), |
| 470 | &self.user_environment, |
| 471 | )?; |
| 472 | let state = self.channels.get_mut(&channel).ok_or_else(|| { |
| 473 | anyhow::anyhow!("subsystem_request on unknown channel {channel:?}") |
| 474 | })?; |
| 475 | state.input_sender = Some(input_sender); |
| 476 | } else { |
| 477 | ocsf_emit!( |
| 478 | SshActivityBuilder::new(openshell_ocsf::ctx::ctx()) |
| 479 | .activity(ActivityId::Refuse) |
| 480 | .action(ActionId::Denied) |
| 481 | .disposition(DispositionId::Rejected) |
| 482 | .severity(SeverityId::Medium) |
| 483 | .message(format!("unsupported subsystem requested: {name}")) |
| 484 | .build() |
| 485 | ); |
| 486 | session.channel_failure(channel)?; |
| 487 | } |
| 488 | Ok(()) |
| 489 | } |
| 490 | |
| 491 | async fn env_request( |
| 492 | &mut self, |
nothing calls this directly
no test coverage detected