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