From 8ada363a9264f48ad8e6aabe941ea26cf1ce8dd3 Mon Sep 17 00:00:00 2001 From: Patrick Michl Date: Sun, 26 Jun 2022 22:45:05 +0200 Subject: [PATCH] fix registering when clients dont use UIAA --- Cargo.lock | 265 ++++++++++++++++++++++++++++-- Cargo.toml | 2 +- src/api/client_server/r0/auth.rs | 80 +++++++-- src/api/client_server/versions.rs | 7 +- src/responses/registration.rs | 2 +- src/types/server_name.rs | 20 +-- 6 files changed, 331 insertions(+), 45 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8a8a8fa..f7f0473 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,7 +8,7 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ - "getrandom", + "getrandom 0.2.6", "once_cell", "version_check", ] @@ -152,7 +152,16 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9cf849ee05b2ee5fba5e36f97ff8ec2533916700fc0758d40d92136a42f3388" dependencies = [ - "digest", + "digest 0.10.3", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", ] [[package]] @@ -194,6 +203,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "const-oid" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d6f2aa4d0537bcc1c74df8755072bd31c1ef1a3a1b85a68e8404a8c353b7b8b" + [[package]] name = "cpufeatures" version = "0.2.2" @@ -248,13 +263,44 @@ dependencies = [ "typenum", ] +[[package]] +name = "curve25519-dalek" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "der" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79b71cca7d95d7681a4b3b9cdf63c8dbc3730d0584c2c74e31416d64a90493f4" +dependencies = [ + "const-oid", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + [[package]] name = "digest" version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" dependencies = [ - "block-buffer", + "block-buffer 0.10.2", "crypto-common", "subtle", ] @@ -265,6 +311,29 @@ version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" +[[package]] +name = "ed25519" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9c280362032ea4203659fc489832d0204ef09f247a0506f170dafcac08c369" +dependencies = [ + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" +dependencies = [ + "curve25519-dalek", + "ed25519", + "rand 0.7.3", + "serde", + "sha2 0.9.9", + "zeroize", +] + [[package]] name = "either" version = "1.6.1" @@ -382,6 +451,17 @@ dependencies = [ "version_check", ] +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + [[package]] name = "getrandom" version = "0.2.6" @@ -649,7 +729,7 @@ dependencies = [ "axum", "axum-macros", "http", - "rand", + "rand 0.8.5", "ruma", "serde", "serde_json", @@ -747,6 +827,12 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + [[package]] name = "parking_lot" version = "0.11.2" @@ -802,7 +888,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e029e94abc8fb0065241c308f1ac6bc8d20f450e8f7c5f0b25cd9b8d526ba294" dependencies = [ "base64ct", - "rand_core", + "rand_core 0.6.3", "subtle", ] @@ -850,6 +936,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee3ef9b64d26bad0536099c816c6734379e45bbd5f14798def6809e5cc350447" +dependencies = [ + "der", + "spki", + "zeroize", +] + [[package]] name = "pkg-config" version = "0.3.25" @@ -890,6 +987,19 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", +] + [[package]] name = "rand" version = "0.8.5" @@ -897,8 +1007,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.3", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", ] [[package]] @@ -908,7 +1028,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.3", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", ] [[package]] @@ -917,7 +1046,16 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ - "getrandom", + "getrandom 0.2.6", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", ] [[package]] @@ -978,6 +1116,8 @@ dependencies = [ "js_int", "ruma-client-api", "ruma-common", + "ruma-signatures", + "ruma-state-res", ] [[package]] @@ -1044,6 +1184,38 @@ dependencies = [ "syn", ] +[[package]] +name = "ruma-signatures" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c747652a4f8c5fd83a703f183c73738b2ed8565a740636c045e064ae77f9b51" +dependencies = [ + "base64", + "ed25519-dalek", + "pkcs8", + "rand 0.7.3", + "ruma-common", + "serde_json", + "sha2 0.9.9", + "thiserror", + "tracing", +] + +[[package]] +name = "ruma-state-res" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9b742ca53b37ec3b3cfba1f27bf64be775550aeadf971deb05e4b93cdd27fbe" +dependencies = [ + "itertools", + "js_int", + "ruma-common", + "serde", + "serde_json", + "thiserror", + "tracing", +] + [[package]] name = "rustls" version = "0.19.1" @@ -1122,6 +1294,19 @@ dependencies = [ "serde", ] +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + [[package]] name = "sha2" version = "0.10.2" @@ -1130,7 +1315,7 @@ checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" dependencies = [ "cfg-if", "cpufeatures", - "digest", + "digest 0.10.3", ] [[package]] @@ -1151,6 +1336,12 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f054c6c1a6e95179d6f23ed974060dcefb2d9388bb7256900badad682c499de4" + [[package]] name = "slab" version = "0.4.6" @@ -1188,6 +1379,15 @@ dependencies = [ "lock_api", ] +[[package]] +name = "spki" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c01a0c15da1b0b0e1494112e7af814a678fec9bd157881b49beac661e9b6f32" +dependencies = [ + "der", +] + [[package]] name = "sqlformat" version = "0.1.8" @@ -1243,7 +1443,7 @@ dependencies = [ "percent-encoding", "rustls", "serde", - "sha2", + "sha2 0.10.2", "smallvec", "sqlformat", "sqlx-rt", @@ -1270,7 +1470,7 @@ dependencies = [ "quote", "serde", "serde_json", - "sha2", + "sha2 0.10.2", "sqlx-core", "sqlx-rt", "syn", @@ -1321,6 +1521,18 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8" +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + [[package]] name = "thiserror" version = "1.0.30" @@ -1621,7 +1833,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8cfcd319456c4d6ea10087ed423473267e1a071f3bc0aa89f80d60997843c6f0" dependencies = [ - "getrandom", + "getrandom 0.2.6", ] [[package]] @@ -1652,6 +1864,12 @@ dependencies = [ "try-lock", ] +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" @@ -1817,3 +2035,24 @@ name = "windows_x86_64_msvc" version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9" + +[[package]] +name = "zeroize" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] diff --git a/Cargo.toml b/Cargo.toml index afef320..0255177 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,6 @@ thiserror = "1.0" argon2 = { version = "0.4", features = ["std"] } rand = { version = "0.8.5", features = ["std"] } uuid = { version = "1.0", features = ["v4"] } -ruma = { version = "0.6.4", features = ["client-api"] } +ruma = { version = "0.6.4", features = ["client-api", "compat"] } axum-macros = "0.2.2" http = "0.2.8" diff --git a/src/api/client_server/r0/auth.rs b/src/api/client_server/r0/auth.rs index aa8ee35..b74bdc6 100644 --- a/src/api/client_server/r0/auth.rs +++ b/src/api/client_server/r0/auth.rs @@ -14,6 +14,7 @@ use crate::{ }, models::{devices::Device, sessions::Session, users::User}, ruma_wrapper::{RumaRequest, RumaResponse}, + types::user_id::UserId, Config, }; @@ -40,6 +41,7 @@ async fn get_login() -> Result>, Extension(db): Extension, RumaRequest(req): RumaRequest, ) -> Result, ApiError> { @@ -51,16 +53,18 @@ async fn post_login( let user_id = if let IncomingUserIdentifier::UserIdOrLocalpart(user_id) = incoming_password.identifier { - ruma::UserId::parse(user_id).map_err(|e| anyhow::anyhow!(e))? + let user_id = UserId::new(&user_id, config.server_name())?; + + ruma::UserId::parse(user_id.to_string()) + .map_err(|_| AuthenticationError::InvalidUserId)? } else { - return Err(AuthenticationError::InvalidUserId.into()) + return Err(AuthenticationError::InvalidUserId.into()); }; let db_user = User::find_by_user_id(&db, user_id.as_str()).await?; db_user .password_correct(&password) - .ok() - .ok_or(AuthenticationError::Forbidden)?; + .map_err(|_| AuthenticationError::Forbidden)?; let device = if let Some(device_id) = req.device_id { Device::find_for_user(&db, &db_user, device_id.as_str()).await? @@ -81,7 +85,7 @@ async fn post_login( ruma::OwnedDeviceId::from(device.device_id), ); - return Ok(RumaResponse(response)); + Ok(RumaResponse(response)) } _ => todo!(), } @@ -94,11 +98,14 @@ async fn get_username_available( Query(params): Query>, ) -> Result, ApiError> { use account::get_username_availability::v3::*; + tracing::debug!("username_available hit"); let username = params .get("username") .ok_or(RegistrationError::MissingUserId)?; - let user_id = ruma::UserId::parse(username).map_err(|_| RegistrationError::InvalidUserId)?; + let user_id = UserId::new(username, config.server_name())?; + let user_id = + ruma::UserId::parse(user_id.to_string()).map_err(|_| RegistrationError::InvalidUserId)?; let exists = User::exists(&db, &user_id).await?; Ok(RumaResponse(Response::new(!exists))) @@ -111,6 +118,7 @@ async fn post_register( RumaRequest(req): RumaRequest, ) -> Result, ApiError> { use account::register::v3::*; + tracing::debug!("Register hit"); config .enable_registration() @@ -124,9 +132,12 @@ async fn post_register( let user_id = if let IncomingUserIdentifier::UserIdOrLocalpart(user_id) = incoming_password.identifier { - ruma::UserId::parse(user_id).map_err(|e| anyhow::anyhow!(e))? + let user_id = UserId::new(&user_id, config.server_name())?; + + ruma::UserId::parse(user_id.to_string()) + .map_err(|_| AuthenticationError::InvalidUserId)? } else { - Err(AuthenticationError::InvalidUserId)? + return Err(AuthenticationError::InvalidUserId.into()); }; if User::exists(&db, &user_id).await? { @@ -156,14 +167,57 @@ async fn post_register( response.access_token = Some(session.key); } if !req.inhibit_login { - response.device_id = Some(ruma::OwnedDeviceId::from(device.device_id)); + response.device_id = Some(device.device_id.into()); } - return Ok(RumaResponse(response)); + Ok(RumaResponse(response)) } _ => todo!(), }, - None => Err(RegistrationError::AdditionalAuthenticationInformation)?, - }; - unreachable!() + // For clients not following using UIAA + None => { + let password = req + .password + .ok_or("password missing") + .map_err(|e| anyhow::anyhow!(e))?; + let user_id = if let Some(username) = req.username { + let user_id = UserId::new(&username, config.server_name())?; + + ruma::UserId::parse(user_id.to_string()).map_err(|e| anyhow::anyhow!(e))? + } else { + return Err(AuthenticationError::InvalidUserId.into()); + }; + + if User::exists(&db, &user_id).await? { + return Err(RegistrationError::UserIdTaken.into()); + } + + let display_name = req + .initial_device_display_name + .unwrap_or_else(|| "Random Display Name".into()); + + let user = User::new(&user_id, &user_id.to_string(), &password)? + .create(&db) + .await?; + + let device = Device::new( + &user, + uuid::Uuid::new_v4().to_string().as_ref(), + &display_name, + )? + .create(&db) + .await?; + let mut response = + Response::new(ruma::UserId::parse(&user.user_id).map_err(|e| anyhow::anyhow!(e))?); + if !req.inhibit_login { + let session = Session::new(&device)?.create(&db).await?; + response.access_token = Some(session.key); + } + if !req.inhibit_login { + response.device_id = Some(ruma::OwnedDeviceId::from(device.device_id)); + } + + Ok(RumaResponse(response)) + } + } } diff --git a/src/api/client_server/versions.rs b/src/api/client_server/versions.rs index 18967de..7cc6822 100644 --- a/src/api/client_server/versions.rs +++ b/src/api/client_server/versions.rs @@ -12,5 +12,10 @@ use ruma::api::client::discovery; async fn get_client_versions() -> RumaResponse { use discovery::get_supported_versions::*; - RumaResponse(Response::new(vec!["v1.2".into()])) + RumaResponse(Response::new(vec![ + "r0.5.0".to_owned(), + "r0.6.0".to_owned(), + "v1.1".to_owned(), + "v1.2".to_owned(), + ])) } diff --git a/src/responses/registration.rs b/src/responses/registration.rs index 2342889..525e70b 100644 --- a/src/responses/registration.rs +++ b/src/responses/registration.rs @@ -12,4 +12,4 @@ impl RegistrationResponse { UserInteractiveAuthorizationInfo::new(), ) } -} \ No newline at end of file +} diff --git a/src/types/server_name.rs b/src/types/server_name.rs index 8af6269..483e6a9 100644 --- a/src/types/server_name.rs +++ b/src/types/server_name.rs @@ -100,40 +100,28 @@ mod tests { #[test] fn parse_ipv6_without_port() { let server_name = ServerName::new("[::1]").unwrap(); - assert_eq!( - server_name.hostname, - Hostname::IPv6("::1".parse().unwrap()) - ); + assert_eq!(server_name.hostname, Hostname::IPv6("::1".parse().unwrap())); assert_eq!(server_name.port, None); } #[test] fn parse_ipv6_with_port() { let server_name = ServerName::new("[::1]:8080").unwrap(); - assert_eq!( - server_name.hostname, - Hostname::IPv6("::1".parse().unwrap()) - ); + assert_eq!(server_name.hostname, Hostname::IPv6("::1".parse().unwrap())); assert_eq!(server_name.port, Some(8080)); } #[test] fn parse_fqdn_without_port() { let server_name = ServerName::new("example.com").unwrap(); - assert_eq!( - server_name.hostname, - Hostname::Fqdn("example.com".into()) - ); + assert_eq!(server_name.hostname, Hostname::Fqdn("example.com".into())); assert_eq!(server_name.port, None); } #[test] fn parse_fqdn_with_port() { let server_name = ServerName::new("example.com:8080").unwrap(); - assert_eq!( - server_name.hostname, - Hostname::Fqdn("example.com".into()) - ); + assert_eq!(server_name.hostname, Hostname::Fqdn("example.com".into())); assert_eq!(server_name.port, Some(8080)); } }