implement deprecated user field for login requests

Signed-off-by: strawberry <strawberry@puppygock.gay>
This commit is contained in:
strawberry 2024-02-15 20:47:12 -05:00 committed by June
parent 5f007d8117
commit a0205cd41d
6 changed files with 73 additions and 33 deletions

24
Cargo.lock generated
View file

@ -2121,7 +2121,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma" name = "ruma"
version = "0.9.4" version = "0.9.4"
source = "git+https://github.com/ruma/ruma?rev=68c9bb0930f2195fa8672fbef9633ef62737df5d#68c9bb0930f2195fa8672fbef9633ef62737df5d" source = "git+https://github.com/ruma/ruma?rev=4d9f754657a099df8e61533787b8eebd12946435#4d9f754657a099df8e61533787b8eebd12946435"
dependencies = [ dependencies = [
"assign", "assign",
"js_int", "js_int",
@ -2140,7 +2140,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-appservice-api" name = "ruma-appservice-api"
version = "0.9.0" version = "0.9.0"
source = "git+https://github.com/ruma/ruma?rev=68c9bb0930f2195fa8672fbef9633ef62737df5d#68c9bb0930f2195fa8672fbef9633ef62737df5d" source = "git+https://github.com/ruma/ruma?rev=4d9f754657a099df8e61533787b8eebd12946435#4d9f754657a099df8e61533787b8eebd12946435"
dependencies = [ dependencies = [
"js_int", "js_int",
"ruma-common", "ruma-common",
@ -2152,7 +2152,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-client-api" name = "ruma-client-api"
version = "0.17.4" version = "0.17.4"
source = "git+https://github.com/ruma/ruma?rev=68c9bb0930f2195fa8672fbef9633ef62737df5d#68c9bb0930f2195fa8672fbef9633ef62737df5d" source = "git+https://github.com/ruma/ruma?rev=4d9f754657a099df8e61533787b8eebd12946435#4d9f754657a099df8e61533787b8eebd12946435"
dependencies = [ dependencies = [
"as_variant", "as_variant",
"assign", "assign",
@ -2171,7 +2171,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-common" name = "ruma-common"
version = "0.12.1" version = "0.12.1"
source = "git+https://github.com/ruma/ruma?rev=68c9bb0930f2195fa8672fbef9633ef62737df5d#68c9bb0930f2195fa8672fbef9633ef62737df5d" source = "git+https://github.com/ruma/ruma?rev=4d9f754657a099df8e61533787b8eebd12946435#4d9f754657a099df8e61533787b8eebd12946435"
dependencies = [ dependencies = [
"as_variant", "as_variant",
"base64", "base64",
@ -2199,7 +2199,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-events" name = "ruma-events"
version = "0.27.11" version = "0.27.11"
source = "git+https://github.com/ruma/ruma?rev=68c9bb0930f2195fa8672fbef9633ef62737df5d#68c9bb0930f2195fa8672fbef9633ef62737df5d" source = "git+https://github.com/ruma/ruma?rev=4d9f754657a099df8e61533787b8eebd12946435#4d9f754657a099df8e61533787b8eebd12946435"
dependencies = [ dependencies = [
"as_variant", "as_variant",
"indexmap", "indexmap",
@ -2221,7 +2221,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-federation-api" name = "ruma-federation-api"
version = "0.8.0" version = "0.8.0"
source = "git+https://github.com/ruma/ruma?rev=68c9bb0930f2195fa8672fbef9633ef62737df5d#68c9bb0930f2195fa8672fbef9633ef62737df5d" source = "git+https://github.com/ruma/ruma?rev=4d9f754657a099df8e61533787b8eebd12946435#4d9f754657a099df8e61533787b8eebd12946435"
dependencies = [ dependencies = [
"js_int", "js_int",
"ruma-common", "ruma-common",
@ -2233,7 +2233,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-identifiers-validation" name = "ruma-identifiers-validation"
version = "0.9.3" version = "0.9.3"
source = "git+https://github.com/ruma/ruma?rev=68c9bb0930f2195fa8672fbef9633ef62737df5d#68c9bb0930f2195fa8672fbef9633ef62737df5d" source = "git+https://github.com/ruma/ruma?rev=4d9f754657a099df8e61533787b8eebd12946435#4d9f754657a099df8e61533787b8eebd12946435"
dependencies = [ dependencies = [
"js_int", "js_int",
"thiserror", "thiserror",
@ -2242,7 +2242,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-identity-service-api" name = "ruma-identity-service-api"
version = "0.8.0" version = "0.8.0"
source = "git+https://github.com/ruma/ruma?rev=68c9bb0930f2195fa8672fbef9633ef62737df5d#68c9bb0930f2195fa8672fbef9633ef62737df5d" source = "git+https://github.com/ruma/ruma?rev=4d9f754657a099df8e61533787b8eebd12946435#4d9f754657a099df8e61533787b8eebd12946435"
dependencies = [ dependencies = [
"js_int", "js_int",
"ruma-common", "ruma-common",
@ -2252,7 +2252,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-macros" name = "ruma-macros"
version = "0.12.0" version = "0.12.0"
source = "git+https://github.com/ruma/ruma?rev=68c9bb0930f2195fa8672fbef9633ef62737df5d#68c9bb0930f2195fa8672fbef9633ef62737df5d" source = "git+https://github.com/ruma/ruma?rev=4d9f754657a099df8e61533787b8eebd12946435#4d9f754657a099df8e61533787b8eebd12946435"
dependencies = [ dependencies = [
"once_cell", "once_cell",
"proc-macro-crate", "proc-macro-crate",
@ -2267,7 +2267,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-push-gateway-api" name = "ruma-push-gateway-api"
version = "0.8.0" version = "0.8.0"
source = "git+https://github.com/ruma/ruma?rev=68c9bb0930f2195fa8672fbef9633ef62737df5d#68c9bb0930f2195fa8672fbef9633ef62737df5d" source = "git+https://github.com/ruma/ruma?rev=4d9f754657a099df8e61533787b8eebd12946435#4d9f754657a099df8e61533787b8eebd12946435"
dependencies = [ dependencies = [
"js_int", "js_int",
"ruma-common", "ruma-common",
@ -2279,7 +2279,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-signatures" name = "ruma-signatures"
version = "0.14.0" version = "0.14.0"
source = "git+https://github.com/ruma/ruma?rev=68c9bb0930f2195fa8672fbef9633ef62737df5d#68c9bb0930f2195fa8672fbef9633ef62737df5d" source = "git+https://github.com/ruma/ruma?rev=4d9f754657a099df8e61533787b8eebd12946435#4d9f754657a099df8e61533787b8eebd12946435"
dependencies = [ dependencies = [
"base64", "base64",
"ed25519-dalek", "ed25519-dalek",
@ -2295,7 +2295,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-state-res" name = "ruma-state-res"
version = "0.10.0" version = "0.10.0"
source = "git+https://github.com/ruma/ruma?rev=68c9bb0930f2195fa8672fbef9633ef62737df5d#68c9bb0930f2195fa8672fbef9633ef62737df5d" source = "git+https://github.com/ruma/ruma?rev=4d9f754657a099df8e61533787b8eebd12946435#4d9f754657a099df8e61533787b8eebd12946435"
dependencies = [ dependencies = [
"itertools 0.11.0", "itertools 0.11.0",
"js_int", "js_int",

View file

@ -23,8 +23,8 @@ tower-http = { version = "0.4.4", features = ["add-extension", "cors", "sensitiv
# Used for matrix spec type definitions and helpers # Used for matrix spec type definitions and helpers
#ruma = { version = "0.4.0", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] } #ruma = { version = "0.4.0", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] }
ruma = { git = "https://github.com/ruma/ruma", rev = "68c9bb0930f2195fa8672fbef9633ef62737df5d", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified", "unstable-msc2870", "unstable-msc3061", "unstable-msc2867", "unstable-extensible-events"] } ruma = { git = "https://github.com/ruma/ruma", rev = "4d9f754657a099df8e61533787b8eebd12946435", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified", "unstable-msc2870", "unstable-msc3061", "unstable-msc2867", "unstable-extensible-events"] }
#ruma = { git = "https://github.com/timokoesters/ruma", rev = "4ec9c69bb7e09391add2382b3ebac97b6e8f4c64", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] } #ruma = { git = "https://github.com/girlbossceo/ruma", rev = "b111ec442df34c4d6518e0ba98c6d10a451fa8a1", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified", "unstable-msc2870", "unstable-msc3061", "unstable-msc2867", "unstable-extensible-events"] }
#ruma = { path = "../ruma/crates/ruma", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] } #ruma = { path = "../ruma/crates/ruma", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] }
# Async runtime and utilities # Async runtime and utilities

View file

@ -71,11 +71,11 @@ pub async fn get_register_available_route(
Ok(get_username_availability::v3::Response { available: true }) Ok(get_username_availability::v3::Response { available: true })
} }
/// # `POST /_matrix/client/r0/register` /// # `POST /_matrix/client/v3/register`
/// ///
/// Register an account on this homeserver. /// Register an account on this homeserver.
/// ///
/// You can use [`GET /_matrix/client/r0/register/available`](fn.get_register_available_route.html) /// You can use [`GET /_matrix/client/v3/register/available`](fn.get_register_available_route.html)
/// to check if the user id is valid and available. /// to check if the user id is valid and available.
/// ///
/// - Only works if registration is enabled /// - Only works if registration is enabled

View file

@ -17,7 +17,7 @@ use ruma::{
UserId, UserId,
}; };
use serde::Deserialize; use serde::Deserialize;
use tracing::{error, info, warn}; use tracing::{debug, error, info, warn};
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
struct Claims { struct Claims {
@ -53,21 +53,32 @@ pub async fn login_route(body: Ruma<login::v3::Request>) -> Result<login::v3::Re
// Validate login method // Validate login method
// TODO: Other login methods // TODO: Other login methods
let user_id = match &body.login_info { let user_id = match &body.login_info {
#[allow(deprecated)]
login::v3::LoginInfo::Password(login::v3::Password { login::v3::LoginInfo::Password(login::v3::Password {
identifier, identifier,
password, password,
user,
..
}) => { }) => {
let username = if let UserIdentifier::UserIdOrLocalpart(user_id) = identifier { debug!("Got password login type");
let username = if let Some(UserIdentifier::UserIdOrLocalpart(user_id)) = identifier {
debug!("Using username from identifier field");
user_id.to_lowercase()
} else if let Some(user_id) = user {
warn!("User \"{}\" is attempting to login with the deprecated \"user\" field at \"/_matrix/client/v3/login\". conduwuit implements this deprecated behaviour, but this is destined to be removed in a future Matrix release.", user_id);
user_id.to_lowercase() user_id.to_lowercase()
} else { } else {
warn!("Bad login type: {:?}", &body.login_info); warn!("Bad login type: {:?}", &body.login_info);
return Err(Error::BadRequest(ErrorKind::Forbidden, "Bad login type.")); return Err(Error::BadRequest(ErrorKind::Forbidden, "Bad login type."));
}; };
let user_id = let user_id =
UserId::parse_with_server_name(username, services().globals.server_name()) UserId::parse_with_server_name(username, services().globals.server_name())
.map_err(|_| { .map_err(|e| {
warn!("Failed to parse username from user logging in: {}", e);
Error::BadRequest(ErrorKind::InvalidUsername, "Username is invalid.") Error::BadRequest(ErrorKind::InvalidUsername, "Username is invalid.")
})?; })?;
let hash = services() let hash = services()
.users .users
.password_hash(&user_id)? .password_hash(&user_id)?
@ -82,15 +93,18 @@ pub async fn login_route(body: Ruma<login::v3::Request>) -> Result<login::v3::Re
"The user has been deactivated", "The user has been deactivated",
)); ));
} }
let Ok(parsed_hash) = PasswordHash::new(&hash) else { let Ok(parsed_hash) = PasswordHash::new(&hash) else {
error!("error while hashing user {}", user_id); error!("error while hashing user {}", user_id);
return Err(Error::BadServerResponse("could not hash")); return Err(Error::BadServerResponse("could not hash"));
}; };
let hash_matches = services() let hash_matches = services()
.globals .globals
.argon .argon
.verify_password(password.as_bytes(), &parsed_hash) .verify_password(password.as_bytes(), &parsed_hash)
.is_ok(); .is_ok();
if !hash_matches { if !hash_matches {
return Err(Error::BadRequest( return Err(Error::BadRequest(
ErrorKind::Forbidden, ErrorKind::Forbidden,
@ -101,16 +115,25 @@ pub async fn login_route(body: Ruma<login::v3::Request>) -> Result<login::v3::Re
user_id user_id
} }
login::v3::LoginInfo::Token(login::v3::Token { token }) => { login::v3::LoginInfo::Token(login::v3::Token { token }) => {
debug!("Got token login type");
if let Some(jwt_decoding_key) = services().globals.jwt_decoding_key() { if let Some(jwt_decoding_key) = services().globals.jwt_decoding_key() {
let token = jsonwebtoken::decode::<Claims>( let token = jsonwebtoken::decode::<Claims>(
token, token,
jwt_decoding_key, jwt_decoding_key,
&jsonwebtoken::Validation::default(), &jsonwebtoken::Validation::default(),
) )
.map_err(|_| Error::BadRequest(ErrorKind::InvalidUsername, "Token is invalid."))?; .map_err(|e| {
warn!("Failed to parse JWT token from user logging in: {}", e);
Error::BadRequest(ErrorKind::InvalidUsername, "Token is invalid.")
})?;
let username = token.claims.sub.to_lowercase(); let username = token.claims.sub.to_lowercase();
UserId::parse_with_server_name(username, services().globals.server_name()).map_err( UserId::parse_with_server_name(username, services().globals.server_name()).map_err(
|_| Error::BadRequest(ErrorKind::InvalidUsername, "Username is invalid."), |e| {
warn!("Failed to parse username from user logging in: {}", e);
Error::BadRequest(ErrorKind::InvalidUsername, "Username is invalid.")
},
)? )?
} else { } else {
return Err(Error::BadRequest( return Err(Error::BadRequest(
@ -119,28 +142,41 @@ pub async fn login_route(body: Ruma<login::v3::Request>) -> Result<login::v3::Re
)); ));
} }
} }
login::v3::LoginInfo::ApplicationService(login::v3::ApplicationService { identifier }) => { #[allow(deprecated)]
login::v3::LoginInfo::ApplicationService(login::v3::ApplicationService {
identifier,
user,
}) => {
debug!("Got appservice login type");
if !body.from_appservice { if !body.from_appservice {
info!("User tried logging in as an appservice, but request body is not from a known/registered appservice");
return Err(Error::BadRequest( return Err(Error::BadRequest(
ErrorKind::Forbidden, ErrorKind::Forbidden,
"Forbidden login type.", "Forbidden login type.",
)); ));
}; };
let username = if let UserIdentifier::UserIdOrLocalpart(user_id) = identifier { let username = if let Some(UserIdentifier::UserIdOrLocalpart(user_id)) = identifier {
user_id.to_lowercase()
} else if let Some(user_id) = user {
warn!("Appservice \"{}\" is attempting to login with the deprecated \"user\" field at \"/_matrix/client/v3/login\". conduwuit implements this deprecated behaviour, but this is destined to be removed in a future Matrix release.", user_id);
user_id.to_lowercase() user_id.to_lowercase()
} else { } else {
return Err(Error::BadRequest(ErrorKind::Forbidden, "Bad login type.")); return Err(Error::BadRequest(ErrorKind::Forbidden, "Bad login type."));
}; };
UserId::parse_with_server_name(username, services().globals.server_name()).map_err( UserId::parse_with_server_name(username, services().globals.server_name()).map_err(
|_| Error::BadRequest(ErrorKind::InvalidUsername, "Username is invalid."), |e| {
warn!("Failed to parse username from appservice logging in: {}", e);
Error::BadRequest(ErrorKind::InvalidUsername, "Username is invalid.")
},
)? )?
} }
_ => { _ => {
warn!("Unsupported or unknown login type: {:?}", &body.login_info); warn!("Unsupported or unknown login type: {:?}", &body.login_info);
debug!("JSON body: {:?}", &body.json_body);
return Err(Error::BadRequest( return Err(Error::BadRequest(
ErrorKind::Unknown, ErrorKind::Unknown,
"Unsupported login type.", "Unsupported or unknown login type.",
)); ));
} }
}; };

View file

@ -12,7 +12,7 @@ use ruma::{
serde::Raw, serde::Raw,
EventId, RoomId, UserId, EventId, RoomId, UserId,
}; };
use tracing::log::warn; use tracing::{error, log::warn};
/// # `PUT /_matrix/client/r0/rooms/{roomId}/state/{eventType}/{stateKey}` /// # `PUT /_matrix/client/r0/rooms/{roomId}/state/{eventType}/{stateKey}`
/// ///
@ -105,7 +105,7 @@ pub async fn get_state_events_route(
}) })
} }
/// # `GET /_matrix/client/r0/rooms/{roomid}/state/{eventType}/{stateKey}` /// # `GET /_matrix/client/v3/rooms/{roomid}/state/{eventType}/{stateKey}`
/// ///
/// Get single state event of a room. /// Get single state event of a room.
/// ///
@ -139,12 +139,14 @@ pub async fn get_state_events_for_key_route(
})?; })?;
Ok(get_state_events_for_key::v3::Response { Ok(get_state_events_for_key::v3::Response {
content: serde_json::from_str(event.content.get()) content: serde_json::from_str(event.content.get()).map_err(|e| {
.map_err(|_| Error::bad_database("Invalid event content in database"))?, error!("Invalid event content in database: {}", e);
Error::bad_database("Invalid event content in database")
})?,
}) })
} }
/// # `GET /_matrix/client/r0/rooms/{roomid}/state/{eventType}` /// # `GET /_matrix/client/v3/rooms/{roomid}/state/{eventType}`
/// ///
/// Get single state event of a room. /// Get single state event of a room.
/// ///
@ -178,8 +180,10 @@ pub async fn get_state_events_for_empty_key_route(
})?; })?;
Ok(get_state_events_for_key::v3::Response { Ok(get_state_events_for_key::v3::Response {
content: serde_json::from_str(event.content.get()) content: serde_json::from_str(event.content.get()).map_err(|e| {
.map_err(|_| Error::bad_database("Invalid event content in database"))?, error!("Invalid event content in database: {}", e);
Error::bad_database("Invalid event content in database")
})?,
} }
.into()) .into())
} }

View file

@ -318,7 +318,7 @@ async fn run_server() -> io::Result<()> {
let socket_perms = config.unix_socket_perms.to_string(); let socket_perms = config.unix_socket_perms.to_string();
let octal_perms = u32::from_str_radix(&socket_perms, 8).unwrap(); let octal_perms = u32::from_str_radix(&socket_perms, 8).unwrap();
let listener = UnixListener::bind(path.clone()).unwrap(); let listener = UnixListener::bind(path.clone())?;
tokio::fs::set_permissions(path, Permissions::from_mode(octal_perms)) tokio::fs::set_permissions(path, Permissions::from_mode(octal_perms))
.await .await
.unwrap(); .unwrap();