mirror of
https://github.com/kanidm/kanidm.git
synced 2025-02-23 04:27:02 +01:00
Resolve kanidm-unix auth-test bug (#3405)
* Resolve kanidm-unix auth-test bug When reworking the unix daemon, we missed changing the auth-test tool to handle the new challenge-response flow correctly which would cause the session to disconnect. * Cleanup
This commit is contained in:
parent
f68906bf1b
commit
1f5ce2617d
|
@ -162,7 +162,7 @@ impl PersonOpt {
|
|||
}
|
||||
PersonPosix::SetPassword(aopt) => {
|
||||
let client = aopt.copt.to_client(OpType::Write).await;
|
||||
let password = match password_prompt("Enter new posix (sudo) password: ") {
|
||||
let password = match password_prompt("Enter new posix (sudo) password") {
|
||||
Some(v) => v,
|
||||
None => {
|
||||
println!("Passwords do not match");
|
||||
|
|
|
@ -254,7 +254,7 @@ async fn do_password(
|
|||
password.to_owned()
|
||||
}
|
||||
None => dialoguer::Password::new()
|
||||
.with_prompt("Enter password: ")
|
||||
.with_prompt("Enter password")
|
||||
.interact()
|
||||
.unwrap_or_else(|e| {
|
||||
error!("Failed to create password prompt -- {:?}", e);
|
||||
|
|
|
@ -29,11 +29,11 @@ impl Decoder for ClientCodec {
|
|||
}
|
||||
}
|
||||
|
||||
impl Encoder<ClientRequest> for ClientCodec {
|
||||
impl Encoder<&ClientRequest> for ClientCodec {
|
||||
type Error = IoError;
|
||||
|
||||
fn encode(&mut self, msg: ClientRequest, dst: &mut BytesMut) -> Result<(), Self::Error> {
|
||||
let data = serde_json::to_vec(&msg).map_err(|e| {
|
||||
fn encode(&mut self, msg: &ClientRequest, dst: &mut BytesMut) -> Result<(), Self::Error> {
|
||||
let data = serde_json::to_vec(msg).map_err(|e| {
|
||||
error!("socket encoding error -> {:?}", e);
|
||||
IoError::new(ErrorKind::Other, "JSON encode error")
|
||||
})?;
|
||||
|
@ -49,21 +49,36 @@ impl ClientCodec {
|
|||
}
|
||||
}
|
||||
|
||||
async fn call_daemon_inner(
|
||||
path: &str,
|
||||
req: ClientRequest,
|
||||
) -> Result<ClientResponse, Box<dyn Error>> {
|
||||
trace!(?path, ?req);
|
||||
let stream = UnixStream::connect(path).await?;
|
||||
pub struct DaemonClient {
|
||||
req_stream: Framed<UnixStream, ClientCodec>,
|
||||
default_timeout: u64,
|
||||
}
|
||||
|
||||
impl DaemonClient {
|
||||
pub async fn new(path: &str, default_timeout: u64) -> Result<Self, Box<dyn Error>> {
|
||||
trace!(?path);
|
||||
let stream = UnixStream::connect(path).await.inspect_err(|e| {
|
||||
error!(
|
||||
"Unix socket stream setup error while connecting to {} -> {:?}",
|
||||
path, e
|
||||
);
|
||||
})?;
|
||||
|
||||
let req_stream = Framed::new(stream, ClientCodec::new());
|
||||
|
||||
trace!("connected");
|
||||
|
||||
let mut reqs = Framed::new(stream, ClientCodec::new());
|
||||
Ok(DaemonClient {
|
||||
req_stream,
|
||||
default_timeout,
|
||||
})
|
||||
}
|
||||
|
||||
reqs.send(req).await?;
|
||||
reqs.flush().await?;
|
||||
async fn call_inner(&mut self, req: &ClientRequest) -> Result<ClientResponse, Box<dyn Error>> {
|
||||
self.req_stream.send(req).await?;
|
||||
self.req_stream.flush().await?;
|
||||
trace!("flushed, waiting ...");
|
||||
|
||||
match reqs.next().await {
|
||||
match self.req_stream.next().await {
|
||||
Some(Ok(res)) => {
|
||||
debug!("Response -> {:?}", res);
|
||||
Ok(res)
|
||||
|
@ -75,13 +90,12 @@ async fn call_daemon_inner(
|
|||
}
|
||||
}
|
||||
|
||||
/// Makes a call to kanidm_unixd via a unix socket at `path`
|
||||
pub async fn call_daemon(
|
||||
path: &str,
|
||||
req: ClientRequest,
|
||||
timeout: u64,
|
||||
pub async fn call(
|
||||
&mut self,
|
||||
req: &ClientRequest,
|
||||
timeout: Option<u64>,
|
||||
) -> Result<ClientResponse, Box<dyn Error>> {
|
||||
let sleep = time::sleep(Duration::from_secs(timeout));
|
||||
let sleep = time::sleep(Duration::from_secs(timeout.unwrap_or(self.default_timeout)));
|
||||
tokio::pin!(sleep);
|
||||
|
||||
tokio::select! {
|
||||
|
@ -89,8 +103,9 @@ pub async fn call_daemon(
|
|||
error!(?timeout, "Timed out making request to kanidm_unixd");
|
||||
Err(Box::new(IoError::new(ErrorKind::Other, "timeout")))
|
||||
}
|
||||
res = call_daemon_inner(path, req) => {
|
||||
res = self.call_inner(req) => {
|
||||
res
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,17 +16,55 @@ extern crate tracing;
|
|||
use std::process::ExitCode;
|
||||
|
||||
use clap::Parser;
|
||||
use kanidm_unix_common::client::call_daemon;
|
||||
use kanidm_unix_common::client::DaemonClient;
|
||||
use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH;
|
||||
use kanidm_unix_common::unix_config::KanidmUnixdConfig;
|
||||
use kanidm_unix_common::unix_proto::{
|
||||
ClientRequest, ClientResponse, PamAuthRequest, PamAuthResponse, PamServiceInfo,
|
||||
};
|
||||
// use std::io;
|
||||
use std::path::PathBuf;
|
||||
|
||||
include!("../opt/tool.rs");
|
||||
|
||||
macro_rules! setup_client {
|
||||
() => {{
|
||||
let Ok(cfg) =
|
||||
KanidmUnixdConfig::new().read_options_from_optional_config(DEFAULT_CONFIG_PATH)
|
||||
else {
|
||||
error!("Failed to parse {}", DEFAULT_CONFIG_PATH);
|
||||
return ExitCode::FAILURE;
|
||||
};
|
||||
|
||||
debug!("Connecting to resolver ...");
|
||||
|
||||
debug!(
|
||||
"Using kanidm_unixd socket path: {:?}",
|
||||
cfg.sock_path.as_str()
|
||||
);
|
||||
|
||||
// see if the kanidm_unixd socket exists and quit if not
|
||||
if !PathBuf::from(&cfg.sock_path).exists() {
|
||||
error!(
|
||||
"Failed to find unix socket at {}, quitting!",
|
||||
cfg.sock_path.as_str()
|
||||
);
|
||||
return ExitCode::FAILURE;
|
||||
}
|
||||
|
||||
match DaemonClient::new(cfg.sock_path.as_str(), cfg.unix_sock_timeout).await {
|
||||
Ok(dc) => dc,
|
||||
Err(err) => {
|
||||
error!(
|
||||
"Failed to connect to resolver at {}-> {:?}",
|
||||
cfg.sock_path.as_str(),
|
||||
err
|
||||
);
|
||||
return ExitCode::FAILURE;
|
||||
}
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
async fn main() -> ExitCode {
|
||||
let opt = KanidmUnixParser::parse();
|
||||
|
@ -54,12 +92,7 @@ async fn main() -> ExitCode {
|
|||
} => {
|
||||
debug!("Starting PAM auth tester tool ...");
|
||||
|
||||
let Ok(cfg) =
|
||||
KanidmUnixdConfig::new().read_options_from_optional_config(DEFAULT_CONFIG_PATH)
|
||||
else {
|
||||
error!("Failed to parse {}", DEFAULT_CONFIG_PATH);
|
||||
return ExitCode::FAILURE;
|
||||
};
|
||||
let mut daemon_client = setup_client!();
|
||||
|
||||
info!("Sending request for user {}", &account_id);
|
||||
|
||||
|
@ -72,7 +105,7 @@ async fn main() -> ExitCode {
|
|||
},
|
||||
};
|
||||
loop {
|
||||
match call_daemon(cfg.sock_path.as_str(), req, cfg.unix_sock_timeout).await {
|
||||
match daemon_client.call(&req, None).await {
|
||||
Ok(r) => match r {
|
||||
ClientResponse::PamAuthenticateStepResponse(PamAuthResponse::Success) => {
|
||||
println!("auth success!");
|
||||
|
@ -90,7 +123,7 @@ async fn main() -> ExitCode {
|
|||
ClientResponse::PamAuthenticateStepResponse(PamAuthResponse::Password) => {
|
||||
// Prompt for and get the password
|
||||
let cred = match dialoguer::Password::new()
|
||||
.with_prompt("Enter Unix password: ")
|
||||
.with_prompt("Enter Unix password")
|
||||
.interact()
|
||||
{
|
||||
Ok(p) => p,
|
||||
|
@ -133,7 +166,7 @@ async fn main() -> ExitCode {
|
|||
|
||||
let sereq = ClientRequest::PamAccountAllowed(account_id);
|
||||
|
||||
match call_daemon(cfg.sock_path.as_str(), sereq, cfg.unix_sock_timeout).await {
|
||||
match daemon_client.call(&sereq, None).await {
|
||||
Ok(r) => match r {
|
||||
ClientResponse::PamStatus(Some(true)) => {
|
||||
println!("account success!");
|
||||
|
@ -158,15 +191,7 @@ async fn main() -> ExitCode {
|
|||
KanidmUnixOpt::CacheClear { debug: _, really } => {
|
||||
debug!("Starting cache clear tool ...");
|
||||
|
||||
let cfg = match KanidmUnixdConfig::new()
|
||||
.read_options_from_optional_config(DEFAULT_CONFIG_PATH)
|
||||
{
|
||||
Ok(c) => c,
|
||||
Err(_e) => {
|
||||
error!("Failed to parse {}", DEFAULT_CONFIG_PATH);
|
||||
return ExitCode::FAILURE;
|
||||
}
|
||||
};
|
||||
let mut daemon_client = setup_client!();
|
||||
|
||||
if !really {
|
||||
error!("Are you sure you want to proceed? If so use --really");
|
||||
|
@ -175,7 +200,7 @@ async fn main() -> ExitCode {
|
|||
|
||||
let req = ClientRequest::ClearCache;
|
||||
|
||||
match call_daemon(cfg.sock_path.as_str(), req, cfg.unix_sock_timeout).await {
|
||||
match daemon_client.call(&req, None).await {
|
||||
Ok(r) => match r {
|
||||
ClientResponse::Ok => info!("success"),
|
||||
_ => {
|
||||
|
@ -192,19 +217,11 @@ async fn main() -> ExitCode {
|
|||
KanidmUnixOpt::CacheInvalidate { debug: _ } => {
|
||||
debug!("Starting cache invalidate tool ...");
|
||||
|
||||
let cfg = match KanidmUnixdConfig::new()
|
||||
.read_options_from_optional_config(DEFAULT_CONFIG_PATH)
|
||||
{
|
||||
Ok(c) => c,
|
||||
Err(_e) => {
|
||||
error!("Failed to parse {}", DEFAULT_CONFIG_PATH);
|
||||
return ExitCode::FAILURE;
|
||||
}
|
||||
};
|
||||
let mut daemon_client = setup_client!();
|
||||
|
||||
let req = ClientRequest::InvalidateCache;
|
||||
|
||||
match call_daemon(cfg.sock_path.as_str(), req, cfg.unix_sock_timeout).await {
|
||||
match daemon_client.call(&req, None).await {
|
||||
Ok(r) => match r {
|
||||
ClientResponse::Ok => info!("success"),
|
||||
_ => {
|
||||
|
@ -221,26 +238,10 @@ async fn main() -> ExitCode {
|
|||
KanidmUnixOpt::Status { debug: _ } => {
|
||||
trace!("Starting cache status tool ...");
|
||||
|
||||
let cfg = match KanidmUnixdConfig::new()
|
||||
.read_options_from_optional_config(DEFAULT_CONFIG_PATH)
|
||||
{
|
||||
Ok(c) => c,
|
||||
Err(_e) => {
|
||||
error!("Failed to parse {}", DEFAULT_CONFIG_PATH);
|
||||
return ExitCode::FAILURE;
|
||||
}
|
||||
};
|
||||
|
||||
let mut daemon_client = setup_client!();
|
||||
let req = ClientRequest::Status;
|
||||
|
||||
let spath = PathBuf::from(cfg.sock_path.as_str());
|
||||
if !spath.exists() {
|
||||
error!(
|
||||
"kanidm_unixd socket {} does not exist - is the service running?",
|
||||
cfg.sock_path
|
||||
)
|
||||
} else {
|
||||
match call_daemon(cfg.sock_path.as_str(), req, cfg.unix_sock_timeout).await {
|
||||
match daemon_client.call(&req, None).await {
|
||||
Ok(r) => match r {
|
||||
ClientResponse::ProviderStatus(results) => {
|
||||
for provider in results {
|
||||
|
@ -259,7 +260,6 @@ async fn main() -> ExitCode {
|
|||
error!("Error -> {:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
ExitCode::SUCCESS
|
||||
}
|
||||
KanidmUnixOpt::Version { debug: _ } => {
|
||||
|
|
|
@ -17,7 +17,7 @@ use std::path::PathBuf;
|
|||
use std::process::ExitCode;
|
||||
|
||||
use clap::Parser;
|
||||
use kanidm_unix_common::client::call_daemon;
|
||||
use kanidm_unix_common::client::DaemonClient;
|
||||
use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH;
|
||||
use kanidm_unix_common::unix_config::KanidmUnixdConfig;
|
||||
use kanidm_unix_common::unix_proto::{ClientRequest, ClientResponse};
|
||||
|
@ -66,21 +66,37 @@ async fn main() -> ExitCode {
|
|||
);
|
||||
return ExitCode::FAILURE;
|
||||
}
|
||||
|
||||
let mut daemon_client =
|
||||
match DaemonClient::new(cfg.sock_path.as_str(), cfg.unix_sock_timeout).await {
|
||||
Ok(dc) => dc,
|
||||
Err(err) => {
|
||||
error!(
|
||||
"Failed to connect to resolver at {}-> {:?}",
|
||||
cfg.sock_path.as_str(),
|
||||
err
|
||||
);
|
||||
return ExitCode::FAILURE;
|
||||
}
|
||||
};
|
||||
|
||||
// safe because we've already thrown an error if it's not there
|
||||
let req = ClientRequest::SshKey(opt.account_id.unwrap_or("".to_string()));
|
||||
|
||||
match call_daemon(cfg.sock_path.as_str(), req, cfg.unix_sock_timeout).await {
|
||||
Ok(r) => match r {
|
||||
ClientResponse::SshKeys(sk) => sk.iter().for_each(|k| {
|
||||
match daemon_client.call(&req, None).await {
|
||||
Ok(ClientResponse::SshKeys(sk)) => {
|
||||
sk.iter().for_each(|k| {
|
||||
println!("{}", k);
|
||||
}),
|
||||
_ => {
|
||||
error!("Error calling kanidm_unixd: unexpected response -> {:?}", r);
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
error!("Error calling kanidm_unixd -> {:?}", e);
|
||||
}
|
||||
};
|
||||
});
|
||||
ExitCode::SUCCESS
|
||||
}
|
||||
Ok(r) => {
|
||||
error!("Error calling kanidm_unixd: unexpected response -> {:?}", r);
|
||||
ExitCode::FAILURE
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Error calling kanidm_unixd -> {:?}", e);
|
||||
ExitCode::FAILURE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue