Merge pull request #78 from kralverde/network_error

Incoming Packet Validation
This commit is contained in:
Alexander Medvedev
2024-09-05 21:24:57 +01:00
committed by GitHub
10 changed files with 179 additions and 103 deletions

View File

@@ -45,77 +45,77 @@ impl<'a, 'de> de::Deserializer<'de> for Deserializer<'a> {
where
V: de::Visitor<'de>,
{
visitor.visit_bool(self.inner.get_bool())
visitor.visit_bool(self.inner.get_bool()?)
}
fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
visitor.visit_i8(self.inner.get_i8())
visitor.visit_i8(self.inner.get_i8()?)
}
fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
visitor.visit_i16(self.inner.get_i16())
visitor.visit_i16(self.inner.get_i16()?)
}
fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
visitor.visit_i32(self.inner.get_i32())
visitor.visit_i32(self.inner.get_i32()?)
}
fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
visitor.visit_i64(self.inner.get_i64())
visitor.visit_i64(self.inner.get_i64()?)
}
fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
visitor.visit_u8(self.inner.get_u8())
visitor.visit_u8(self.inner.get_u8()?)
}
fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
visitor.visit_u16(self.inner.get_u16())
visitor.visit_u16(self.inner.get_u16()?)
}
fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
visitor.visit_u32(self.inner.get_u32())
visitor.visit_u32(self.inner.get_u32()?)
}
fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
visitor.visit_u64(self.inner.get_u64())
visitor.visit_u64(self.inner.get_u64()?)
}
fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
visitor.visit_f32(self.inner.get_f32())
visitor.visit_f32(self.inner.get_f32()?)
}
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
visitor.visit_f64(self.inner.get_f64())
visitor.visit_f64(self.inner.get_f64()?)
}
fn deserialize_char<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
@@ -129,7 +129,7 @@ impl<'a, 'de> de::Deserializer<'de> for Deserializer<'a> {
where
V: de::Visitor<'de>,
{
let string = self.inner.get_string().map_err(DeserializerError::Stdio)?;
let string = self.inner.get_string()?;
visitor.visit_str(&string)
}
@@ -137,7 +137,7 @@ impl<'a, 'de> de::Deserializer<'de> for Deserializer<'a> {
where
V: de::Visitor<'de>,
{
let string = self.inner.get_string().map_err(DeserializerError::Stdio)?;
let string = self.inner.get_string()?;
visitor.visit_str(&string)
}

View File

@@ -1,7 +1,6 @@
use crate::{BitSet, FixedBitSet, VarInt, VarLongType};
use bytes::{Buf, BufMut, BytesMut};
use core::str;
use std::io::{self, Error, ErrorKind};
mod deserializer;
pub use deserializer::DeserializerError;
@@ -26,12 +25,12 @@ impl ByteBuffer {
Self { buffer }
}
pub fn get_var_int(&mut self) -> VarInt {
pub fn get_var_int(&mut self) -> Result<VarInt, DeserializerError> {
let mut value: i32 = 0;
let mut position: i32 = 0;
loop {
let read = self.buffer.get_u8();
let read = self.get_u8()?;
value |= ((read & SEGMENT_BITS) as i32) << position;
@@ -42,19 +41,19 @@ impl ByteBuffer {
position += 7;
if position >= 32 {
panic!("VarInt is too big");
return Err(DeserializerError::Message("VarInt is too big".to_string()));
}
}
VarInt(value)
Ok(VarInt(value))
}
pub fn get_var_long(&mut self) -> VarLongType {
pub fn get_var_long(&mut self) -> Result<VarLongType, DeserializerError> {
let mut value: i64 = 0;
let mut position: i64 = 0;
loop {
let read = self.buffer.get_u8();
let read = self.get_u8()?;
value |= ((read & SEGMENT_BITS) as i64) << position;
@@ -65,49 +64,48 @@ impl ByteBuffer {
position += 7;
if position >= 64 {
panic!("VarInt is too big");
return Err(DeserializerError::Message("VarLong is too big".to_string()));
}
}
value
Ok(value)
}
pub fn get_string(&mut self) -> Result<String, io::Error> {
pub fn get_string(&mut self) -> Result<String, DeserializerError> {
self.get_string_len(32767)
}
pub fn get_string_len(&mut self, max_size: usize) -> Result<String, io::Error> {
let size = self.get_var_int().0;
pub fn get_string_len(&mut self, max_size: usize) -> Result<String, DeserializerError> {
let size = self.get_var_int()?.0;
if size as usize > max_size {
return Err(Error::new(
ErrorKind::InvalidData,
"String length is bigger than max size",
return Err(DeserializerError::Message(
"String length is bigger than max size".to_string(),
));
}
let data = self.buffer.copy_to_bytes(size as usize);
let data = self.copy_to_bytes(size as usize)?;
if data.len() > max_size {
return Err(Error::new(
ErrorKind::InvalidData,
"String is bigger than max size",
return Err(DeserializerError::Message(
"String is bigger than max size".to_string(),
));
}
match str::from_utf8(&data) {
Ok(string_result) => Ok(string_result.to_string()),
Err(e) => Err(Error::new(ErrorKind::InvalidData, e)),
Err(e) => Err(DeserializerError::Message(e.to_string())),
}
}
pub fn get_bool(&mut self) -> bool {
self.buffer.get_u8() != 0
pub fn get_bool(&mut self) -> Result<bool, DeserializerError> {
Ok(self.get_u8()? != 0)
}
pub fn get_uuid(&mut self) -> uuid::Uuid {
pub fn get_uuid(&mut self) -> Result<uuid::Uuid, DeserializerError> {
let mut bytes = [0u8; 16];
self.buffer.copy_to_slice(&mut bytes);
uuid::Uuid::from_slice(&bytes).expect("Failed to parse UUID")
self.copy_to_slice(&mut bytes)?;
Ok(uuid::Uuid::from_slice(&bytes).expect("Failed to parse UUID"))
}
pub fn get_fixed_bitset(&mut self, bits: usize) -> FixedBitSet {
pub fn get_fixed_bitset(&mut self, bits: usize) -> Result<FixedBitSet, DeserializerError> {
self.copy_to_bytes(bits.div_ceil(8))
}
@@ -161,11 +159,14 @@ impl ByteBuffer {
/// Reads a boolean. If true, the closure is called, and the returned value is
/// wrapped in Some. Otherwise, this returns None.
pub fn get_option<T>(&mut self, val: impl FnOnce(&mut Self) -> T) -> Option<T> {
if self.get_bool() {
Some(val(self))
pub fn get_option<T>(
&mut self,
val: impl FnOnce(&mut Self) -> Result<T, DeserializerError>,
) -> Result<Option<T>, DeserializerError> {
if self.get_bool()? {
Ok(Some(val(self)?))
} else {
None
Ok(None)
}
}
/// Writes `true` if the option is Some, or `false` if None. If the option is
@@ -177,13 +178,16 @@ impl ByteBuffer {
}
}
pub fn get_list<T>(&mut self, val: impl Fn(&mut Self) -> T) -> Vec<T> {
let len = self.get_var_int().0 as usize;
pub fn get_list<T>(
&mut self,
val: impl Fn(&mut Self) -> Result<T, DeserializerError>,
) -> Result<Vec<T>, DeserializerError> {
let len = self.get_var_int()?.0 as usize;
let mut list = Vec::with_capacity(len);
for _ in 0..len {
list.push(val(self));
list.push(val(self)?);
}
list
Ok(list)
}
/// Writes a list to the buffer.
pub fn put_list<T>(&mut self, list: &[T], write: impl Fn(&mut Self, &T)) {
@@ -211,50 +215,109 @@ impl ByteBuffer {
pub fn buf(&mut self) -> &mut BytesMut {
&mut self.buffer
}
}
// trait
impl ByteBuffer {
pub fn get_u8(&mut self) -> u8 {
self.buffer.get_u8()
// Trait equivalents
pub fn get_u8(&mut self) -> Result<u8, DeserializerError> {
if self.buffer.has_remaining() {
Ok(self.buffer.get_u8())
} else {
Err(DeserializerError::Message(
"No bytes left to consume".to_string(),
))
}
}
pub fn get_i8(&mut self) -> i8 {
self.buffer.get_i8()
pub fn get_i8(&mut self) -> Result<i8, DeserializerError> {
if self.buffer.has_remaining() {
Ok(self.buffer.get_i8())
} else {
Err(DeserializerError::Message(
"No bytes left to consume".to_string(),
))
}
}
pub fn get_u16(&mut self) -> u16 {
self.buffer.get_u16()
pub fn get_u16(&mut self) -> Result<u16, DeserializerError> {
if self.buffer.remaining() >= 2 {
Ok(self.buffer.get_u16())
} else {
Err(DeserializerError::Message(
"Less than 2 bytes left to consume".to_string(),
))
}
}
pub fn get_i16(&mut self) -> i16 {
self.buffer.get_i16()
pub fn get_i16(&mut self) -> Result<i16, DeserializerError> {
if self.buffer.remaining() >= 2 {
Ok(self.buffer.get_i16())
} else {
Err(DeserializerError::Message(
"Less than 2 bytes left to consume".to_string(),
))
}
}
pub fn get_u32(&mut self) -> u32 {
self.buffer.get_u32()
pub fn get_u32(&mut self) -> Result<u32, DeserializerError> {
if self.buffer.remaining() >= 4 {
Ok(self.buffer.get_u32())
} else {
Err(DeserializerError::Message(
"Less than 4 bytes left to consume".to_string(),
))
}
}
pub fn get_i32(&mut self) -> i32 {
self.buffer.get_i32()
pub fn get_i32(&mut self) -> Result<i32, DeserializerError> {
if self.buffer.remaining() >= 4 {
Ok(self.buffer.get_i32())
} else {
Err(DeserializerError::Message(
"Less than 4 bytes left to consume".to_string(),
))
}
}
pub fn get_u64(&mut self) -> u64 {
self.buffer.get_u64()
pub fn get_u64(&mut self) -> Result<u64, DeserializerError> {
if self.buffer.remaining() >= 8 {
Ok(self.buffer.get_u64())
} else {
Err(DeserializerError::Message(
"Less than 8 bytes left to consume".to_string(),
))
}
}
pub fn get_i64(&mut self) -> i64 {
self.buffer.get_i64()
pub fn get_i64(&mut self) -> Result<i64, DeserializerError> {
if self.buffer.remaining() >= 8 {
Ok(self.buffer.get_i64())
} else {
Err(DeserializerError::Message(
"Less than 8 bytes left to consume".to_string(),
))
}
}
pub fn get_f32(&mut self) -> f32 {
self.buffer.get_f32()
pub fn get_f32(&mut self) -> Result<f32, DeserializerError> {
if self.buffer.remaining() >= 4 {
Ok(self.buffer.get_f32())
} else {
Err(DeserializerError::Message(
"Less than 4 bytes left to consume".to_string(),
))
}
}
pub fn get_f64(&mut self) -> f64 {
self.buffer.get_f64()
pub fn get_f64(&mut self) -> Result<f64, DeserializerError> {
if self.buffer.remaining() >= 8 {
Ok(self.buffer.get_f64())
} else {
Err(DeserializerError::Message(
"Less than 8 bytes left to consume".to_string(),
))
}
}
// TODO: SerializerError?
pub fn put_u8(&mut self, n: u8) {
self.buffer.put_u8(n)
}
@@ -295,12 +358,25 @@ impl ByteBuffer {
self.buffer.put_f64(n)
}
pub fn copy_to_bytes(&mut self, len: usize) -> bytes::Bytes {
self.buffer.copy_to_bytes(len)
pub fn copy_to_bytes(&mut self, len: usize) -> Result<bytes::Bytes, DeserializerError> {
if self.buffer.len() >= len {
Ok(self.buffer.copy_to_bytes(len))
} else {
Err(DeserializerError::Message(
"Unable to copy bytes".to_string(),
))
}
}
pub fn copy_to_slice(&mut self, dst: &mut [u8]) {
self.buffer.copy_to_slice(dst)
pub fn copy_to_slice(&mut self, dst: &mut [u8]) -> Result<(), DeserializerError> {
if self.buffer.remaining() >= dst.len() {
self.buffer.copy_to_slice(dst);
Ok(())
} else {
Err(DeserializerError::Message(
"Unable to copy slice".to_string(),
))
}
}
pub fn put_slice(&mut self, src: &[u8]) {

View File

@@ -16,10 +16,10 @@ pub struct SHandShake {
impl ServerPacket for SHandShake {
fn read(bytebuf: &mut ByteBuffer) -> Result<Self, DeserializerError> {
Ok(Self {
protocol_version: bytebuf.get_var_int(),
server_address: bytebuf.get_string_len(255).unwrap(),
server_port: bytebuf.get_u16(),
next_state: bytebuf.get_var_int().into(),
protocol_version: bytebuf.get_var_int()?,
server_address: bytebuf.get_string_len(255)?,
server_port: bytebuf.get_u16()?,
next_state: bytebuf.get_var_int()?.into(),
})
}
}

View File

@@ -15,10 +15,10 @@ pub struct SEncryptionResponse {
impl ServerPacket for SEncryptionResponse {
fn read(bytebuf: &mut ByteBuffer) -> Result<Self, DeserializerError> {
let shared_secret_length = bytebuf.get_var_int();
let shared_secret = bytebuf.copy_to_bytes(shared_secret_length.0 as usize);
let verify_token_length = bytebuf.get_var_int();
let verify_token = bytebuf.copy_to_bytes(shared_secret_length.0 as usize);
let shared_secret_length = bytebuf.get_var_int()?;
let shared_secret = bytebuf.copy_to_bytes(shared_secret_length.0 as usize)?;
let verify_token_length = bytebuf.get_var_int()?;
let verify_token = bytebuf.copy_to_bytes(shared_secret_length.0 as usize)?;
Ok(Self {
shared_secret_length,
shared_secret: shared_secret.to_vec(),

View File

@@ -14,8 +14,8 @@ pub struct SLoginStart {
impl ServerPacket for SLoginStart {
fn read(bytebuf: &mut ByteBuffer) -> Result<Self, DeserializerError> {
Ok(Self {
name: bytebuf.get_string_len(16).unwrap(),
uuid: bytebuf.get_uuid(),
name: bytebuf.get_string_len(16)?,
uuid: bytebuf.get_uuid()?,
})
}
}

View File

@@ -16,9 +16,9 @@ pub struct SLoginPluginResponse {
impl ServerPacket for SLoginPluginResponse {
fn read(bytebuf: &mut ByteBuffer) -> Result<Self, DeserializerError> {
Ok(Self {
message_id: bytebuf.get_var_int(),
successful: bytebuf.get_bool(),
data: bytebuf.get_option(|v| v.get_slice()),
message_id: bytebuf.get_var_int()?,
successful: bytebuf.get_bool()?,
data: bytebuf.get_option(|v| Ok(v.get_slice()))?,
})
}
}

View File

@@ -21,12 +21,12 @@ pub struct SChatMessage {
impl ServerPacket for SChatMessage {
fn read(bytebuf: &mut ByteBuffer) -> Result<Self, DeserializerError> {
Ok(Self {
message: bytebuf.get_string().unwrap(),
timestamp: bytebuf.get_i64(),
salt: bytebuf.get_i64(),
signature: bytebuf.get_option(|v| v.copy_to_bytes(256)),
message_count: bytebuf.get_var_int(),
acknowledged: bytebuf.get_fixed_bitset(20),
message: bytebuf.get_string()?,
timestamp: bytebuf.get_i64()?,
salt: bytebuf.get_i64()?,
signature: bytebuf.get_option(|v| v.copy_to_bytes(256))?,
message_count: bytebuf.get_var_int()?,
acknowledged: bytebuf.get_fixed_bitset(20)?,
})
}
}

View File

@@ -18,8 +18,8 @@ impl ServerPacket for SInteract {
fn read(
bytebuf: &mut crate::bytebuf::ByteBuffer,
) -> Result<Self, crate::bytebuf::DeserializerError> {
let entity_id = bytebuf.get_var_int();
let typ = bytebuf.get_var_int();
let entity_id = bytebuf.get_var_int()?;
let typ = bytebuf.get_var_int()?;
let action = ActionType::from_i32(typ.0).ok_or(DeserializerError::Message(
"invalid action type".to_string(),
))?;
@@ -27,13 +27,13 @@ impl ServerPacket for SInteract {
ActionType::Interact => None,
ActionType::Attack => None,
ActionType::InteractAt => {
Some((bytebuf.get_f32(), bytebuf.get_f32(), bytebuf.get_f32()))
Some((bytebuf.get_f32()?, bytebuf.get_f32()?, bytebuf.get_f32()?))
}
};
let hand = match action {
ActionType::Interact => Some(bytebuf.get_var_int()),
ActionType::Interact => Some(bytebuf.get_var_int()?),
ActionType::Attack => None,
ActionType::InteractAt => Some(bytebuf.get_var_int()),
ActionType::InteractAt => Some(bytebuf.get_var_int()?),
};
Ok(Self {
@@ -41,7 +41,7 @@ impl ServerPacket for SInteract {
typ,
target_position,
hand,
sneaking: bytebuf.get_bool(),
sneaking: bytebuf.get_bool()?,
})
}
}

View File

@@ -25,9 +25,9 @@ pub enum Action {
impl ServerPacket for SPlayerCommand {
fn read(bytebuf: &mut crate::bytebuf::ByteBuffer) -> Result<Self, DeserializerError> {
Ok(Self {
entity_id: bytebuf.get_var_int(),
action: bytebuf.get_var_int(),
jump_boost: bytebuf.get_var_int(),
entity_id: bytebuf.get_var_int()?,
action: bytebuf.get_var_int()?,
jump_boost: bytebuf.get_var_int()?,
})
}
}

View File

@@ -52,7 +52,7 @@ pub fn receive_plugin_response(
buf.put_slice(data_without_signature);
// check velocity version
let version = buf.get_var_int();
let version = buf.get_var_int().unwrap();
let version = version.0;
if version > MAX_SUPPORTED_FORWARDING_VERSION {
client.kick(&format!(