Browse Source

Allow to lower KDF iterations for tests

pull/7752/head
Timshel 2 months ago
parent
commit
cd45c52d0c
  1. 2
      Cargo.toml
  2. 2
      playwright/compose/warden/build.sh
  3. 4
      playwright/docker-compose.yml
  4. 2
      playwright/test.env
  5. 12
      src/api/core/accounts.rs
  6. 20
      src/config.rs
  7. 3
      src/db/models/user.rs

2
Cargo.toml

@ -48,6 +48,8 @@ s3 = [
"dep:reqsign-aws-v4", "dep:reqsign-aws-v4",
"dep:reqsign-core", "dep:reqsign-core",
] ]
# Enable to allow to set lower KDF iterations settings
unsafe_test_mode = []
# OIDC specific features # OIDC specific features
oidc-accept-rfc3339-timestamps = ["openidconnect/accept-rfc3339-timestamps"] oidc-accept-rfc3339-timestamps = ["openidconnect/accept-rfc3339-timestamps"]

2
playwright/compose/warden/build.sh

@ -24,7 +24,7 @@ if [[ ! -z "$REPO_URL" ]] && [[ ! -z "$COMMIT_HASH" ]] ; then
fi fi
# Lower the KDF iterations default for faster tests. # Lower the KDF iterations default for faster tests.
sed -i 's/(6e5,2e6,6e5)/(1e5,2e6,1e5)/' /web-vault/app/main.*.js sed -i 's/(6e5,2e6,6e5)/(6e3,2e6,6e3)/' /web-vault/app/main.*.js
# Generate a self signed cert # Generate a self signed cert
mkdir -p /data/ssl; cd /data/ssl mkdir -p /data/ssl; cd /data/ssl

4
playwright/docker-compose.yml

@ -6,6 +6,8 @@ services:
build: build:
context: .. context: ..
dockerfile: Dockerfile dockerfile: Dockerfile
args:
DB: sqlite,mysql,postgresql,unsafe_test_mode
entrypoint: /bin/bash entrypoint: /bin/bash
restart: "no" restart: "no"
@ -23,12 +25,14 @@ services:
env_file: ${DC_ENV_FILE:-.env} env_file: ${DC_ENV_FILE:-.env}
environment: environment:
- ADMIN_TOKEN - ADMIN_TOKEN
- CLIENT_KDF_ITER
- DATABASE_URL - DATABASE_URL
- CLIENT_SUPPRESS_ONBOARDING - CLIENT_SUPPRESS_ONBOARDING
- EMAIL_2FA_AUTO_FALLBACK - EMAIL_2FA_AUTO_FALLBACK
- I_REALLY_WANT_VOLATILE_STORAGE - I_REALLY_WANT_VOLATILE_STORAGE
- LOG_LEVEL - LOG_LEVEL
- LOGIN_RATELIMIT_MAX_BURST - LOGIN_RATELIMIT_MAX_BURST
- PASSWORD_ITERATIONS
- SMTP_HOST - SMTP_HOST
- SMTP_FROM - SMTP_FROM
- SMTP_DEBUG - SMTP_DEBUG

2
playwright/test.env

@ -58,6 +58,8 @@ LOG_LEVEL=info,oidcwarden::sso=debug
LOGIN_RATELIMIT_MAX_BURST=100 LOGIN_RATELIMIT_MAX_BURST=100
ADMIN_TOKEN=admin ADMIN_TOKEN=admin
CLIENT_SUPPRESS_ONBOARDING=true CLIENT_SUPPRESS_ONBOARDING=true
PASSWORD_ITERATIONS=6000
CLIENT_KDF_ITER=6000
SMTP_SECURITY=off SMTP_SECURITY=off
SMTP_PORT=${MAILDEV_SMTP_PORT} SMTP_PORT=${MAILDEV_SMTP_PORT}

12
src/api/core/accounts.rs

@ -688,8 +688,8 @@ async fn post_password(data: Json<ChangePassData>, headers: Headers, conn: DbCon
} }
fn set_kdf_data(user: &mut User, data: &KDFData) -> EmptyResult { fn set_kdf_data(user: &mut User, data: &KDFData) -> EmptyResult {
if data.kdf == UserKdfType::Pbkdf2 as i32 && data.kdf_iterations < 100_000 { if data.kdf == UserKdfType::Pbkdf2 as i32 && data.kdf_iterations < CONFIG.client_kdf_iter() {
err!("PBKDF2 KDF iterations must be at least 100000.") err!(format!("PBKDF2 KDF iterations must be at least {}.", CONFIG.client_kdf_iter()))
} }
if data.kdf == UserKdfType::Argon2id as i32 { if data.kdf == UserKdfType::Argon2id as i32 {
@ -1401,15 +1401,15 @@ fn unknown_email_kdf(email: &str) -> (i32, i32, Option<i32>, Option<i32>) {
const PBKDF2: i32 = UserKdfType::Pbkdf2 as i32; const PBKDF2: i32 = UserKdfType::Pbkdf2 as i32;
const ARGON2ID: i32 = UserKdfType::Argon2id as i32; const ARGON2ID: i32 = UserKdfType::Argon2id as i32;
// Same list as upstream, the default is in it twice to give it more weight // Same list as upstream, the default is in it twice to give it more weight
const KDF_SETTINGS: [(i32, i32, Option<i32>, Option<i32>); 6] = [ let kdf_settings: [(i32, i32, Option<i32>, Option<i32>); 6] = [
(User::CLIENT_KDF_TYPE_DEFAULT, User::CLIENT_KDF_ITER_DEFAULT, None, None), (User::CLIENT_KDF_TYPE_DEFAULT, CONFIG.client_kdf_iter(), None, None),
(User::CLIENT_KDF_TYPE_DEFAULT, User::CLIENT_KDF_ITER_DEFAULT, None, None), (User::CLIENT_KDF_TYPE_DEFAULT, CONFIG.client_kdf_iter(), None, None),
(PBKDF2, 100_000, None, None), (PBKDF2, 100_000, None, None),
(PBKDF2, 5_000, None, None), (PBKDF2, 5_000, None, None),
(ARGON2ID, 3, Some(64), Some(4)), (ARGON2ID, 3, Some(64), Some(4)),
(ARGON2ID, 6, Some(32), Some(4)), (ARGON2ID, 6, Some(32), Some(4)),
]; ];
KDF_SETTINGS[crate::auth::prelogin_kdf_index(email, KDF_SETTINGS.len())] kdf_settings[crate::auth::prelogin_kdf_index(email, kdf_settings.len())]
} }
pub async fn prelogin(data: Json<PreloginData>, ip: ClientIp, conn: DbConn) -> JsonResult { pub async fn prelogin(data: Json<PreloginData>, ip: ClientIp, conn: DbConn) -> JsonResult {

20
src/config.rs

@ -661,7 +661,9 @@ make_config! {
client { client {
/// Control whether clients onboarding interstitials are suppressed |> post-login welcome dialogs, extension install prompts, setup extension redirects, and premium upsell modals /// Control whether clients onboarding interstitials are suppressed |> post-login welcome dialogs, extension install prompts, setup extension redirects, and premium upsell modals
client_suppress_onboarding: bool, true, def, false; client_suppress_onboarding: bool, true, def, false;
/// In most cases this value is set by the client |> Will block clients from setting too low of a value in `accounts::post_kdf`
client_kdf_iter: i32, false, def, 600_000;
}, },
/// Advanced settings /// Advanced settings
@ -935,6 +937,17 @@ make_config! {
}, },
} }
fn check_iterations(iterations: i32, key: &str) -> Result<(), Error> {
if iterations < 100_000 {
#[cfg(feature = "unsafe_test_mode")]
println!("[WARNING] {key} should be at least 100000 or higher. The default is 600000!");
#[cfg(not(feature = "unsafe_test_mode"))]
err!(format!("{key} should be at least 100000 or higher. The default is 600000!"));
}
Ok(())
}
fn validate_config(cfg: &ConfigItems, on_update: bool) -> Result<(), Error> { fn validate_config(cfg: &ConfigItems, on_update: bool) -> Result<(), Error> {
// Validate connection URL is valid and DB feature is enabled // Validate connection URL is valid and DB feature is enabled
#[cfg(sqlite)] #[cfg(sqlite)]
@ -969,9 +982,8 @@ fn validate_config(cfg: &ConfigItems, on_update: bool) -> Result<(), Error> {
} }
} }
if cfg.password_iterations < 100_000 { check_iterations(cfg.password_iterations, "PASSWORD_ITERATIONS")?;
err!("PASSWORD_ITERATIONS should be at least 100000 or higher. The default is 600000!"); check_iterations(cfg.client_kdf_iter, "CLIENT_KDF_ITER")?;
}
let limit = 256; let limit = 256;
if cfg.database_max_conns < 1 || cfg.database_max_conns > limit { if cfg.database_max_conns < 1 || cfg.database_max_conns > limit {

3
src/db/models/user.rs

@ -110,7 +110,6 @@ pub struct UserStampException {
/// Local methods /// Local methods
impl User { impl User {
pub const CLIENT_KDF_TYPE_DEFAULT: i32 = UserKdfType::Pbkdf2 as i32; pub const CLIENT_KDF_TYPE_DEFAULT: i32 = UserKdfType::Pbkdf2 as i32;
pub const CLIENT_KDF_ITER_DEFAULT: i32 = 600_000;
pub fn new(email: &str, name: Option<String>) -> Self { pub fn new(email: &str, name: Option<String>) -> Self {
let now = Utc::now().naive_utc(); let now = Utc::now().naive_utc();
@ -148,7 +147,7 @@ impl User {
excluded_globals: "[]".to_owned(), excluded_globals: "[]".to_owned(),
client_kdf_type: Self::CLIENT_KDF_TYPE_DEFAULT, client_kdf_type: Self::CLIENT_KDF_TYPE_DEFAULT,
client_kdf_iter: Self::CLIENT_KDF_ITER_DEFAULT, client_kdf_iter: CONFIG.client_kdf_iter(),
client_kdf_memory: None, client_kdf_memory: None,
client_kdf_parallelism: None, client_kdf_parallelism: None,

Loading…
Cancel
Save