mirror of
https://github.com/nitnelave/lldap.git
synced 2023-04-12 14:25:13 +00:00
server: Prevent passwords and secrets from being printed
This commit is contained in:
parent
617a0f53fa
commit
9124339b96
11
Cargo.lock
generated
11
Cargo.lock
generated
@ -1803,6 +1803,7 @@ dependencies = [
|
||||
"orion",
|
||||
"rand 0.8.4",
|
||||
"sea-query",
|
||||
"secstr",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
@ -2757,6 +2758,16 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "secstr"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cce2c726741c320e5b8f1edd9a21b3c2c292ae94514afd001d41d81ba143dafc"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "2.4.2"
|
||||
|
@ -83,5 +83,9 @@ features = ["with-chrono"]
|
||||
features = ["env", "toml"]
|
||||
version = "*"
|
||||
|
||||
[dependencies.secstr]
|
||||
features = ["serde"]
|
||||
version = "*"
|
||||
|
||||
[dev-dependencies]
|
||||
mockall = "0.9.1"
|
||||
|
@ -437,7 +437,7 @@ mod tests {
|
||||
let sql_pool = get_in_memory_db().await;
|
||||
let config = ConfigurationBuilder::default()
|
||||
.ldap_user_dn("admin".to_string())
|
||||
.ldap_user_pass("test".to_string())
|
||||
.ldap_user_pass(secstr::SecUtf8::from("test"))
|
||||
.build()
|
||||
.unwrap();
|
||||
let handler = SqlBackendHandler::new(config, sql_pool);
|
||||
|
@ -9,6 +9,7 @@ use async_trait::async_trait;
|
||||
use lldap_auth::opaque;
|
||||
use log::*;
|
||||
use sea_query::{Expr, Iden, Query};
|
||||
use secstr::SecUtf8;
|
||||
use sqlx::Row;
|
||||
|
||||
type SqlOpaqueHandler = SqlBackendHandler;
|
||||
@ -83,7 +84,7 @@ impl SqlBackendHandler {
|
||||
impl LoginHandler for SqlBackendHandler {
|
||||
async fn bind(&self, request: BindRequest) -> Result<()> {
|
||||
if request.name == self.config.ldap_user_dn {
|
||||
if request.password == self.config.ldap_user_pass {
|
||||
if SecUtf8::from(request.password) == self.config.ldap_user_pass {
|
||||
return Ok(());
|
||||
} else {
|
||||
debug!(r#"Invalid password for LDAP bind user"#);
|
||||
@ -220,11 +221,12 @@ impl OpaqueHandler for SqlOpaqueHandler {
|
||||
pub(crate) async fn register_password(
|
||||
opaque_handler: &SqlOpaqueHandler,
|
||||
username: &str,
|
||||
password: &str,
|
||||
password: &SecUtf8,
|
||||
) -> Result<()> {
|
||||
let mut rng = rand::rngs::OsRng;
|
||||
use registration::*;
|
||||
let registration_start = opaque::client::registration::start_registration(password, &mut rng)?;
|
||||
let registration_start =
|
||||
opaque::client::registration::start_registration(password.unsecure(), &mut rng)?;
|
||||
let start_response = opaque_handler
|
||||
.registration_start(ClientRegistrationStartRequest {
|
||||
username: username.to_string(),
|
||||
@ -321,7 +323,7 @@ mod tests {
|
||||
attempt_login(&opaque_handler, "bob", "bob00")
|
||||
.await
|
||||
.unwrap_err();
|
||||
register_password(&opaque_handler, "bob", "bob00").await?;
|
||||
register_password(&opaque_handler, "bob", &secstr::SecUtf8::from("bob00")).await?;
|
||||
attempt_login(&opaque_handler, "bob", "wrong_password")
|
||||
.await
|
||||
.unwrap_err();
|
||||
|
@ -6,6 +6,7 @@ use figment::{
|
||||
};
|
||||
use lettre::message::Mailbox;
|
||||
use lldap_auth::opaque::{server::ServerSetup, KeyPair};
|
||||
use secstr::SecUtf8;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, derive_builder::Builder)]
|
||||
@ -23,8 +24,8 @@ pub struct MailOptions {
|
||||
pub port: u16,
|
||||
#[builder(default = r#""admin".to_string()"#)]
|
||||
pub user: String,
|
||||
#[builder(default = r#""".to_string()"#)]
|
||||
pub password: String,
|
||||
#[builder(default = r#"SecUtf8::from("")"#)]
|
||||
pub password: SecUtf8,
|
||||
#[builder(default = "true")]
|
||||
pub tls_required: bool,
|
||||
}
|
||||
@ -47,14 +48,14 @@ pub struct Configuration {
|
||||
pub ldaps_port: u16,
|
||||
#[builder(default = "17170")]
|
||||
pub http_port: u16,
|
||||
#[builder(default = r#"String::from("secretjwtsecret")"#)]
|
||||
pub jwt_secret: String,
|
||||
#[builder(default = r#"SecUtf8::from("secretjwtsecret")"#)]
|
||||
pub jwt_secret: SecUtf8,
|
||||
#[builder(default = r#"String::from("dc=example,dc=com")"#)]
|
||||
pub ldap_base_dn: String,
|
||||
#[builder(default = r#"String::from("admin")"#)]
|
||||
pub ldap_user_dn: String,
|
||||
#[builder(default = r#"String::from("password")"#)]
|
||||
pub ldap_user_pass: String,
|
||||
#[builder(default = r#"SecUtf8::from("password")"#)]
|
||||
pub ldap_user_pass: SecUtf8,
|
||||
#[builder(default = r#"String::from("sqlite://users.db?mode=rwc")"#)]
|
||||
pub database_url: String,
|
||||
#[builder(default = "false")]
|
||||
@ -188,7 +189,7 @@ impl ConfigOverrider for SmtpOpts {
|
||||
config.smtp_options.user = user.clone();
|
||||
}
|
||||
if let Some(password) = &self.smtp_password {
|
||||
config.smtp_options.password = password.clone();
|
||||
config.smtp_options.password = SecUtf8::from(password.clone());
|
||||
}
|
||||
if let Some(tls_required) = self.smtp_tls_required {
|
||||
config.smtp_options.tls_required = tls_required;
|
||||
@ -219,10 +220,10 @@ where
|
||||
println!("Configuration: {:#?}", &config);
|
||||
}
|
||||
config.server_setup = Some(get_server_setup(&config.key_file)?);
|
||||
if config.jwt_secret == "secretjwtsecret" {
|
||||
if config.jwt_secret == SecUtf8::from("secretjwtsecret") {
|
||||
println!("WARNING: Default JWT secret used! This is highly unsafe and can allow attackers to log in as admin.");
|
||||
}
|
||||
if config.ldap_user_pass == "password" {
|
||||
if config.ldap_user_pass == SecUtf8::from("password") {
|
||||
println!("WARNING: Unsecure default admin password is used.");
|
||||
}
|
||||
Ok(config)
|
||||
|
@ -22,7 +22,10 @@ pub fn send_test_email(to: Mailbox, options: &MailOptions) -> Result<()> {
|
||||
.to(to)
|
||||
.subject("LLDAP test email")
|
||||
.body("The test is successful! You can send emails from LLDAP".to_string())?;
|
||||
let creds = Credentials::new(options.user.clone(), options.password.clone());
|
||||
let creds = Credentials::new(
|
||||
options.user.clone(),
|
||||
options.password.unsecure().to_string(),
|
||||
);
|
||||
let mailer = SmtpTransport::relay(&options.server)?
|
||||
.credentials(creds)
|
||||
.build();
|
||||
|
@ -44,14 +44,14 @@ pub(crate) fn error_to_http_response(error: DomainError) -> HttpResponse {
|
||||
fn http_config<Backend>(
|
||||
cfg: &mut web::ServiceConfig,
|
||||
backend_handler: Backend,
|
||||
jwt_secret: String,
|
||||
jwt_secret: secstr::SecUtf8,
|
||||
jwt_blacklist: HashSet<u64>,
|
||||
) where
|
||||
Backend: TcpBackendHandler + BackendHandler + LoginHandler + OpaqueHandler + Sync + 'static,
|
||||
{
|
||||
cfg.app_data(web::Data::new(AppState::<Backend> {
|
||||
backend_handler,
|
||||
jwt_key: Hmac::new_varkey(jwt_secret.as_bytes()).unwrap(),
|
||||
jwt_key: Hmac::new_varkey(jwt_secret.unsecure().as_bytes()).unwrap(),
|
||||
jwt_blacklist: RwLock::new(jwt_blacklist),
|
||||
}))
|
||||
// Serve index.html and main.js, and default to index.html.
|
||||
|
@ -20,10 +20,11 @@ mod domain;
|
||||
mod infra;
|
||||
|
||||
async fn create_admin_user(handler: &SqlBackendHandler, config: &Configuration) -> Result<()> {
|
||||
let pass_length = config.ldap_user_pass.unsecure().len();
|
||||
assert!(
|
||||
config.ldap_user_pass.len() >= 8,
|
||||
pass_length >= 8,
|
||||
"Minimum password length is 8 characters, got {} characters",
|
||||
config.ldap_user_pass.len()
|
||||
pass_length
|
||||
);
|
||||
handler
|
||||
.create_user(CreateUserRequest {
|
||||
|
Loading…
Reference in New Issue
Block a user