JMAP Registry API implementation - part 6
This commit is contained in:
@@ -11,13 +11,18 @@ use ldap3::LdapConnSettings;
|
||||
use registry::schema::structs;
|
||||
|
||||
impl LdapDirectory {
|
||||
pub fn open(config: structs::LdapDirectory) -> Result<Directory, String> {
|
||||
pub async fn open(config: structs::LdapDirectory) -> Result<Directory, String> {
|
||||
let bind_dn = if let Some(dn) = config.bind_dn {
|
||||
Bind::new(
|
||||
dn,
|
||||
config.bind_secret.ok_or_else(|| {
|
||||
"LDAP bind password is required when bind DN is set".to_string()
|
||||
})?,
|
||||
config
|
||||
.bind_secret
|
||||
.secret()
|
||||
.await?
|
||||
.map(|v| v.into_owned())
|
||||
.ok_or_else(|| {
|
||||
"LDAP bind password is required when bind DN is set".to_string()
|
||||
})?,
|
||||
)
|
||||
.into()
|
||||
} else {
|
||||
|
||||
@@ -9,7 +9,7 @@ use crate::Directory;
|
||||
use registry::schema::structs;
|
||||
|
||||
impl OpenIdDirectory {
|
||||
pub fn open(config: structs::OidcDirectory) -> Result<Directory, String> {
|
||||
pub async fn open(config: structs::OidcDirectory) -> Result<Directory, String> {
|
||||
Ok(Directory::OpenId(match config {
|
||||
structs::OidcDirectory::UserInfo(config) => OpenIdDirectory::UserInfo {
|
||||
endpoint: config.endpoint,
|
||||
@@ -19,12 +19,15 @@ impl OpenIdDirectory {
|
||||
claim_name: config.claim_name,
|
||||
},
|
||||
structs::OidcDirectory::Introspect(config) => {
|
||||
let client = config.http_auth.build_http_client(
|
||||
config.http_headers,
|
||||
None,
|
||||
config.timeout,
|
||||
config.allow_invalid_certs,
|
||||
)?;
|
||||
let client = config
|
||||
.http_auth
|
||||
.build_http_client(
|
||||
config.http_headers,
|
||||
None,
|
||||
config.timeout,
|
||||
config.allow_invalid_certs,
|
||||
)
|
||||
.await?;
|
||||
OpenIdDirectory::Introspect {
|
||||
client,
|
||||
endpoint: config.endpoint,
|
||||
|
||||
@@ -22,11 +22,11 @@ impl Directories {
|
||||
for directory in bp.list_infallible::<structs::Directory>().await {
|
||||
let id = directory.id;
|
||||
let result = match directory.object {
|
||||
structs::Directory::Ldap(directory) => LdapDirectory::open(directory),
|
||||
structs::Directory::Ldap(directory) => LdapDirectory::open(directory).await,
|
||||
structs::Directory::Sql(directory) => {
|
||||
SqlDirectory::open(directory, &bp.data_store).await
|
||||
}
|
||||
structs::Directory::Oidc(directory) => OpenIdDirectory::open(directory),
|
||||
structs::Directory::Oidc(directory) => OpenIdDirectory::open(directory).await,
|
||||
};
|
||||
|
||||
match result {
|
||||
|
||||
@@ -5,11 +5,15 @@
|
||||
*/
|
||||
|
||||
use argon2::Argon2;
|
||||
use argon2::PasswordHasher;
|
||||
use mail_builder::encoders::base64::base64_encode;
|
||||
use mail_parser::decoders::base64::base64_decode;
|
||||
use password_hash::PasswordHash;
|
||||
use password_hash::SaltString;
|
||||
use password_hash::rand_core::OsRng;
|
||||
use pbkdf2::Pbkdf2;
|
||||
use pwhash::{bcrypt, bsdi_crypt, md5_crypt, sha1_crypt, sha256_crypt, sha512_crypt, unix_crypt};
|
||||
use registry::schema::enums::PasswordHashAlgorithm;
|
||||
use scrypt::Scrypt;
|
||||
use sha1::Digest;
|
||||
use sha1::Sha1;
|
||||
@@ -219,3 +223,50 @@ pub async fn verify_secret_hash(hashed_secret: &str, secret: &[u8]) -> trc::Resu
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn hash_secret(algorithm: PasswordHashAlgorithm, secret: String) -> trc::Result<String> {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
tokio::task::spawn_blocking(move || {
|
||||
let salt = SaltString::generate(&mut OsRng);
|
||||
|
||||
let result = match algorithm {
|
||||
PasswordHashAlgorithm::Argon2id => {
|
||||
let hasher = Argon2::default();
|
||||
hasher
|
||||
.hash_password(secret.as_bytes(), &salt)
|
||||
.map(|h| h.to_string())
|
||||
}
|
||||
PasswordHashAlgorithm::Bcrypt => {
|
||||
return tx
|
||||
.send(bcrypt::hash(secret.as_bytes()).map_err(|err| {
|
||||
trc::AuthEvent::Error
|
||||
.reason(err)
|
||||
.details("Bcrypt hash failed")
|
||||
}))
|
||||
.ok()
|
||||
.unwrap_or(());
|
||||
}
|
||||
PasswordHashAlgorithm::Scrypt => Scrypt
|
||||
.hash_password(secret.as_bytes(), &salt)
|
||||
.map(|h| h.to_string()),
|
||||
PasswordHashAlgorithm::Pbkdf2 => Pbkdf2
|
||||
.hash_password(secret.as_bytes(), &salt)
|
||||
.map(|h| h.to_string()),
|
||||
};
|
||||
|
||||
tx.send(result.map_err(|err| {
|
||||
trc::AuthEvent::Error
|
||||
.reason(err)
|
||||
.details("Password hash failed")
|
||||
}))
|
||||
.ok();
|
||||
});
|
||||
|
||||
match rx.await {
|
||||
Ok(result) => result,
|
||||
Err(err) => Err(trc::EventType::Server(trc::ServerEvent::ThreadError)
|
||||
.caused_by(trc::location!())
|
||||
.reason(err)),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user