fix: Authentication
This commit is contained in:
parent
41c4d23821
commit
dbcb3c8052
19
Cargo.lock
generated
19
Cargo.lock
generated
@ -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",
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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"
|
||||||
|
|||||||
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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(),
|
||||||
|
|||||||
@ -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());
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user