Skip to content

Commit 8c3fb5b

Browse files
committed
Add example illustrating retrieving underlying socket info
Signed-off-by: Wiktor Kwapisiewicz <wiktor@metacode.biz>
1 parent 42fa2a4 commit 8c3fb5b

File tree

1 file changed

+82
-0
lines changed

1 file changed

+82
-0
lines changed

examples/agent-socket-info.rs

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
//! This example shows how to access the underlying socket info.
2+
//! The socket info can be used to implement fine-grained access controls based on UID/GID.
3+
//!
4+
//! Run the example with: `cargo run --example agent-socket-info -- -H unix:///tmp/sock`
5+
//! Then inspect the socket info with: `SSH_AUTH_SOCK=/tmp/sock ssh-add -L` which should display
6+
//! something like this:
7+
//!
8+
//! ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA unix: addr: (unnamed) cred: UCred { pid: Some(68463), uid: 1000, gid: 1000 }
9+
10+
use clap::Parser;
11+
use service_binding::Binding;
12+
use ssh_agent_lib::{
13+
agent::{bind, Agent, Session},
14+
error::AgentError,
15+
proto::Identity,
16+
};
17+
use ssh_key::public::KeyData;
18+
use testresult::TestResult;
19+
20+
#[derive(Debug, Default)]
21+
struct AgentSocketInfo {
22+
comment: String,
23+
}
24+
25+
#[ssh_agent_lib::async_trait]
26+
impl Session for AgentSocketInfo {
27+
async fn request_identities(&mut self) -> Result<Vec<Identity>, AgentError> {
28+
Ok(vec![Identity {
29+
// this is just a dummy key, the comment is important
30+
pubkey: KeyData::Ed25519(ssh_key::public::Ed25519PublicKey([0; 32])),
31+
comment: self.comment.clone(),
32+
}])
33+
}
34+
}
35+
36+
#[cfg(unix)]
37+
impl Agent<tokio::net::UnixListener> for AgentSocketInfo {
38+
fn new_session(&mut self, socket: &tokio::net::UnixStream) -> impl Session {
39+
Self {
40+
comment: format!(
41+
"unix: addr: {:?} cred: {:?}",
42+
socket.peer_addr().unwrap(),
43+
socket.peer_cred().unwrap()
44+
),
45+
}
46+
}
47+
}
48+
49+
impl Agent<tokio::net::TcpListener> for AgentSocketInfo {
50+
fn new_session(&mut self, _socket: &tokio::net::TcpStream) -> impl Session {
51+
Self {
52+
comment: "tcp".into(),
53+
}
54+
}
55+
}
56+
57+
#[cfg(windows)]
58+
impl Agent<ssh_agent_lib::agent::NamedPipeListener> for AgentSocketInfo {
59+
fn new_session(
60+
&mut self,
61+
_socket: &tokio::net::windows::named_pipe::NamedPipeServer,
62+
) -> impl Session {
63+
Self {
64+
comment: "pipe".into(),
65+
}
66+
}
67+
}
68+
69+
#[derive(Debug, Parser)]
70+
struct Args {
71+
#[clap(short = 'H', long)]
72+
host: Binding,
73+
}
74+
75+
#[tokio::main]
76+
async fn main() -> TestResult {
77+
env_logger::init();
78+
79+
let args = Args::parse();
80+
bind(args.host.try_into()?, AgentSocketInfo::default()).await?;
81+
Ok(())
82+
}

0 commit comments

Comments
 (0)