mirror of
https://github.com/lldap/lldap.git
synced 2024-11-25 09:06:03 +00:00
parent
d672f68049
commit
da364746c4
5 changed files with 75 additions and 9 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -2383,6 +2383,7 @@ dependencies = [
|
|||
"opaque-ke",
|
||||
"orion",
|
||||
"rand 0.8.5",
|
||||
"rand_chacha 0.3.1",
|
||||
"reqwest",
|
||||
"rustls",
|
||||
"rustls-pemfile",
|
||||
|
|
|
@ -93,8 +93,15 @@ database_url = "sqlite:///data/users.db?mode=rwc"
|
|||
## would still have to perform an (expensive) brute force attack to find
|
||||
## each password.
|
||||
## Randomly generated on first run if it doesn't exist.
|
||||
## Alternatively, you can use key_seed to override this instead of relying on
|
||||
## a file.
|
||||
key_file = "/data/private_key"
|
||||
|
||||
## Seed to generate the server private key, see key_file above.
|
||||
## This can be any random string, the recommendation is that it's at least 12
|
||||
## characters long.
|
||||
#key_seed = "RanD0m STR1ng"
|
||||
|
||||
## Ignored attributes.
|
||||
## Some services will request attributes that are not present in LLDAP. When it
|
||||
## is the case, LLDAP will warn about the attribute being unknown. If you want
|
||||
|
@ -106,7 +113,7 @@ key_file = "/data/private_key"
|
|||
## Options to configure SMTP parameters, to send password reset emails.
|
||||
## To set these options from environment variables, use the following format
|
||||
## (example with "password"): LLDAP_SMTP_OPTIONS__PASSWORD
|
||||
#[smtp_options]
|
||||
[smtp_options]
|
||||
## Whether to enabled password reset via email, from LLDAP.
|
||||
#enable_password_reset=true
|
||||
## The SMTP server.
|
||||
|
@ -128,7 +135,7 @@ key_file = "/data/private_key"
|
|||
## Options to configure LDAPS.
|
||||
## To set these options from environment variables, use the following format
|
||||
## (example with "port"): LLDAP_LDAPS_OPTIONS__PORT
|
||||
#[ldaps_options]
|
||||
[ldaps_options]
|
||||
## Whether to enable LDAPS.
|
||||
#enabled=true
|
||||
## Port on which to listen.
|
||||
|
|
|
@ -31,6 +31,7 @@ lber = "0.4.1"
|
|||
ldap3_proto = ">=0.3.1"
|
||||
log = "*"
|
||||
orion = "0.17"
|
||||
rand_chacha = "0.3"
|
||||
rustls-pemfile = "1"
|
||||
serde = "*"
|
||||
serde_bytes = "0.11"
|
||||
|
|
|
@ -54,9 +54,16 @@ pub struct RunOpts {
|
|||
|
||||
/// Path to the file that contains the private server key.
|
||||
/// It will be created if it doesn't exist.
|
||||
/// Alternatively, you can set `server_key_seed`. If `server_key_seed` is given,
|
||||
/// `server_key_file` will be ignored.
|
||||
#[clap(long, env = "LLDAP_SERVER_KEY_FILE")]
|
||||
pub server_key_file: Option<String>,
|
||||
|
||||
/// Seed used to generate the private server key.
|
||||
/// Takes precedence over `server_key_file`.
|
||||
#[clap(long, env = "LLDAP_SERVER_KEY_SEED")]
|
||||
pub server_key_seed: Option<String>,
|
||||
|
||||
/// Change ldap host. Default: "0.0.0.0"
|
||||
#[clap(long, env = "LLDAP_LDAP_HOST")]
|
||||
pub ldap_host: Option<String>,
|
||||
|
|
|
@ -17,7 +17,7 @@ use serde::{Deserialize, Serialize};
|
|||
pub struct MailOptions {
|
||||
#[builder(default = "false")]
|
||||
pub enable_password_reset: bool,
|
||||
#[builder(default = "None")]
|
||||
#[builder(default)]
|
||||
pub from: Option<Mailbox>,
|
||||
#[builder(default = "None")]
|
||||
pub reply_to: Option<Mailbox>,
|
||||
|
@ -25,7 +25,7 @@ pub struct MailOptions {
|
|||
pub server: String,
|
||||
#[builder(default = "587")]
|
||||
pub port: u16,
|
||||
#[builder(default = r#"String::default()"#)]
|
||||
#[builder(default)]
|
||||
pub user: String,
|
||||
#[builder(default = r#"SecUtf8::from("")"#)]
|
||||
pub password: SecUtf8,
|
||||
|
@ -78,7 +78,7 @@ pub struct Configuration {
|
|||
pub ldap_base_dn: String,
|
||||
#[builder(default = r#"UserId::new("admin")"#)]
|
||||
pub ldap_user_dn: UserId,
|
||||
#[builder(default = r#"String::default()"#)]
|
||||
#[builder(default)]
|
||||
pub ldap_user_email: String,
|
||||
#[builder(default = r#"SecUtf8::from("password")"#)]
|
||||
pub ldap_user_pass: SecUtf8,
|
||||
|
@ -93,6 +93,8 @@ pub struct Configuration {
|
|||
#[builder(default = r#"String::from("server_key")"#)]
|
||||
pub key_file: String,
|
||||
#[builder(default)]
|
||||
pub key_seed: String,
|
||||
#[builder(default)]
|
||||
pub smtp_options: MailOptions,
|
||||
#[builder(default)]
|
||||
pub ldaps_options: LdapsOptions,
|
||||
|
@ -111,7 +113,10 @@ impl std::default::Default for Configuration {
|
|||
|
||||
impl ConfigurationBuilder {
|
||||
pub fn build(self) -> Result<Configuration> {
|
||||
let server_setup = get_server_setup(self.key_file.as_deref().unwrap_or("server_key"))?;
|
||||
let server_setup = get_server_setup(
|
||||
self.key_file.as_deref().unwrap_or("server_key"),
|
||||
self.key_seed.as_deref().unwrap_or_default(),
|
||||
)?;
|
||||
Ok(self.server_setup(Some(server_setup)).private_build()?)
|
||||
}
|
||||
|
||||
|
@ -154,10 +159,25 @@ fn write_to_readonly_file(path: &std::path::Path, buffer: &[u8]) -> Result<()> {
|
|||
Ok(file.write_all(buffer)?)
|
||||
}
|
||||
|
||||
fn get_server_setup(file_path: &str) -> Result<ServerSetup> {
|
||||
fn get_server_setup(file_path: &str, key_seed: &str) -> Result<ServerSetup> {
|
||||
use std::fs::read;
|
||||
let path = std::path::Path::new(file_path);
|
||||
if path.exists() {
|
||||
if !key_seed.is_empty() {
|
||||
if file_path != "server_key" || path.exists() {
|
||||
eprintln!("WARNING: A key_seed was given, we will ignore the server_key and generate one from the seed!");
|
||||
} else {
|
||||
println!("Got a key_seed, ignoring key_file");
|
||||
}
|
||||
let hash = |val: &[u8]| -> [u8; 32] {
|
||||
use sha2::{Digest, Sha256};
|
||||
let mut seed_hasher = Sha256::new();
|
||||
seed_hasher.update(val);
|
||||
seed_hasher.finalize().into()
|
||||
};
|
||||
use rand::SeedableRng;
|
||||
let mut rng = rand_chacha::ChaCha20Rng::from_seed(hash(key_seed.as_bytes()));
|
||||
Ok(ServerSetup::new(&mut rng))
|
||||
} else if path.exists() {
|
||||
let bytes = read(file_path).context(format!("Could not read key file `{}`", file_path))?;
|
||||
Ok(ServerSetup::deserialize(&bytes)?)
|
||||
} else {
|
||||
|
@ -198,6 +218,10 @@ impl ConfigOverrider for RunOpts {
|
|||
config.key_file = path.to_string();
|
||||
}
|
||||
|
||||
if let Some(seed) = self.server_key_seed.as_ref() {
|
||||
config.key_seed = seed.to_string();
|
||||
}
|
||||
|
||||
if let Some(port) = self.ldap_port {
|
||||
config.ldap_port = port;
|
||||
}
|
||||
|
@ -306,7 +330,7 @@ where
|
|||
if config.verbose {
|
||||
println!("Configuration: {:#?}", &config);
|
||||
}
|
||||
config.server_setup = Some(get_server_setup(&config.key_file)?);
|
||||
config.server_setup = Some(get_server_setup(&config.key_file, &config.key_seed)?);
|
||||
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.");
|
||||
}
|
||||
|
@ -318,3 +342,29 @@ where
|
|||
}
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn check_generated_server_key() {
|
||||
assert_eq!(
|
||||
bincode::serialize(&get_server_setup("/doesnt/exist", "key seed").unwrap()).unwrap(),
|
||||
[
|
||||
255, 206, 202, 50, 247, 13, 59, 191, 69, 244, 148, 187, 150, 227, 12, 250, 20, 207,
|
||||
211, 151, 147, 33, 107, 132, 2, 252, 121, 94, 97, 6, 97, 232, 163, 168, 86, 246,
|
||||
249, 186, 31, 204, 59, 75, 65, 134, 108, 159, 15, 70, 246, 250, 150, 195, 54, 197,
|
||||
195, 176, 150, 200, 157, 119, 13, 173, 119, 8, 32, 0, 0, 0, 0, 0, 0, 0, 248, 123,
|
||||
35, 91, 194, 51, 52, 57, 191, 210, 68, 227, 107, 166, 232, 37, 195, 244, 100, 84,
|
||||
88, 212, 190, 12, 195, 57, 83, 72, 127, 189, 179, 16, 32, 0, 0, 0, 0, 0, 0, 0, 128,
|
||||
112, 60, 207, 205, 69, 67, 73, 24, 175, 187, 62, 16, 45, 59, 136, 78, 40, 187, 54,
|
||||
159, 94, 116, 33, 133, 119, 231, 43, 199, 164, 141, 7, 32, 0, 0, 0, 0, 0, 0, 0,
|
||||
212, 134, 53, 203, 131, 24, 138, 211, 162, 28, 23, 233, 251, 82, 34, 66, 98, 12,
|
||||
249, 205, 35, 208, 241, 50, 128, 131, 46, 189, 211, 51, 56, 109, 32, 0, 0, 0, 0, 0,
|
||||
0, 0, 84, 20, 147, 25, 50, 5, 243, 203, 216, 180, 175, 121, 159, 96, 123, 183, 146,
|
||||
251, 22, 44, 98, 168, 67, 224, 255, 139, 159, 25, 24, 254, 88, 3
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue