diff --git a/src/config.rs b/src/config.rs index 72a6e64..3be1ada 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,7 +1,7 @@ //! Configuration for the server. use std::borrow::Cow; -use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; +use std::net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4}; use std::panic::{RefUnwindSafe, UnwindSafe}; use async_trait::async_trait; @@ -208,6 +208,26 @@ pub trait Config: Sized + Send + Sync + UnwindSafe + RefUnwindSafe + 'static { Ok(()) } + /// Called upon (every) client connect (if online mode is enabled) to obtain + /// the full URL to use for session server requests. Defaults to + /// `https://sessionserver.mojang.com/session/minecraft/hasJoined?username=&serverId=&ip=`. + /// + /// It is assumed, that upon successful request, a structure matching the + /// description in the [wiki](https://wiki.vg/Protocol_Encryption#Server) was obtained. + /// Providing a URL that does not return such a structure will result in a + /// disconnect for every client that connects. + /// + /// The arguments are described in the linked wiki article. + fn format_session_server_url( + &self, + server: &SharedServer, + username: &str, + auth_digest: &str, + player_ip: &IpAddr, + ) -> String { + format!("https://sessionserver.mojang.com/session/minecraft/hasJoined?username={username}&serverId={auth_digest}&ip={player_ip}") + } + /// Called after the server is created, but prior to accepting connections /// and entering the update loop. /// diff --git a/src/server.rs b/src/server.rs index 3bd0ac0..cdf72ed 100644 --- a/src/server.rs +++ b/src/server.rs @@ -704,9 +704,15 @@ async fn handle_login( .chain(&server.0.public_key_der) .finalize(); - let hex_hash = weird_hex_encoding(&hash); + let hex_hash = auth_digest(&hash); - let url = format!("https://sessionserver.mojang.com/session/minecraft/hasJoined?username={username}&serverId={hex_hash}&ip={}", remote_addr.ip()); + let url = C::format_session_server_url( + server.config(), + server, + &username, + &hex_hash, + &remote_addr.ip(), + ); let resp = server.0.http_client.get(url).send().await?; let status = resp.status(); @@ -823,7 +829,7 @@ async fn handle_play( Ok(()) } -fn weird_hex_encoding(bytes: &[u8]) -> String { +fn auth_digest(bytes: &[u8]) -> String { BigInt::from_signed_bytes_be(bytes).to_str_radix(16) } @@ -832,17 +838,17 @@ mod tests { use super::*; #[test] - fn weird_hex_encoding_correct() { + fn auth_digest_correct() { assert_eq!( - weird_hex_encoding(&Sha1::digest("Notch")), + auth_digest(&Sha1::digest("Notch")), "4ed1f46bbe04bc756bcb17c0c7ce3e4632f06a48" ); assert_eq!( - weird_hex_encoding(&Sha1::digest("jeb_")), + auth_digest(&Sha1::digest("jeb_")), "-7c9d5b0044c130109a5d7b5fb5c317c02b4e28c1" ); assert_eq!( - weird_hex_encoding(&Sha1::digest("simon")), + auth_digest(&Sha1::digest("simon")), "88e16a1019277b15d58faf0541e11910eb756f6" ); }