Authenticate configured WebDAV users with omitted empty passwords
This commit is contained in:
+66
-27
@@ -26,6 +26,28 @@ struct Session {
|
||||
authorization: Option<String>,
|
||||
}
|
||||
|
||||
impl Session {
|
||||
fn from_config(config: &[(String, Setting)]) -> Result<Self, ErrorCode> {
|
||||
let lookup = |wanted: &str| {
|
||||
config
|
||||
.iter()
|
||||
.find(|(key, _)| key == wanted)
|
||||
.and_then(|(_, value)| text(Some(value.clone())))
|
||||
};
|
||||
let root = lookup("url").ok_or(ErrorCode::InvalidInput)?;
|
||||
if !root.starts_with("https://") && !root.starts_with("http://") {
|
||||
return Err(ErrorCode::InvalidInput);
|
||||
}
|
||||
let authorization = lookup("username").map(|username| {
|
||||
dav::basic(&username, &lookup("password").unwrap_or_default())
|
||||
});
|
||||
Ok(Self {
|
||||
root,
|
||||
authorization,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
static SESSION: RefCell<Option<Session>> = const { RefCell::new(None) };
|
||||
}
|
||||
@@ -227,26 +249,7 @@ impl Guest for Webdav {
|
||||
config: Vec<(String, Setting)>,
|
||||
) -> Result<Capabilities, ErrorCode> {
|
||||
SESSION.set(None);
|
||||
let lookup = |wanted: &str| {
|
||||
config
|
||||
.iter()
|
||||
.find(|(key, _)| key == wanted)
|
||||
.and_then(|(_, value)| text(Some(value.clone())))
|
||||
};
|
||||
let root = lookup("url").ok_or(ErrorCode::InvalidInput)?;
|
||||
if !root.starts_with("https://") && !root.starts_with("http://") {
|
||||
return Err(ErrorCode::InvalidInput);
|
||||
}
|
||||
let authorization = match (lookup("username"), lookup("password")) {
|
||||
(Some(username), Some(password)) => {
|
||||
Some(dav::basic(&username, &password))
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
SESSION.set(Some(Session {
|
||||
root,
|
||||
authorization,
|
||||
}));
|
||||
SESSION.set(Some(Session::from_config(&config)?));
|
||||
let probe = Self::stat(Locator::Path("/".to_owned())).and_then(|info| {
|
||||
if matches!(info.kind, EntryKind::Directory) {
|
||||
Ok(())
|
||||
@@ -429,23 +432,59 @@ sdk::export!(Webdav with_types_in sdk);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{SESSION, Session, Webdav, text};
|
||||
use super::{SESSION, Session, Webdav};
|
||||
use crate::sdk::{ErrorCode, Guest, Setting};
|
||||
|
||||
#[tokio::test]
|
||||
async fn passwords_keep_leading_and_trailing_whitespace() {
|
||||
async fn passwords_keep_leading_and_trailing_whitespace()
|
||||
-> Result<(), ErrorCode> {
|
||||
let config = vec![
|
||||
(
|
||||
"url".to_owned(),
|
||||
Setting::Text("https://dav.example/".to_owned()),
|
||||
),
|
||||
("username".to_owned(), Setting::Text("user".to_owned())),
|
||||
(
|
||||
"password".to_owned(),
|
||||
Setting::Secret(" pass word \t".to_owned()),
|
||||
),
|
||||
];
|
||||
assert_eq!(
|
||||
text(Some(Setting::Secret(" pass word \t".to_owned()))),
|
||||
Some(" pass word \t".to_owned())
|
||||
Session::from_config(&config)?.authorization.as_deref(),
|
||||
Some("Basic dXNlcjogcGFzcyB3b3JkIAk=")
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn an_empty_password_still_supplies_basic_auth_credentials() {
|
||||
async fn a_username_without_a_password_setting_sends_basic_auth()
|
||||
-> Result<(), ErrorCode> {
|
||||
let config = vec![
|
||||
(
|
||||
"url".to_owned(),
|
||||
Setting::Text("https://dav.example/".to_owned()),
|
||||
),
|
||||
("username".to_owned(), Setting::Text("user".to_owned())),
|
||||
];
|
||||
assert_eq!(
|
||||
text(Some(Setting::Secret(String::new()))),
|
||||
Some(String::new())
|
||||
Session::from_config(&config)?.authorization.as_deref(),
|
||||
Some("Basic dXNlcjo=")
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn no_username_keeps_the_connection_anonymous() -> Result<(), ErrorCode>
|
||||
{
|
||||
let config = vec![
|
||||
(
|
||||
"url".to_owned(),
|
||||
Setting::Text("https://dav.example/".to_owned()),
|
||||
),
|
||||
("password".to_owned(), Setting::Secret("unused".to_owned())),
|
||||
];
|
||||
assert!(Session::from_config(&config)?.authorization.is_none());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
Reference in New Issue
Block a user