10
Cargo.toml
10
Cargo.toml
@@ -223,6 +223,11 @@ version = "0.1.3"
|
|||||||
[workspace.dependencies.itertools]
|
[workspace.dependencies.itertools]
|
||||||
version = "0.14.0"
|
version = "0.14.0"
|
||||||
|
|
||||||
|
[workspace.dependencies.ldap3]
|
||||||
|
version = "0.11"
|
||||||
|
default-features = false
|
||||||
|
features = ["sync", "tls-rustls"]
|
||||||
|
|
||||||
[workspace.dependencies.libc]
|
[workspace.dependencies.libc]
|
||||||
version = "0.2"
|
version = "0.2"
|
||||||
|
|
||||||
@@ -549,11 +554,6 @@ features = ["serde"]
|
|||||||
version = "2.0.1"
|
version = "2.0.1"
|
||||||
default-features = false
|
default-features = false
|
||||||
|
|
||||||
[workspace.dependencies.ldap3]
|
|
||||||
version = "0.11"
|
|
||||||
default-features = false
|
|
||||||
features = ["sync", "tls-rustls"]
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Patches
|
# Patches
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -49,6 +49,9 @@ jemalloc_stats = [
|
|||||||
"tuwunel-core/jemalloc_stats",
|
"tuwunel-core/jemalloc_stats",
|
||||||
"tuwunel-service/jemalloc_stats",
|
"tuwunel-service/jemalloc_stats",
|
||||||
]
|
]
|
||||||
|
ldap = [
|
||||||
|
"tuwunel-service/ldap",
|
||||||
|
]
|
||||||
release_max_log_level = [
|
release_max_log_level = [
|
||||||
"tuwunel-core/release_max_log_level",
|
"tuwunel-core/release_max_log_level",
|
||||||
"tuwunel-service/release_max_log_level",
|
"tuwunel-service/release_max_log_level",
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ pub(crate) async fn login_route(
|
|||||||
return Err!(Request(Unknown("User ID does not belong to this homeserver")));
|
return Err!(Request(Unknown("User ID does not belong to this homeserver")));
|
||||||
}
|
}
|
||||||
|
|
||||||
if services.config.ldap.enable {
|
if cfg!(feature = "ldap") && services.config.ldap.enable {
|
||||||
ldap_login(&services, &user_id, &lowercased_user_id, password).await?
|
ldap_login(&services, &user_id, &lowercased_user_id, password).await?
|
||||||
} else {
|
} else {
|
||||||
password_login(&services, &user_id, &lowercased_user_id, password).await?
|
password_login(&services, &user_id, &lowercased_user_id, password).await?
|
||||||
|
|||||||
@@ -93,6 +93,10 @@ jemalloc_stats = [
|
|||||||
jemalloc_conf = [
|
jemalloc_conf = [
|
||||||
"tuwunel-core/jemalloc_conf",
|
"tuwunel-core/jemalloc_conf",
|
||||||
]
|
]
|
||||||
|
ldap = [
|
||||||
|
"tuwunel-api/ldap",
|
||||||
|
"tuwunel-service/ldap",
|
||||||
|
]
|
||||||
media_thumbnail = [
|
media_thumbnail = [
|
||||||
"tuwunel-service/media_thumbnail",
|
"tuwunel-service/media_thumbnail",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -53,6 +53,9 @@ jemalloc_stats = [
|
|||||||
"tuwunel-core/jemalloc_stats",
|
"tuwunel-core/jemalloc_stats",
|
||||||
"tuwunel-database/jemalloc_stats",
|
"tuwunel-database/jemalloc_stats",
|
||||||
]
|
]
|
||||||
|
ldap = [
|
||||||
|
"dep:ldap3",
|
||||||
|
]
|
||||||
media_thumbnail = [
|
media_thumbnail = [
|
||||||
"dep:image",
|
"dep:image",
|
||||||
]
|
]
|
||||||
@@ -88,6 +91,7 @@ image.optional = true
|
|||||||
ipaddress.workspace = true
|
ipaddress.workspace = true
|
||||||
itertools.workspace = true
|
itertools.workspace = true
|
||||||
ldap3.workspace = true
|
ldap3.workspace = true
|
||||||
|
ldap3.optional = true
|
||||||
log.workspace = true
|
log.workspace = true
|
||||||
loole.workspace = true
|
loole.workspace = true
|
||||||
lru-cache.workspace = true
|
lru-cache.workspace = true
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
use std::{collections::BTreeMap, mem, sync::Arc};
|
use std::{collections::BTreeMap, mem, sync::Arc};
|
||||||
|
|
||||||
use futures::{Stream, StreamExt, TryFutureExt};
|
use futures::{Stream, StreamExt, TryFutureExt};
|
||||||
use itertools::Itertools;
|
|
||||||
use ldap3::{LdapConnAsync, Scope, SearchEntry};
|
|
||||||
use ruma::{
|
use ruma::{
|
||||||
DeviceId, KeyId, MilliSecondsSinceUnixEpoch, OneTimeKeyAlgorithm, OneTimeKeyId,
|
DeviceId, KeyId, MilliSecondsSinceUnixEpoch, OneTimeKeyAlgorithm, OneTimeKeyId,
|
||||||
OneTimeKeyName, OwnedDeviceId, OwnedKeyId, OwnedMxcUri, OwnedUserId, RoomId, UInt, UserId,
|
OneTimeKeyName, OwnedDeviceId, OwnedKeyId, OwnedMxcUri, OwnedUserId, RoomId, UInt, UserId,
|
||||||
@@ -15,8 +13,8 @@ use ruma::{
|
|||||||
};
|
};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use tuwunel_core::{
|
use tuwunel_core::{
|
||||||
Err, Error, Result, Server, at, debug, debug_warn, err, error, trace,
|
Err, Error, Result, Server, at, debug_warn, err, trace,
|
||||||
utils::{self, ReadyExt, result::LogErr, stream::TryIgnore, string::Unquoted},
|
utils::{self, ReadyExt, stream::TryIgnore, string::Unquoted},
|
||||||
};
|
};
|
||||||
use tuwunel_database::{Deserialized, Ignore, Interfix, Json, Map};
|
use tuwunel_database::{Deserialized, Ignore, Interfix, Json, Map};
|
||||||
|
|
||||||
@@ -249,30 +247,32 @@ impl Service {
|
|||||||
// Cannot change the password of a LDAP user. There are two special cases :
|
// Cannot change the password of a LDAP user. There are two special cases :
|
||||||
// - a `None` password can be used to deactivate a LDAP user
|
// - a `None` password can be used to deactivate a LDAP user
|
||||||
// - a "*" password is used as the default password of an active LDAP user
|
// - a "*" password is used as the default password of an active LDAP user
|
||||||
if self
|
if cfg!(feature = "ldap")
|
||||||
.db
|
&& password.is_some()
|
||||||
.userid_origin
|
|
||||||
.get(user_id)
|
|
||||||
.await
|
|
||||||
.deserialized::<String>()?
|
|
||||||
== "ldap" && password.is_some()
|
|
||||||
&& password != Some("*")
|
&& password != Some("*")
|
||||||
|
&& self
|
||||||
|
.db
|
||||||
|
.userid_origin
|
||||||
|
.get(user_id)
|
||||||
|
.await
|
||||||
|
.deserialized::<String>()?
|
||||||
|
== "ldap"
|
||||||
{
|
{
|
||||||
Err!(Request(InvalidParam("Cannot change password of a LDAP user")))
|
return Err!(Request(InvalidParam("Cannot change password of a LDAP user")));
|
||||||
} else {
|
|
||||||
password
|
|
||||||
.map(utils::hash::password)
|
|
||||||
.transpose()
|
|
||||||
.map_err(|e| {
|
|
||||||
err!(Request(InvalidParam("Password does not meet the requirements: {e}")))
|
|
||||||
})?
|
|
||||||
.map_or_else(
|
|
||||||
|| self.db.userid_password.insert(user_id, b""),
|
|
||||||
|hash| self.db.userid_password.insert(user_id, hash),
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
password
|
||||||
|
.map(utils::hash::password)
|
||||||
|
.transpose()
|
||||||
|
.map_err(|e| {
|
||||||
|
err!(Request(InvalidParam("Password does not meet the requirements: {e}")))
|
||||||
|
})?
|
||||||
|
.map_or_else(
|
||||||
|
|| self.db.userid_password.insert(user_id, b""),
|
||||||
|
|hash| self.db.userid_password.insert(user_id, hash),
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the displayname of a user on this homeserver.
|
/// Returns the displayname of a user on this homeserver.
|
||||||
@@ -1178,7 +1178,12 @@ impl Service {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ldap")]
|
||||||
pub async fn search_ldap(&self, user_id: &UserId) -> Result<Vec<String>> {
|
pub async fn search_ldap(&self, user_id: &UserId) -> Result<Vec<String>> {
|
||||||
|
use itertools::Itertools;
|
||||||
|
use ldap3::{LdapConnAsync, Scope, SearchEntry};
|
||||||
|
use tuwunel_core::{debug, error, result::LogErr};
|
||||||
|
|
||||||
let config = &self.services.server.config.ldap;
|
let config = &self.services.server.config.ldap;
|
||||||
let (conn, mut ldap) = LdapConnAsync::new(config.uri.as_str())
|
let (conn, mut ldap) = LdapConnAsync::new(config.uri.as_str())
|
||||||
.await
|
.await
|
||||||
@@ -1239,7 +1244,16 @@ impl Service {
|
|||||||
Ok(dns)
|
Ok(dns)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ldap"))]
|
||||||
|
pub async fn search_ldap(&self, _user_id: &UserId) -> Result<Vec<String>> {
|
||||||
|
Err!(FeatureDisabled("ldap"))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ldap")]
|
||||||
pub async fn auth_ldap(&self, user_dn: &str, password: &str) -> Result {
|
pub async fn auth_ldap(&self, user_dn: &str, password: &str) -> Result {
|
||||||
|
use ldap3::LdapConnAsync;
|
||||||
|
use tuwunel_core::{debug, error, result::LogErr};
|
||||||
|
|
||||||
let config = &self.services.server.config.ldap;
|
let config = &self.services.server.config.ldap;
|
||||||
let (conn, mut ldap) = LdapConnAsync::new(config.uri.as_str())
|
let (conn, mut ldap) = LdapConnAsync::new(config.uri.as_str())
|
||||||
.await
|
.await
|
||||||
@@ -1267,6 +1281,11 @@ impl Service {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ldap"))]
|
||||||
|
pub async fn auth_ldap(&self, _user_dn: &str, _password: &str) -> Result {
|
||||||
|
Err!(FeatureDisabled("ldap"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_master_key(
|
pub fn parse_master_key(
|
||||||
|
|||||||
Reference in New Issue
Block a user