1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-07-29 22:01:14 +03:00

Use the new password manager

This commit is contained in:
Quentin Gliech
2022-12-14 15:28:36 +01:00
parent ff2f009b0e
commit 533cabe005
19 changed files with 768 additions and 427 deletions

View File

@ -13,16 +13,14 @@
// limitations under the License.
use anyhow::Context;
use argon2::Argon2;
use clap::{Parser, ValueEnum};
use mas_config::{DatabaseConfig, RootConfig};
use mas_config::{DatabaseConfig, PasswordsConfig, RootConfig};
use mas_iana::{jose::JsonWebSignatureAlg, oauth::OAuthClientAuthenticationMethod};
use mas_router::UrlBuilder;
use mas_storage::{
oauth2::client::{insert_client_from_config, lookup_client, truncate_clients},
user::{
lookup_user_by_username, lookup_user_email, mark_user_email_as_verified, register_user,
set_password,
add_user_password, lookup_user_by_username, lookup_user_email, mark_user_email_as_verified,
},
Clock,
};
@ -30,6 +28,8 @@ use oauth2_types::scope::Scope;
use rand::SeedableRng;
use tracing::{info, warn};
use crate::util::password_manager_from_config;
#[derive(Parser, Debug)]
pub(super) struct Options {
#[command(subcommand)]
@ -142,9 +142,6 @@ impl From<&SigningAlgorithm> for JsonWebSignatureAlg {
#[derive(Parser, Debug)]
enum Subcommand {
/// Register a new user
Register { username: String, password: String },
/// Mark email address as verified
VerifyEmail { username: String, email: String },
@ -196,30 +193,33 @@ impl Options {
let mut rng = rand_chacha::ChaChaRng::from_entropy();
match &self.subcommand {
SC::Register { username, password } => {
let config: DatabaseConfig = root.load_config()?;
let pool = config.connect().await?;
let mut txn = pool.begin().await?;
let hasher = Argon2::default();
let user =
register_user(&mut txn, &mut rng, &clock, hasher, username, password).await?;
txn.commit().await?;
info!(%user.id, %user.username, "User registered");
Ok(())
}
SC::SetPassword { username, password } => {
let config: DatabaseConfig = root.load_config()?;
let pool = config.connect().await?;
let database_config: DatabaseConfig = root.load_config()?;
let passwords_config: PasswordsConfig = root.load_config()?;
let pool = database_config.connect().await?;
let password_manager = password_manager_from_config(&passwords_config).await?;
let mut txn = pool.begin().await?;
let hasher = Argon2::default();
let user = lookup_user_by_username(&mut txn, username)
.await?
.context("User not found")?;
set_password(&mut txn, &mut rng, &clock, hasher, &user, password).await?;
let password = password.as_bytes().to_vec().into();
let (version, hashed_password) = password_manager.hash(&mut rng, password).await?;
add_user_password(
&mut txn,
&mut rng,
&clock,
&user,
version,
hashed_password,
None,
)
.await?;
info!(%user.id, %user.username, "Password changed");
txn.commit().await?;

View File

@ -20,7 +20,7 @@ use futures_util::stream::{StreamExt, TryStreamExt};
use itertools::Itertools;
use mas_config::RootConfig;
use mas_email::Mailer;
use mas_handlers::{passwords::PasswordManager, AppState, HttpClientFactory, MatrixHomeserver};
use mas_handlers::{AppState, HttpClientFactory, MatrixHomeserver};
use mas_listener::{server::Server, shutdown::ShutdownStream};
use mas_policy::PolicyFactory;
use mas_router::UrlBuilder;
@ -30,6 +30,8 @@ use mas_templates::Templates;
use tokio::signal::unix::SignalKind;
use tracing::{error, info, log::warn};
use crate::util::password_manager_from_config;
#[derive(Parser, Debug, Default)]
pub(super) struct Options {
/// Automatically apply pending migrations
@ -168,23 +170,7 @@ impl Options {
let listeners_config = config.http.listeners.clone();
let password_manager = config
.passwords
.load()
.await
.context("failed to load the password schemes")?
.into_iter()
.map(|(version, algorithm, secret)| {
use mas_handlers::passwords::Hasher;
let hasher = match algorithm {
mas_config::PasswordAlgorithm::Pbkdf2 => Hasher::pbkdf2(secret),
mas_config::PasswordAlgorithm::Bcrypt { cost } => Hasher::bcrypt(cost, secret),
mas_config::PasswordAlgorithm::Argon2id => Hasher::argon2id(secret),
};
(version, hasher)
});
let password_manager = PasswordManager::new(password_manager)?;
let password_manager = password_manager_from_config(&config.passwords).await?;
// Explicitely the config to properly zeroize secret keys
drop(config);

View File

@ -28,6 +28,7 @@ use tracing_subscriber::{
mod commands;
mod server;
mod telemetry;
mod util;
#[tokio::main]
async fn main() -> anyhow::Result<()> {

37
crates/cli/src/util.rs Normal file
View File

@ -0,0 +1,37 @@
// Copyright 2022 The Matrix.org Foundation C.I.C.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use mas_config::PasswordsConfig;
use mas_handlers::passwords::PasswordManager;
pub async fn password_manager_from_config(
config: &PasswordsConfig,
) -> Result<PasswordManager, anyhow::Error> {
let schemes = config
.load()
.await?
.into_iter()
.map(|(version, algorithm, secret)| {
use mas_handlers::passwords::Hasher;
let hasher = match algorithm {
mas_config::PasswordAlgorithm::Pbkdf2 => Hasher::pbkdf2(secret),
mas_config::PasswordAlgorithm::Bcrypt { cost } => Hasher::bcrypt(cost, secret),
mas_config::PasswordAlgorithm::Argon2id => Hasher::argon2id(secret),
};
(version, hasher)
});
PasswordManager::new(schemes)
}