Clean up code, add link to etc-passwd crate
This commit is contained in:
parent
0e48e930ba
commit
cc71f5bb9a
File diff suppressed because it is too large
Load Diff
|
@ -180,7 +180,8 @@ pub async fn client_authenticate(
|
|||
}
|
||||
Question::Prompt {
|
||||
prompt,
|
||||
echo,
|
||||
// TODO: implement this
|
||||
echo: _,
|
||||
} => {
|
||||
stdout.write_all(prompt.to_bytes()).await?;
|
||||
stdout.write_all(b" ").await?;
|
||||
|
|
|
@ -41,15 +41,22 @@ async fn server_authorize_key(user_id: Uid, public_key: &ssh_key::public::Public
|
|||
let mut authorized_keys = String::with_capacity(home.len() + PATH.len());
|
||||
authorized_keys.push_str(home);
|
||||
authorized_keys.push_str(PATH);
|
||||
let authorized_keys = tokio::fs::read_to_string(authorized_keys).await?;
|
||||
let mut authorized_keys = ssh_key::authorized_keys::AuthorizedKeys::new(&authorized_keys);
|
||||
match tokio::fs::read_to_string(&authorized_keys).await {
|
||||
Ok(authorized_keys) => {
|
||||
let mut authorized_keys = ssh_key::authorized_keys::AuthorizedKeys::new(&authorized_keys);
|
||||
|
||||
while let Some(r) = authorized_keys.next() {
|
||||
let entry = r?;
|
||||
if entry.public_key().key_data() == public_key.key_data() {
|
||||
return Ok(());
|
||||
while let Some(r) = authorized_keys.next() {
|
||||
let entry = r?;
|
||||
if entry.public_key().key_data() == public_key.key_data() {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {}
|
||||
Err(e) => {
|
||||
error!("unable to read authorized keys file at {:?}: {}", authorized_keys, e);
|
||||
}
|
||||
};
|
||||
Err(anyhow!("Key provided by the client is not authorized to connect"))
|
||||
}
|
||||
|
||||
|
|
96
src/main.rs
96
src/main.rs
|
@ -26,9 +26,7 @@ use std::future::Future;
|
|||
use std::mem::ManuallyDrop;
|
||||
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
|
||||
use std::os::fd::FromRawFd;
|
||||
use std::os::unix::process::CommandExt;
|
||||
use std::pin::Pin;
|
||||
use std::process::Stdio;
|
||||
use std::ptr::NonNull;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
|
@ -40,7 +38,6 @@ use nix::unistd::Uid;
|
|||
use quinn::{ReadExactError, RecvStream, SendStream};
|
||||
use rustls::client::ServerCertVerifier;
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::process::Command;
|
||||
use tracing::Instrument;
|
||||
use user_info::UserInfo;
|
||||
use webpki::SubjectNameRef;
|
||||
|
@ -319,14 +316,6 @@ async fn run_server() -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn is_broken_pipe<T>(r: &Result<T, std::io::Error>) -> bool {
|
||||
if let Err(e) = r {
|
||||
e.kind() == std::io::ErrorKind::BrokenPipe
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn transport_config() -> quinn::TransportConfig {
|
||||
let mut transport = quinn::TransportConfig::default();
|
||||
transport.stream_receive_window((64u32 * 1024 * 1024).into());
|
||||
|
@ -545,7 +534,7 @@ impl ServerCertVerifier for InformedServerCertVerifier {
|
|||
}
|
||||
}
|
||||
|
||||
let cert = webpki::EndEntityCert::try_from(end_entity.0.as_ref()).map_err(pki_error)?;
|
||||
let _cert = webpki::EndEntityCert::try_from(end_entity.0.as_ref()).map_err(pki_error)?;
|
||||
|
||||
let ip_addr_slot;
|
||||
let subject_name = match server_name {
|
||||
|
@ -785,8 +774,7 @@ async fn run_client(mut args: std::env::Args) -> Result<()> {
|
|||
.as_ref()
|
||||
.and_then(|s| s.split_once('@'))
|
||||
.context("Expected an argument of the form USERNAME@HOST")?;
|
||||
let (host_name, port) = host.split_once(':').unwrap_or((host, "8022"));
|
||||
let port = port.parse::<u16>()?;
|
||||
let (host_name, _port) = host.split_once(':').unwrap_or((host, "8022"));
|
||||
|
||||
let mut client_crypto = rustls::ClientConfig::builder()
|
||||
.with_safe_defaults()
|
||||
|
@ -935,7 +923,7 @@ async fn do_forward_to(conn: &quinn::Connection, spec: ForwardSpec) -> Result<()
|
|||
socket.bind(spec.bind.into())?;
|
||||
let list = socket.listen(1024)?;
|
||||
loop {
|
||||
let (mut local_stream, peer) = list.accept().await?;
|
||||
let (mut local_stream, _peer) = list.accept().await?;
|
||||
let (send, recv) = open_stream(
|
||||
conn,
|
||||
&Stream::Forward {
|
||||
|
@ -1083,7 +1071,7 @@ async fn greet_conn(cfg: &'static ServerConfig, conn: quinn::Connecting) -> Resu
|
|||
|
||||
#[cfg(feature = "server")]
|
||||
async fn authenticate_conn(
|
||||
cfg: &'static ServerConfig,
|
||||
_cfg: &'static ServerConfig,
|
||||
conn: &quinn::Connection,
|
||||
) -> Result<(UserInfo, Vec<(CString, CString)>)> {
|
||||
info!("authenticating connection");
|
||||
|
@ -1192,78 +1180,16 @@ async fn handle_conn(
|
|||
}
|
||||
|
||||
async fn handle_stream_exec(
|
||||
cfg: &ServerConfig,
|
||||
mut send: SendStream,
|
||||
mut recv: RecvStream,
|
||||
user_info: &UserInfo,
|
||||
_cfg: &ServerConfig,
|
||||
_send: SendStream,
|
||||
_recv: RecvStream,
|
||||
_user_info: &UserInfo,
|
||||
) -> Result<()> {
|
||||
(|| todo!())();
|
||||
let mut cmd = std::process::Command::new("");
|
||||
cmd.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.stdin(Stdio::piped());
|
||||
#[cfg(target_family = "unix")]
|
||||
cmd.process_group(0);
|
||||
info!("Running {:?}", cmd);
|
||||
let mut sh = Command::from(cmd).kill_on_drop(true).spawn()?;
|
||||
|
||||
let mut stdout = sh.stdout.take().unwrap();
|
||||
let mut stderr = sh.stderr.take().unwrap();
|
||||
let mut stdin = sh.stdin.take().unwrap();
|
||||
let mut stdout_buf = Vec::with_capacity(4096);
|
||||
let mut stderr_buf = Vec::with_capacity(4096);
|
||||
let mut stdin_buf = Vec::with_capacity(4096);
|
||||
|
||||
let mut stdout_eof = false;
|
||||
let mut stderr_eof = false;
|
||||
|
||||
loop {
|
||||
tokio::select! {
|
||||
r = sh.wait() => {
|
||||
let code = r?;
|
||||
send.finish().await?;
|
||||
if !code.success() {
|
||||
info!("Child exit: {}", code);
|
||||
|
||||
recv.stop(1u8.into())?;
|
||||
return Ok(());
|
||||
} else {
|
||||
info!("Child exit");
|
||||
recv.stop(0u8.into())?;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
r = stdout.read_buf(&mut stdout_buf), if !stdout_eof => {
|
||||
if is_broken_pipe(&r) || r? == 0 {
|
||||
stdout_eof = true;
|
||||
info!("stdout eof");
|
||||
} else {
|
||||
send.write_all(&stdout_buf).await?;
|
||||
info!("sent stdout: {:x?}", stdout_buf);
|
||||
stdout_buf.clear();
|
||||
}
|
||||
},
|
||||
r = stderr.read_buf(&mut stderr_buf), if !stderr_eof => {
|
||||
if is_broken_pipe(&r) || r? == 0 {
|
||||
stderr_eof = true;
|
||||
info!("stderr eof");
|
||||
} else {
|
||||
send.write_all(&stderr_buf).await?;
|
||||
stderr_buf.clear();
|
||||
info!("sent stderr: {:x?}", stderr_buf);
|
||||
}
|
||||
},
|
||||
r = recv.read_buf(&mut stdin_buf) => if r? > 0 {
|
||||
stdin.write_all(&stdin_buf).await?;
|
||||
stdin_buf.clear();
|
||||
info!("recv stdin");
|
||||
},
|
||||
}
|
||||
}
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn handle_stream_shell(
|
||||
cfg: &ServerConfig,
|
||||
_cfg: &ServerConfig,
|
||||
mut send: SendStream,
|
||||
mut recv: RecvStream,
|
||||
user_info: &UserInfo,
|
||||
|
@ -1636,7 +1562,7 @@ async fn handle_stream_shell(
|
|||
}
|
||||
|
||||
async fn handle_stream_forward(
|
||||
cfg: &ServerConfig,
|
||||
_cfg: &ServerConfig,
|
||||
send: SendStream,
|
||||
recv: RecvStream,
|
||||
addr: Ipv4Addr,
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
//! Forked from <https://github.com/gifnksm/etc-passwd>.
|
||||
//!
|
||||
//! Get user information stored in the password file `/etc/passwd`.
|
||||
//!
|
||||
//! This crate provides a safe wrapper for libc functions such as [`getpwnam_r(3)`] and [`getpwuid_r(3)`].
|
||||
|
|
Loading…
Reference in New Issue