fix: Authentication

This commit is contained in:
Snowiiii 2024-08-04 17:10:25 +02:00
parent 41c4d23821
commit dbcb3c8052
9 changed files with 35 additions and 39 deletions

19
Cargo.lock generated
View File

@ -455,6 +455,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-sink",
] ]
[[package]] [[package]]
@ -463,6 +464,12 @@ version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
[[package]]
name = "futures-io"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
[[package]] [[package]]
name = "futures-sink" name = "futures-sink"
version = "0.3.30" version = "0.3.30"
@ -482,9 +489,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-io",
"futures-sink",
"futures-task", "futures-task",
"memchr",
"pin-project-lite", "pin-project-lite",
"pin-utils", "pin-utils",
"slab",
] ]
[[package]] [[package]]
@ -1094,12 +1105,6 @@ dependencies = [
"miniz_oxide", "miniz_oxide",
] ]
[[package]]
name = "pollster"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2"
[[package]] [[package]]
name = "powerfmt" name = "powerfmt"
version = "0.2.0" version = "0.2.0"
@ -1146,7 +1151,6 @@ dependencies = [
"log", "log",
"mio", "mio",
"num-bigint", "num-bigint",
"pollster",
"pumpkin-protocol", "pumpkin-protocol",
"pumpkin-registry", "pumpkin-registry",
"pumpkin-world", "pumpkin-world",
@ -1255,6 +1259,7 @@ dependencies = [
"base64", "base64",
"bytes", "bytes",
"encoding_rs", "encoding_rs",
"futures-channel",
"futures-core", "futures-core",
"futures-util", "futures-util",
"h2", "h2",

View File

@ -112,7 +112,9 @@ impl ByteBuffer {
} }
pub fn put_uuid(&mut self, v: uuid::Uuid) { pub fn put_uuid(&mut self, v: uuid::Uuid) {
self.buffer.put_slice(v.as_bytes()); let pair = v.as_u64_pair();
self.put_u64(pair.0);
self.put_u64(pair.1);
} }
pub fn put_string(&mut self, val: &str) { pub fn put_string(&mut self, val: &str) {

View File

@ -86,8 +86,10 @@ impl<'a> CLoginSuccess<'a> {
#[derive(Deserialize, Clone, Debug)] #[derive(Deserialize, Clone, Debug)]
pub struct Property { pub struct Property {
pub name: String, pub name: String,
// base 64
pub value: String, pub value: String,
pub signature: String, // base 64
pub signature: Option<String>,
} }
impl<'a> ClientPacket for CLoginSuccess<'a> { impl<'a> ClientPacket for CLoginSuccess<'a> {
@ -100,10 +102,8 @@ impl<'a> ClientPacket for CLoginSuccess<'a> {
p.put_string(&v.name); p.put_string(&v.name);
p.put_string(&v.value); p.put_string(&v.value);
// has signature ? // has signature ?
p.put_bool(true); p.put_bool(false);
// option // p.put_option(&v.signature, |p,v| p.put_string(v));
p.put_bool(true);
p.put_string(&v.signature);
}); });
bytebuf.put_bool(self.strict_error_handling); bytebuf.put_bool(self.strict_error_handling);
} }

View File

@ -13,8 +13,6 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"
toml = "0.8.19" toml = "0.8.19"
pollster = "0.3.0"
rand = "0.8.5" rand = "0.8.5"
num-bigint = "0.4.6" num-bigint = "0.4.6"
@ -26,7 +24,7 @@ rsa-der = "0.3.0"
flate2 = "1.0.30" flate2 = "1.0.30"
# authentication # authentication
reqwest = { version = "0.12.5", features = ["json"]} reqwest = { version = "0.12.5", features = ["json", "blocking"]}
sha1 = "0.10.6" sha1 = "0.10.6"
digest = "=0.11.0-pre.9" digest = "=0.11.0-pre.9"

View File

@ -1,4 +1,4 @@
use std::{error, net::IpAddr}; use std::{net::IpAddr};
use num_bigint::BigInt; use num_bigint::BigInt;
use pumpkin_protocol::client::login::Property; use pumpkin_protocol::client::login::Property;
@ -9,14 +9,14 @@ use uuid::Uuid;
use crate::server::Server; use crate::server::Server;
#[derive(Deserialize, Clone)] #[derive(Deserialize, Clone, Debug)]
pub struct GameProfile { pub struct GameProfile {
pub id: Uuid, pub id: Uuid,
pub name: String, pub name: String,
pub properties: Vec<Property>, pub properties: Vec<Property>,
} }
pub async fn authenticate( pub fn authenticate(
username: &str, username: &str,
server_hash: &str, server_hash: &str,
ip: &IpAddr, ip: &IpAddr,
@ -34,14 +34,13 @@ pub async fn authenticate(
.unwrap() .unwrap()
.get(address) .get(address)
.send() .send()
.await
.map_err(|_| AuthError::FailedResponse)?; .map_err(|_| AuthError::FailedResponse)?;
match response.status() { match response.status() {
StatusCode::OK => {} StatusCode::OK => {}
StatusCode::NO_CONTENT => Err(AuthError::UnverifiedUsername)?, StatusCode::NO_CONTENT => Err(AuthError::UnverifiedUsername)?,
other => Err(AuthError::UnknownStatusCode(other.as_str().to_string()))?, other => Err(AuthError::UnknownStatusCode(other.as_str().to_string()))?,
} }
let profile: GameProfile = response.json().await.map_err(|_| AuthError::FailedParse)?; let profile: GameProfile = response.json().map_err(|_| AuthError::FailedParse)?;
Ok(profile) Ok(profile)
} }

View File

@ -94,7 +94,7 @@ impl ClientPacketProcessor for Client {
properties: vec![], properties: vec![],
}); });
// we want encryption // todo: check config for encryption
let verify_token: [u8; 4] = rand::random(); let verify_token: [u8; 4] = rand::random();
let public_key_der = &server.public_key_der; let public_key_der = &server.public_key_der;
let packet = CEncryptionRequest::new( let packet = CEncryptionRequest::new(
@ -117,6 +117,8 @@ impl ClientPacketProcessor for Client {
.decrypt(Pkcs1v15Encrypt, &encryption_response.shared_secret) .decrypt(Pkcs1v15Encrypt, &encryption_response.shared_secret)
.map_err(|_| EncryptionError::FailedDecrypt) .map_err(|_| EncryptionError::FailedDecrypt)
.unwrap(); .unwrap();
self.enable_encryption(&shared_secret)
.unwrap_or_else(|e| self.kick(&e.to_string()));
if server.base_config.online_mode { if server.base_config.online_mode {
let hash = Sha1::new() let hash = Sha1::new()
@ -125,20 +127,17 @@ impl ClientPacketProcessor for Client {
.finalize(); .finalize();
let hash = auth_digest(&hash); let hash = auth_digest(&hash);
let ip = self.address.ip(); let ip = self.address.ip();
match pollster::block_on(authentication::authenticate( match authentication::authenticate(
&self.gameprofile.as_ref().unwrap().name, &self.gameprofile.as_ref().unwrap().name,
&hash, &hash,
&ip, &ip,
server, server,
)) { ) {
Ok(p) => self.gameprofile = Some(p), Ok(p) => self.gameprofile = Some(p),
Err(e) => self.kick(&e.to_string()), Err(e) => self.kick(&e.to_string()),
} }
} }
self.enable_encryption(server, shared_secret)
.unwrap_or_else(|e| self.kick(&e.to_string()));
if let Some(profile) = self.gameprofile.as_ref().cloned() { if let Some(profile) = self.gameprofile.as_ref().cloned() {
let packet = CLoginSuccess::new(profile.id, profile.name, &profile.properties, false); let packet = CLoginSuccess::new(profile.id, profile.name, &profile.properties, false);
self.send_packet(packet) self.send_packet(packet)

View File

@ -32,7 +32,6 @@ use pumpkin_protocol::{
ClientPacket, ConnectionState, PacketError, RawPacket, ServerPacket, ClientPacket, ConnectionState, PacketError, RawPacket, ServerPacket,
}; };
use rsa::Pkcs1v15Encrypt;
use std::io::Read; use std::io::Read;
use thiserror::Error; use thiserror::Error;
@ -99,16 +98,10 @@ impl Client {
/// enables encryption /// enables encryption
pub fn enable_encryption( pub fn enable_encryption(
&mut self, &mut self,
server: &mut Server, shared_secret: &[u8], // decrypted
shared_secret: Vec<u8>, // decrypted
) -> Result<(), EncryptionError> { ) -> Result<(), EncryptionError> {
self.encrytion = true; self.encrytion = true;
let shared_secret = server
.private_key
.decrypt(Pkcs1v15Encrypt, &shared_secret)
.map_err(|_| EncryptionError::FailedDecrypt)?;
let crypt_key: [u8; 16] = shared_secret let crypt_key: [u8; 16] = shared_secret
.as_slice()
.try_into() .try_into()
.map_err(|_| EncryptionError::SharedWrongLength)?; .map_err(|_| EncryptionError::SharedWrongLength)?;
self.dec.enable_encryption(&crypt_key); self.dec.enable_encryption(&crypt_key);

View File

@ -68,7 +68,7 @@ impl Default for BasicConfiguration {
server_address: "127.0.0.1".to_string(), server_address: "127.0.0.1".to_string(),
server_port: 25565, server_port: 25565,
seed: "".to_string(), seed: "".to_string(),
max_players: 0, max_players: 100000,
view_distances: 10, view_distances: 10,
simulation_distance: 10, simulation_distance: 10,
resource_pack: "".to_string(), resource_pack: "".to_string(),

View File

@ -47,7 +47,7 @@ pub struct Server {
pub advanced_config: AdvancedConfiguration, pub advanced_config: AdvancedConfiguration,
/// Used for Authentication, None is Online mode is disabled /// Used for Authentication, None is Online mode is disabled
pub auth_client: Option<reqwest::Client>, pub auth_client: Option<reqwest::blocking::Client>,
} }
impl Server { impl Server {
@ -67,7 +67,7 @@ impl Server {
) )
.into_boxed_slice(); .into_boxed_slice();
let auth_client = if config.0.online_mode { let auth_client = if config.0.online_mode {
Some(reqwest::Client::new()) Some(reqwest::blocking::Client::new())
} else { } else {
None None
}; };
@ -163,7 +163,7 @@ impl Server {
} }
pub fn build_brand() -> Vec<u8> { pub fn build_brand() -> Vec<u8> {
let brand = "pumpkin"; let brand = "Pumpkin";
let mut buf = vec![]; let mut buf = vec![];
let _ = VarInt32(brand.len() as i32).encode(&mut buf); let _ = VarInt32(brand.len() as i32).encode(&mut buf);
buf.extend_from_slice(brand.as_bytes()); buf.extend_from_slice(brand.as_bytes());