things
This commit is contained in:
parent
4d4fc6c7bf
commit
fc94f655b2
43 changed files with 1957 additions and 694 deletions
|
|
@ -3,21 +3,24 @@
|
|||
// force the compiler to shut up here
|
||||
#![allow(unused_parens)]
|
||||
|
||||
use crate::prudp::packet::PacketOption::{
|
||||
ConnectionSignature, FragmentId, InitialSequenceId, MaximumSubstreamId, SupportedFunctions,
|
||||
};
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
use hmac::{Hmac, Mac};
|
||||
use log::{error, warn};
|
||||
use md5::{Digest, Md5};
|
||||
use rnex_core::prudp::socket_addr::PRUDPSockAddr;
|
||||
use rnex_core::prudp::types_flags::TypesFlags;
|
||||
use rnex_core::prudp::types_flags::flags::ACK;
|
||||
use rnex_core::prudp::virtual_port::VirtualPort;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::io;
|
||||
use std::io::{Cursor, Read, Seek, Write};
|
||||
use std::net::SocketAddrV4;
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
use hmac::{Hmac, Mac};
|
||||
use log::{error, warn};
|
||||
use md5::{Md5, Digest};
|
||||
use thiserror::Error;
|
||||
use v_byte_helpers::{SwapEndian};
|
||||
use v_byte_helpers::SwapEndian;
|
||||
use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions};
|
||||
use crate::prudp::packet::flags::ACK;
|
||||
use crate::prudp::packet::PacketOption::{ConnectionSignature, FragmentId, InitialSequenceId, MaximumSubstreamId, SupportedFunctions};
|
||||
use rnex_core::prudp::socket_addr::PRUDPSockAddr;
|
||||
use rnex_core::prudp::virtual_port::VirtualPort;
|
||||
|
||||
type Md5Hmac = Hmac<Md5>;
|
||||
|
||||
|
|
@ -32,73 +35,11 @@ pub enum Error {
|
|||
#[error("invalid option id {0}")]
|
||||
InvalidOptionId(u8),
|
||||
#[error("option size {size} doesnt match expected option for given option id {id}")]
|
||||
InvalidOptionSize {
|
||||
id: u8,
|
||||
size: u8,
|
||||
},
|
||||
InvalidOptionSize { id: u8, size: u8 },
|
||||
}
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Pod, Zeroable, SwapEndian, Default, Eq, PartialEq)]
|
||||
pub struct TypesFlags(u16);
|
||||
|
||||
impl TypesFlags {
|
||||
#[inline]
|
||||
pub const fn get_types(self) -> u8 {
|
||||
(self.0 & 0x000F) as u8
|
||||
}
|
||||
#[inline]
|
||||
pub const fn get_flags(self) -> u16 {
|
||||
(self.0 & 0xFFF0) >> 4
|
||||
}
|
||||
#[inline]
|
||||
pub const fn types(self, val: u8) -> Self {
|
||||
Self((self.0 & 0xFFF0) | (val as u16 & 0x000F))
|
||||
}
|
||||
#[inline]
|
||||
pub const fn flags(self, val: u16) -> Self {
|
||||
Self((self.0 & 0x000F) | ((val << 4) & 0xFFF0))
|
||||
}
|
||||
#[inline]
|
||||
pub const fn set_flag(&mut self, val: u16){
|
||||
self.0 |= (val & 0xFFF) << 4;
|
||||
}
|
||||
#[inline]
|
||||
pub const fn set_types(&mut self, val: u8){
|
||||
self.0 |= val as u16 & 0x0F;
|
||||
}
|
||||
}
|
||||
|
||||
pub mod flags {
|
||||
pub const ACK: u16 = 0x001;
|
||||
pub const RELIABLE: u16 = 0x002;
|
||||
pub const NEED_ACK: u16 = 0x004;
|
||||
pub const HAS_SIZE: u16 = 0x008;
|
||||
pub const MULTI_ACK: u16 = 0x200;
|
||||
}
|
||||
|
||||
pub mod types {
|
||||
pub const SYN: u8 = 0x0;
|
||||
pub const CONNECT: u8 = 0x1;
|
||||
pub const DATA: u8 = 0x2;
|
||||
pub const DISCONNECT: u8 = 0x3;
|
||||
pub const PING: u8 = 0x4;
|
||||
/// no idea what user is supposed to mean
|
||||
pub const USER: u8 = 0x5;
|
||||
}
|
||||
|
||||
impl Debug for TypesFlags {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
let stream_type = self.get_types();
|
||||
let port_number = self.get_flags();
|
||||
write!(f, "TypesFlags{{ types: {}, flags: {} }}", stream_type, port_number)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, Pod, Zeroable, SwapEndian, Eq, PartialEq)]
|
||||
pub struct PRUDPV1Header {
|
||||
|
|
@ -116,7 +57,7 @@ pub struct PRUDPV1Header {
|
|||
|
||||
impl Default for PRUDPV1Header {
|
||||
fn default() -> Self {
|
||||
Self{
|
||||
Self {
|
||||
magic: [0xEA, 0xD0],
|
||||
version: 1,
|
||||
session_id: 0,
|
||||
|
|
@ -126,32 +67,30 @@ impl Default for PRUDPV1Header {
|
|||
destination_port: VirtualPort(0),
|
||||
types_and_flags: TypesFlags(0),
|
||||
packet_specific_size: 0,
|
||||
substream_id: 0
|
||||
substream_id: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub enum PacketOption{
|
||||
pub enum PacketOption {
|
||||
SupportedFunctions(u32),
|
||||
ConnectionSignature([u8; 16]),
|
||||
FragmentId(u8),
|
||||
InitialSequenceId(u16),
|
||||
MaximumSubstreamId(u8)
|
||||
MaximumSubstreamId(u8),
|
||||
}
|
||||
|
||||
impl PacketOption{
|
||||
fn from(option_id: OptionId, option_data: &[u8]) -> io::Result<Self>{
|
||||
|
||||
impl PacketOption {
|
||||
fn from(option_id: OptionId, option_data: &[u8]) -> io::Result<Self> {
|
||||
let mut data_cursor = Cursor::new(option_data);
|
||||
let val = match option_id.into(){
|
||||
let val = match option_id.into() {
|
||||
0 => SupportedFunctions(data_cursor.read_struct(IS_BIG_ENDIAN)?),
|
||||
1 => ConnectionSignature(data_cursor.read_struct(IS_BIG_ENDIAN)?),
|
||||
2 => FragmentId(data_cursor.read_struct(IS_BIG_ENDIAN)?),
|
||||
3 => InitialSequenceId(data_cursor.read_struct(IS_BIG_ENDIAN)?),
|
||||
4 => MaximumSubstreamId(data_cursor.read_struct(IS_BIG_ENDIAN)?),
|
||||
_ => unreachable!()
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
Ok(val)
|
||||
|
|
@ -212,7 +151,7 @@ impl OptionId {
|
|||
// Invariant is upheld because we only create the object if it doesn't violate the invariant
|
||||
match val {
|
||||
0 | 1 | 2 | 3 | 4 => Ok(Self(val)),
|
||||
_ => Err(Error::InvalidOptionId(val))
|
||||
_ => Err(Error::InvalidOptionId(val)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -223,7 +162,7 @@ impl OptionId {
|
|||
2 => 1,
|
||||
3 => 2,
|
||||
4 => 1,
|
||||
_ => unreachable!()
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -238,8 +177,7 @@ impl PRUDPV1Packet {
|
|||
pub fn new(reader: &mut (impl Read + Seek)) -> Result<Self> {
|
||||
let header: PRUDPV1Header = reader.read_struct(IS_BIG_ENDIAN)?;
|
||||
|
||||
if header.magic[0] != 0xEA ||
|
||||
header.magic[1] != 0xD0 {
|
||||
if header.magic[0] != 0xEA || header.magic[1] != 0xD0 {
|
||||
return Err(Error::InvalidMagic(u16::from_be_bytes(header.magic)));
|
||||
}
|
||||
|
||||
|
|
@ -247,31 +185,31 @@ impl PRUDPV1Packet {
|
|||
return Err(Error::InvalidVersion(header.version));
|
||||
}
|
||||
|
||||
|
||||
let packet_signature: [u8; 16] = reader.read_struct(IS_BIG_ENDIAN)?;
|
||||
//let packet_signature: [u8; 16] = [0; 16];
|
||||
|
||||
assert_eq!(reader.stream_position().ok(), Some(14 + 16));
|
||||
|
||||
|
||||
|
||||
let mut packet_specific_buffer = vec![0u8; header.packet_specific_size as usize];
|
||||
|
||||
reader.read_exact(&mut packet_specific_buffer)?;
|
||||
|
||||
|
||||
//no clue whats up with options but they are broken
|
||||
let mut packet_specific_data_cursor = Cursor::new(&packet_specific_buffer);
|
||||
|
||||
let mut options = Vec::new();
|
||||
|
||||
loop {
|
||||
let Ok(option_id): io::Result<u8> = packet_specific_data_cursor.read_struct(IS_BIG_ENDIAN) else {
|
||||
break
|
||||
let Ok(option_id): io::Result<u8> =
|
||||
packet_specific_data_cursor.read_struct(IS_BIG_ENDIAN)
|
||||
else {
|
||||
break;
|
||||
};
|
||||
|
||||
let Ok(value_size): io::Result<u8> = packet_specific_data_cursor.read_struct(IS_BIG_ENDIAN) else {
|
||||
break
|
||||
let Ok(value_size): io::Result<u8> =
|
||||
packet_specific_data_cursor.read_struct(IS_BIG_ENDIAN)
|
||||
else {
|
||||
break;
|
||||
};
|
||||
|
||||
if value_size == 0 {
|
||||
|
|
@ -291,20 +229,21 @@ impl PRUDPV1Packet {
|
|||
}
|
||||
|
||||
let mut option_data = vec![0u8; value_size as usize];
|
||||
if packet_specific_data_cursor.read_exact(&mut option_data[..]).is_err() {
|
||||
if packet_specific_data_cursor
|
||||
.read_exact(&mut option_data[..])
|
||||
.is_err()
|
||||
{
|
||||
error!("unable to read options");
|
||||
break;
|
||||
}
|
||||
|
||||
options.push(PacketOption::from(option_id, &option_data)?);
|
||||
}
|
||||
|
||||
|
||||
let mut payload = vec![0u8; header.payload_size as usize];
|
||||
|
||||
reader.read_exact(&mut payload)?;
|
||||
|
||||
|
||||
|
||||
Ok(Self {
|
||||
header,
|
||||
packet_signature,
|
||||
|
|
@ -313,22 +252,21 @@ impl PRUDPV1Packet {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn base_acknowledgement_packet(&self) -> Self{
|
||||
pub fn base_acknowledgement_packet(&self) -> Self {
|
||||
let base = self.base_response_packet();
|
||||
|
||||
let mut flags = self.header.types_and_flags.flags(0);
|
||||
|
||||
flags.set_flag(ACK);
|
||||
|
||||
let options = self.options
|
||||
let options = self
|
||||
.options
|
||||
.iter()
|
||||
.filter(|o| matches!(o, FragmentId(_)))
|
||||
.cloned()
|
||||
.collect();
|
||||
|
||||
|
||||
|
||||
Self{
|
||||
Self {
|
||||
header: PRUDPV1Header {
|
||||
types_and_flags: flags,
|
||||
sequence_id: self.header.sequence_id,
|
||||
|
|
@ -348,17 +286,24 @@ impl PRUDPV1Packet {
|
|||
}
|
||||
}
|
||||
|
||||
fn generate_options_bytes(&self) -> Vec<u8>{
|
||||
fn generate_options_bytes(&self) -> Vec<u8> {
|
||||
let mut vec = Vec::new();
|
||||
|
||||
for option in &self.options{
|
||||
option.write_to_stream(&mut vec).expect("vec should always automatically be able to extend");
|
||||
for option in &self.options {
|
||||
option
|
||||
.write_to_stream(&mut vec)
|
||||
.expect("vec should always automatically be able to extend");
|
||||
}
|
||||
|
||||
vec
|
||||
}
|
||||
|
||||
pub fn calculate_signature_value(&self, access_key: &str, session_key: Option<[u8; 32]>, connection_signature: Option<[u8; 16]>) -> [u8; 16]{
|
||||
pub fn calculate_signature_value(
|
||||
&self,
|
||||
access_key: &str,
|
||||
session_key: Option<[u8; 32]>,
|
||||
connection_signature: Option<[u8; 16]>,
|
||||
) -> [u8; 16] {
|
||||
let access_key_bytes = access_key.as_bytes();
|
||||
let access_key_sum: u32 = access_key_bytes.iter().map(|v| *v as u32).sum();
|
||||
let access_key_sum_bytes: [u8; 4] = access_key_sum.to_le_bytes();
|
||||
|
|
@ -374,32 +319,46 @@ impl PRUDPV1Packet {
|
|||
|
||||
let mut hmac = Md5Hmac::new_from_slice(&key).expect("fuck");
|
||||
|
||||
hmac.write(&header_data).expect("error during hmac calculation");
|
||||
hmac.write(&header_data)
|
||||
.expect("error during hmac calculation");
|
||||
if let Some(session_key) = session_key {
|
||||
hmac.write(&session_key).expect("error during hmac calculation");
|
||||
hmac.write(&session_key)
|
||||
.expect("error during hmac calculation");
|
||||
}
|
||||
hmac.write(&access_key_sum_bytes).expect("error during hmac calculation");
|
||||
hmac.write(&access_key_sum_bytes)
|
||||
.expect("error during hmac calculation");
|
||||
if let Some(connection_signature) = connection_signature {
|
||||
hmac.write(&connection_signature).expect("error during hmac calculation");
|
||||
hmac.write(&connection_signature)
|
||||
.expect("error during hmac calculation");
|
||||
}
|
||||
|
||||
hmac.write(&option_bytes).expect("error during hmac calculation");
|
||||
hmac.write(&option_bytes)
|
||||
.expect("error during hmac calculation");
|
||||
|
||||
hmac.write_all(&self.payload).expect("error during hmac calculation");
|
||||
hmac.write_all(&self.payload)
|
||||
.expect("error during hmac calculation");
|
||||
|
||||
hmac.finalize().into_bytes()[0..16].try_into().expect("invalid hmac size")
|
||||
hmac.finalize().into_bytes()[0..16]
|
||||
.try_into()
|
||||
.expect("invalid hmac size")
|
||||
}
|
||||
|
||||
pub fn calculate_and_assign_signature(&mut self, access_key: &str, session_key: Option<[u8; 32]>, connection_signature: Option<[u8; 16]>){
|
||||
self.packet_signature = self.calculate_signature_value(access_key, session_key, connection_signature);
|
||||
pub fn calculate_and_assign_signature(
|
||||
&mut self,
|
||||
access_key: &str,
|
||||
session_key: Option<[u8; 32]>,
|
||||
connection_signature: Option<[u8; 16]>,
|
||||
) {
|
||||
self.packet_signature =
|
||||
self.calculate_signature_value(access_key, session_key, connection_signature);
|
||||
}
|
||||
|
||||
pub fn set_sizes(&mut self){
|
||||
pub fn set_sizes(&mut self) {
|
||||
self.header.packet_specific_size = self.options.iter().map(|o| o.write_size()).sum();
|
||||
self.header.payload_size = self.payload.len() as u16;
|
||||
}
|
||||
|
||||
pub fn base_response_packet(&self) -> Self {
|
||||
pub fn base_response_packet(&self) -> Self {
|
||||
Self {
|
||||
header: PRUDPV1Header {
|
||||
magic: [0xEA, 0xD0],
|
||||
|
|
@ -412,19 +371,18 @@ impl PRUDPV1Packet {
|
|||
sequence_id: 0,
|
||||
session_id: 0,
|
||||
substream_id: 0,
|
||||
|
||||
},
|
||||
packet_signature: [0; 16],
|
||||
payload: Default::default(),
|
||||
options: Default::default()
|
||||
options: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_to(&self, writer: &mut impl Write) -> io::Result<()>{
|
||||
pub fn write_to(&self, writer: &mut impl Write) -> io::Result<()> {
|
||||
writer.write_all(bytemuck::bytes_of(&self.header))?;
|
||||
writer.write_all(&self.packet_signature)?;
|
||||
|
||||
for option in &self.options{
|
||||
for option in &self.options {
|
||||
option.write_to_stream(writer)?;
|
||||
}
|
||||
|
||||
|
|
@ -436,20 +394,24 @@ impl PRUDPV1Packet {
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::prudp::packet::flags::{NEED_ACK, RELIABLE};
|
||||
use crate::prudp::packet::types::DATA;
|
||||
use super::{OptionId, PacketOption, PRUDPV1Header, TypesFlags};
|
||||
use rnex_core::prudp::virtual_port::VirtualPort;
|
||||
use super::{OptionId, PRUDPV1Header, PacketOption, TypesFlags};
|
||||
use rnex_core::prudp::{
|
||||
types_flags::{
|
||||
flags::{NEED_ACK, RELIABLE},
|
||||
types::DATA,
|
||||
},
|
||||
virtual_port::VirtualPort,
|
||||
};
|
||||
#[test]
|
||||
fn size_test() {
|
||||
assert_eq!(size_of::<PRUDPV1Header>(), 14);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_options(){
|
||||
let packet_types = [0,1,2,3,4];
|
||||
fn test_options() {
|
||||
let packet_types = [0, 1, 2, 3, 4];
|
||||
|
||||
for p_type in packet_types{
|
||||
for p_type in packet_types {
|
||||
let option_id = OptionId::new(p_type).unwrap();
|
||||
|
||||
let buf = vec![0; option_id.option_type_size() as usize];
|
||||
|
|
@ -463,12 +425,10 @@ mod test {
|
|||
assert_eq!(write_buf.len() as u8, opt.write_size())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn header_read(){
|
||||
fn header_read() {
|
||||
let header = PRUDPV1Header {
|
||||
version: 0,
|
||||
destination_port: VirtualPort(0),
|
||||
|
|
@ -478,8 +438,8 @@ mod test {
|
|||
packet_specific_size: 0,
|
||||
payload_size: 0,
|
||||
sequence_id: 0,
|
||||
magic: [0xEA,0xD0],
|
||||
source_port: VirtualPort(0)
|
||||
magic: [0xEA, 0xD0],
|
||||
source_port: VirtualPort(0),
|
||||
};
|
||||
|
||||
let bytes = bytemuck::bytes_of(&header);
|
||||
|
|
@ -490,11 +450,11 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_types_flags(){
|
||||
fn test_types_flags() {
|
||||
let types = TypesFlags::default().types(DATA).flags(NEED_ACK | RELIABLE);
|
||||
|
||||
assert_ne!((types.0 >> 4) & NEED_ACK, 0);
|
||||
assert_ne!((types.0 >> 4) & RELIABLE, 0);
|
||||
assert_ne!((types.0 & 0xFF) as u8 & DATA, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,19 @@
|
|||
use std::io::Cursor;
|
||||
use crate::prudp::packet::PRUDPV1Packet;
|
||||
use crate::prudp::socket::{CryptoHandler, CryptoHandlerConnectionInstance};
|
||||
use hmac::digest::consts::U32;
|
||||
use log::error;
|
||||
use rc4::cipher::StreamCipherCoreWrapper;
|
||||
use rc4::{KeyInit, Rc4, Rc4Core, StreamCipher};
|
||||
use rc4::consts::U16;
|
||||
use rc4::{KeyInit, Rc4, Rc4Core, StreamCipher};
|
||||
use rnex_core::kerberos::{TicketInternalData, derive_key};
|
||||
use rnex_core::nex::account::Account;
|
||||
use rnex_core::prudp::encryption::EncryptionPair;
|
||||
use rnex_core::rmc::structures::RmcSerialize;
|
||||
use std::io::Cursor;
|
||||
use typenum::U5;
|
||||
use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions};
|
||||
use rnex_core::kerberos::{derive_key, TicketInternalData};
|
||||
use rnex_core::nex::account::Account;
|
||||
use crate::prudp::packet::PRUDPV1Packet;
|
||||
use crate::prudp::socket::{CryptoHandler, CryptoHandlerConnectionInstance, EncryptionPair};
|
||||
use rnex_core::rmc::structures::RmcSerialize;
|
||||
|
||||
pub fn read_secure_connection_data(data: &[u8], act: &Account) -> Option<([u8; 32], u32, u32)>{
|
||||
pub fn read_secure_connection_data(data: &[u8], act: &Account) -> Option<([u8; 32], u32, u32)> {
|
||||
let mut cursor = Cursor::new(data);
|
||||
|
||||
let mut ticket_data: Vec<u8> = Vec::deserialize(&mut cursor).ok()?;
|
||||
|
|
@ -20,7 +21,7 @@ pub fn read_secure_connection_data(data: &[u8], act: &Account) -> Option<([u8; 3
|
|||
|
||||
let ticket_data_size = ticket_data.len();
|
||||
|
||||
let ticket_data = &mut ticket_data[0..ticket_data_size-0x10];
|
||||
let ticket_data = &mut ticket_data[0..ticket_data_size - 0x10];
|
||||
|
||||
let server_key = derive_key(act.pid, act.kerbros_password);
|
||||
|
||||
|
|
@ -29,7 +30,7 @@ pub fn read_secure_connection_data(data: &[u8], act: &Account) -> Option<([u8; 3
|
|||
|
||||
rc4.apply_keystream(ticket_data);
|
||||
|
||||
let ticket_data: &TicketInternalData = match bytemuck::try_from_bytes(ticket_data){
|
||||
let ticket_data: &TicketInternalData = match bytemuck::try_from_bytes(ticket_data) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
error!("unable to read internal ticket data: {}", e);
|
||||
|
|
@ -39,15 +40,15 @@ pub fn read_secure_connection_data(data: &[u8], act: &Account) -> Option<([u8; 3
|
|||
|
||||
// todo: add ticket expiration
|
||||
|
||||
let TicketInternalData{
|
||||
let TicketInternalData {
|
||||
session_key,
|
||||
pid: ticket_source_pid,
|
||||
issued_time
|
||||
issued_time,
|
||||
} = *ticket_data;
|
||||
|
||||
// todo: add checking if tickets are signed with a valid md5-hmac
|
||||
let request_data_length = request_data.len();
|
||||
let request_data = &mut request_data[0.. request_data_length - 0x10];
|
||||
let request_data = &mut request_data[0..request_data_length - 0x10];
|
||||
|
||||
let mut rc4: StreamCipherCoreWrapper<Rc4Core<U32>> =
|
||||
Rc4::new_from_slice(&session_key).expect("unable to init rc4 keystream");
|
||||
|
|
@ -58,53 +59,55 @@ pub fn read_secure_connection_data(data: &[u8], act: &Account) -> Option<([u8; 3
|
|||
|
||||
let pid: u32 = reqest_data_cursor.read_struct(IS_BIG_ENDIAN).ok()?;
|
||||
|
||||
if pid != ticket_source_pid{
|
||||
if pid != ticket_source_pid {
|
||||
let ticket_created_on = issued_time.to_regular_time();
|
||||
|
||||
error!("someone tried to spoof their pid, ticket was created on: {}", ticket_created_on.to_rfc2822());
|
||||
error!(
|
||||
"someone tried to spoof their pid, ticket was created on: {}",
|
||||
ticket_created_on.to_rfc2822()
|
||||
);
|
||||
return None;
|
||||
}
|
||||
|
||||
let _cid: u32 = reqest_data_cursor.read_struct(IS_BIG_ENDIAN).ok()?;
|
||||
let response_check: u32 = reqest_data_cursor.read_struct(IS_BIG_ENDIAN).ok()?;
|
||||
|
||||
|
||||
|
||||
Some((session_key, pid, response_check))
|
||||
}
|
||||
|
||||
type Rc4U32 = StreamCipherCoreWrapper<Rc4Core<U32>>;
|
||||
|
||||
pub fn generate_secure_encryption_pairs(mut session_key: [u8; 32], count: u8) -> Vec<EncryptionPair<Rc4<U32>>>{
|
||||
pub fn generate_secure_encryption_pairs(
|
||||
mut session_key: [u8; 32],
|
||||
count: u8,
|
||||
) -> Vec<EncryptionPair<Rc4<U32>>> {
|
||||
let mut vec = Vec::with_capacity(count as usize);
|
||||
|
||||
vec.push(EncryptionPair{
|
||||
vec.push(EncryptionPair {
|
||||
send: Rc4U32::new_from_slice(&session_key).expect("unable to create rc4"),
|
||||
recv: Rc4U32::new_from_slice(&session_key).expect("unable to create rc4")
|
||||
recv: Rc4U32::new_from_slice(&session_key).expect("unable to create rc4"),
|
||||
});
|
||||
|
||||
for _ in 1..=count{
|
||||
for _ in 1..=count {
|
||||
let modifier = session_key.len() + 1;
|
||||
|
||||
let key_length = session_key.len();
|
||||
|
||||
for (position, val) in (&mut session_key[0..key_length/2]).iter_mut().enumerate(){
|
||||
for (position, val) in (&mut session_key[0..key_length / 2]).iter_mut().enumerate() {
|
||||
*val = val.wrapping_add((modifier - position) as u8);
|
||||
}
|
||||
|
||||
vec.push(EncryptionPair{
|
||||
vec.push(EncryptionPair {
|
||||
send: Rc4U32::new_from_slice(&session_key).expect("unable to create rc4"),
|
||||
recv: Rc4U32::new_from_slice(&session_key).expect("unable to create rc4")
|
||||
recv: Rc4U32::new_from_slice(&session_key).expect("unable to create rc4"),
|
||||
});
|
||||
}
|
||||
|
||||
vec
|
||||
}
|
||||
|
||||
|
||||
pub struct Secure(pub &'static str, pub Account);
|
||||
|
||||
|
||||
pub struct SecureInstance {
|
||||
access_key: &'static str,
|
||||
session_key: [u8; 32],
|
||||
|
|
@ -155,18 +158,17 @@ impl CryptoHandler for Secure {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
impl CryptoHandlerConnectionInstance for SecureInstance {
|
||||
type Encryption = Rc4<U5>;
|
||||
|
||||
fn decrypt_incoming(&mut self, substream: u8, data: &mut [u8]) {
|
||||
if let Some(crypt_pair) = self.streams.get_mut(substream as usize){
|
||||
if let Some(crypt_pair) = self.streams.get_mut(substream as usize) {
|
||||
crypt_pair.recv.apply_keystream(data);
|
||||
}
|
||||
}
|
||||
|
||||
fn encrypt_outgoing(&mut self, substream: u8, data: &mut [u8]) {
|
||||
if let Some(crypt_pair) = self.streams.get_mut(substream as usize){
|
||||
if let Some(crypt_pair) = self.streams.get_mut(substream as usize) {
|
||||
crypt_pair.send.apply_keystream(data);
|
||||
}
|
||||
}
|
||||
|
|
@ -182,10 +184,14 @@ impl CryptoHandlerConnectionInstance for SecureInstance {
|
|||
|
||||
fn sign_packet(&self, packet: &mut PRUDPV1Packet) {
|
||||
packet.set_sizes();
|
||||
packet.calculate_and_assign_signature(self.access_key, Some(self.session_key), Some(self.self_signature));
|
||||
packet.calculate_and_assign_signature(
|
||||
self.access_key,
|
||||
Some(self.session_key),
|
||||
Some(self.self_signature),
|
||||
);
|
||||
}
|
||||
|
||||
fn verify_packet(&self, _packet: &PRUDPV1Packet) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,47 +1,34 @@
|
|||
use crate::prudp::packet::flags::{ACK, HAS_SIZE, MULTI_ACK, NEED_ACK, RELIABLE};
|
||||
use crate::prudp::packet::types::{CONNECT, DATA, DISCONNECT, PING, SYN};
|
||||
use crate::prudp::packet::PacketOption::{
|
||||
ConnectionSignature, FragmentId, MaximumSubstreamId, SupportedFunctions,
|
||||
};
|
||||
use crate::prudp::packet::{PRUDPV1Header, PRUDPV1Packet, TypesFlags};
|
||||
use rnex_core::prudp::virtual_port::VirtualPort;
|
||||
use rnex_core::prudp::socket_addr::PRUDPSockAddr;
|
||||
use crate::prudp::packet::{PRUDPV1Header, PRUDPV1Packet};
|
||||
use async_trait::async_trait;
|
||||
use log::{info, warn};
|
||||
use log::error;
|
||||
use log::{info, warn};
|
||||
use rc4::StreamCipher;
|
||||
use v_byte_helpers::ReadExtensions;
|
||||
use v_byte_helpers::little_endian::read_u16;
|
||||
use rnex_core::prudp::socket_addr::PRUDPSockAddr;
|
||||
use rnex_core::prudp::types_flags::TypesFlags;
|
||||
use rnex_core::prudp::types_flags::flags::{ACK, HAS_SIZE, MULTI_ACK, NEED_ACK, RELIABLE};
|
||||
use rnex_core::prudp::types_flags::types::{CONNECT, DATA, DISCONNECT, PING, SYN};
|
||||
use rnex_core::prudp::virtual_port::VirtualPort;
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::io::Cursor;
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::Deref;
|
||||
use std::sync::{Arc, Weak};
|
||||
use v_byte_helpers::ReadExtensions;
|
||||
use v_byte_helpers::little_endian::read_u16;
|
||||
|
||||
use std::time::Duration;
|
||||
use tokio::net::UdpSocket;
|
||||
use tokio::sync::mpsc::{channel, Receiver, Sender};
|
||||
use tokio::sync::Mutex;
|
||||
use tokio::time::{sleep, Instant};
|
||||
use tokio::sync::mpsc::{Receiver, Sender, channel};
|
||||
use tokio::time::{Instant, sleep};
|
||||
// due to the way this is designed crashing the router thread causes deadlock, sorry ;-;
|
||||
// (maybe i will fix that some day)
|
||||
|
||||
/// PRUDP Socket for accepting connections to then send and recieve data from those clients
|
||||
|
||||
pub struct EncryptionPair<T: StreamCipher + Send> {
|
||||
pub send: T,
|
||||
pub recv: T,
|
||||
}
|
||||
|
||||
impl<T: StreamCipher + Send> EncryptionPair<T> {
|
||||
pub fn init_both<F: Fn() -> T>(func: F) -> Self {
|
||||
Self {
|
||||
recv: func(),
|
||||
send: func(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CommonConnection {
|
||||
pub user_id: u32,
|
||||
pub socket_addr: PRUDPSockAddr,
|
||||
|
|
@ -61,7 +48,7 @@ struct InternalConnection<E: CryptoHandlerConnectionInstance> {
|
|||
socket: Arc<UdpSocket>,
|
||||
packet_queue: HashMap<u16, PRUDPV1Packet>,
|
||||
last_packet_time: Instant,
|
||||
unacknowleged_packets: Vec<(Instant, PRUDPV1Packet)>
|
||||
unacknowleged_packets: Vec<(Instant, PRUDPV1Packet)>,
|
||||
}
|
||||
|
||||
impl<E: CryptoHandlerConnectionInstance> Deref for InternalConnection<E> {
|
||||
|
|
@ -82,17 +69,17 @@ impl<E: CryptoHandlerConnectionInstance> InternalConnection<E> {
|
|||
}
|
||||
|
||||
/// Sends a raw packet to a given client on the connection
|
||||
///
|
||||
/// a raw packet is one which does not get processed any further(other than to send it
|
||||
///
|
||||
/// a raw packet is one which does not get processed any further(other than to send it
|
||||
/// off without buffering or anything),
|
||||
/// as such you need to make sure that
|
||||
/// as such you need to make sure that
|
||||
/// the sizes are set correctly and so on
|
||||
#[inline]
|
||||
async fn send_raw_packet(&self, prudp_packet: &PRUDPV1Packet) {
|
||||
send_raw_prudp_to_sockaddr(&self.socket, self.socket_addr, prudp_packet).await;
|
||||
}
|
||||
|
||||
async fn delete_connection(&self){
|
||||
async fn delete_connection(&self) {
|
||||
let Some(conns) = self.connections.upgrade() else {
|
||||
// this is fine as it implies the server has already quit, thus meaning that we dont
|
||||
// have to remove ourselves from the server
|
||||
|
|
@ -187,8 +174,6 @@ pub(super) trait AnyInternalConnection:
|
|||
async fn close_connection(&mut self);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[async_trait]
|
||||
impl<T: CryptoHandlerConnectionInstance> AnyInternalConnection for InternalConnection<T> {
|
||||
async fn send_data_packet(&mut self, data: Vec<u8>) {
|
||||
|
|
@ -219,7 +204,6 @@ impl<T: CryptoHandlerConnectionInstance> AnyInternalConnection for InternalConne
|
|||
self.unacknowleged_packets.push((Instant::now(), packet));
|
||||
}
|
||||
|
||||
|
||||
async fn close_connection(&mut self) {
|
||||
// jon confirmed that this should be a safe way to dc a client
|
||||
|
||||
|
|
@ -250,7 +234,11 @@ impl<T: CryptoHandlerConnectionInstance> AnyInternalConnection for InternalConne
|
|||
}
|
||||
}
|
||||
|
||||
async fn send_raw_prudp_to_sockaddr(udp_socket: &UdpSocket, dest: PRUDPSockAddr, packet: &PRUDPV1Packet){
|
||||
async fn send_raw_prudp_to_sockaddr(
|
||||
udp_socket: &UdpSocket,
|
||||
dest: PRUDPSockAddr,
|
||||
packet: &PRUDPV1Packet,
|
||||
) {
|
||||
let mut vec = Vec::new();
|
||||
|
||||
packet
|
||||
|
|
@ -281,7 +269,7 @@ impl<T: CryptoHandler> InternalSocket<T> {
|
|||
}
|
||||
|
||||
/// sends a raw packet to a specific prudp socket address
|
||||
///
|
||||
///
|
||||
/// a raw packet is a packet is a packet which wont get processed any further,
|
||||
/// sizes signatures etc need to be set before using this function
|
||||
async fn send_packet_unbuffered(&self, dest: PRUDPSockAddr, packet: &PRUDPV1Packet) {
|
||||
|
|
@ -353,13 +341,15 @@ impl<T: CryptoHandler> InternalSocket<T> {
|
|||
conn.close_connection().await;
|
||||
}
|
||||
|
||||
for (send_time, packet) in &conn.unacknowleged_packets{
|
||||
if *send_time < (Instant::now() - Duration::from_millis(3000)){
|
||||
warn!("failed to resend packet 5 times and never got response, destroying connection");
|
||||
for (send_time, packet) in &conn.unacknowleged_packets {
|
||||
if *send_time < (Instant::now() - Duration::from_millis(3000)) {
|
||||
warn!(
|
||||
"failed to resend packet 5 times and never got response, destroying connection"
|
||||
);
|
||||
conn.close_connection().await;
|
||||
break;
|
||||
}
|
||||
if *send_time < (Instant::now() - Duration::from_millis(500)){
|
||||
if *send_time < (Instant::now() - Duration::from_millis(500)) {
|
||||
info!("unacknowledged packet sat arround for more than 500 ms, resending");
|
||||
conn.send_raw_packet(packet).await;
|
||||
}
|
||||
|
|
@ -399,7 +389,7 @@ impl<T: CryptoHandler> InternalSocket<T> {
|
|||
packet_queue: Default::default(),
|
||||
last_packet_time: Instant::now(),
|
||||
unacknowleged_packets: Vec::new(),
|
||||
supported_function_version
|
||||
supported_function_version,
|
||||
};
|
||||
|
||||
let internal = Arc::new(Mutex::new(internal));
|
||||
|
|
@ -487,7 +477,7 @@ impl<T: CryptoHandler> InternalSocket<T> {
|
|||
SupportedFunctions(funcs) => {
|
||||
functions = *funcs & 0xFF;
|
||||
response.options.push(SupportedFunctions(*funcs & 0xFF));
|
||||
},
|
||||
}
|
||||
_ => { /* ? */ }
|
||||
}
|
||||
}
|
||||
|
|
@ -610,7 +600,6 @@ impl<T: CryptoHandler> AnyInternalSocket for InternalSocket<T> {
|
|||
if (packet.header.types_and_flags.get_flags() & ACK) != 0 {
|
||||
info!("got ack");
|
||||
|
||||
|
||||
if packet.header.types_and_flags.get_types() == SYN
|
||||
|| packet.header.types_and_flags.get_types() == CONNECT
|
||||
{
|
||||
|
|
@ -645,9 +634,8 @@ impl<T: CryptoHandler> AnyInternalSocket for InternalSocket<T> {
|
|||
|
||||
// remove the packet whose sequence id matches the ack packet
|
||||
// or in other words keep all of those which dont match the sequence id
|
||||
conn.unacknowleged_packets.retain_mut(|v| {
|
||||
packet.header.sequence_id != v.1.header.sequence_id
|
||||
});
|
||||
conn.unacknowleged_packets
|
||||
.retain_mut(|v| packet.header.sequence_id != v.1.header.sequence_id);
|
||||
} else {
|
||||
error!("non connection acknowledgement packet on nonexistent connection...")
|
||||
}
|
||||
|
|
@ -659,26 +647,23 @@ impl<T: CryptoHandler> AnyInternalSocket for InternalSocket<T> {
|
|||
if let Some(conn) = self.get_connection(address).await {
|
||||
let mut conn = conn.lock().await;
|
||||
|
||||
if conn.supported_function_version == 1{
|
||||
if conn.supported_function_version == 1 {
|
||||
let mut collected_ids: Vec<u16> = Vec::new();
|
||||
let mut cursor = Cursor::new(&packet.payload);
|
||||
|
||||
while let Ok(v) = read_u16(&mut cursor){
|
||||
while let Ok(v) = read_u16(&mut cursor) {
|
||||
collected_ids.push(v);
|
||||
}
|
||||
|
||||
conn.unacknowleged_packets.retain_mut(|(_, up)| {
|
||||
!(
|
||||
collected_ids.iter().any(|id| up.header.sequence_id == *id) ||
|
||||
up.header.sequence_id <= packet.header.sequence_id
|
||||
)
|
||||
!(collected_ids.iter().any(|id| up.header.sequence_id == *id)
|
||||
|| up.header.sequence_id <= packet.header.sequence_id)
|
||||
});
|
||||
|
||||
} else {
|
||||
let mut collected_ids: Vec<u16> = Vec::new();
|
||||
let mut cursor = Cursor::new(&packet.payload);
|
||||
|
||||
let Ok(_substream_id): Result<u8, _> = cursor.read_le_struct() else{
|
||||
let Ok(_substream_id): Result<u8, _> = cursor.read_le_struct() else {
|
||||
error!("invalid data whilest reading new version agregate acknowledgement");
|
||||
return;
|
||||
};
|
||||
|
|
@ -690,19 +675,20 @@ impl<T: CryptoHandler> AnyInternalSocket for InternalSocket<T> {
|
|||
error!("invalid data whilest reading new version agregate acknowledgement");
|
||||
return;
|
||||
};
|
||||
for _ in 0..additional_sequence_ids{
|
||||
let Ok(additional_sequence_id): Result<u16, _> = cursor.read_le_struct() else {
|
||||
error!("invalid data whilest reading new version agregate acknowledgement");
|
||||
for _ in 0..additional_sequence_ids {
|
||||
let Ok(additional_sequence_id): Result<u16, _> = cursor.read_le_struct()
|
||||
else {
|
||||
error!(
|
||||
"invalid data whilest reading new version agregate acknowledgement"
|
||||
);
|
||||
return;
|
||||
};
|
||||
collected_ids.push(additional_sequence_id);
|
||||
}
|
||||
|
||||
conn.unacknowleged_packets.retain_mut(|(_, up)| {
|
||||
!(
|
||||
collected_ids.iter().any(|id| up.header.sequence_id == *id) ||
|
||||
up.header.sequence_id <= sequence_id
|
||||
)
|
||||
!(collected_ids.iter().any(|id| up.header.sequence_id == *id)
|
||||
|| up.header.sequence_id <= sequence_id)
|
||||
});
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
use crate::prudp::packet::PRUDPV1Packet;
|
||||
use crate::prudp::socket::{CryptoHandler, CryptoHandlerConnectionInstance};
|
||||
use once_cell::sync::Lazy;
|
||||
use rc4::{Key, KeyInit, Rc4, StreamCipher};
|
||||
use rnex_core::prudp::encryption::{DEFAULT_KEY, EncryptionPair};
|
||||
use typenum::U5;
|
||||
use crate::prudp::packet::PRUDPV1Packet;
|
||||
use crate::prudp::socket::{CryptoHandler, CryptoHandlerConnectionInstance, EncryptionPair};
|
||||
|
||||
pub struct Unsecure(pub &'static str);
|
||||
|
||||
|
||||
|
||||
pub struct UnsecureInstance {
|
||||
key: &'static str,
|
||||
streams: Vec<EncryptionPair<Rc4<U5>>>,
|
||||
|
|
@ -18,7 +17,6 @@ pub struct UnsecureInstance {
|
|||
// my hand was forced to use lazy so that we can guarantee this code
|
||||
// only runs once and so that i can put it here as a "constant" (for performance and readability)
|
||||
// since for some reason rust crypto doesn't have any const time key initialization
|
||||
static DEFAULT_KEY: Lazy<Key<U5>> = Lazy::new(|| Key::from(*b"CD&ML"));
|
||||
|
||||
impl CryptoHandler for Unsecure {
|
||||
type CryptoConnectionInstance = UnsecureInstance;
|
||||
|
|
@ -53,13 +51,13 @@ impl CryptoHandlerConnectionInstance for UnsecureInstance {
|
|||
type Encryption = Rc4<U5>;
|
||||
|
||||
fn decrypt_incoming(&mut self, substream: u8, data: &mut [u8]) {
|
||||
if let Some(crypt_pair) = self.streams.get_mut(substream as usize){
|
||||
if let Some(crypt_pair) = self.streams.get_mut(substream as usize) {
|
||||
crypt_pair.recv.apply_keystream(data);
|
||||
}
|
||||
}
|
||||
|
||||
fn encrypt_outgoing(&mut self, substream: u8, data: &mut [u8]) {
|
||||
if let Some(crypt_pair) = self.streams.get_mut(substream as usize){
|
||||
if let Some(crypt_pair) = self.streams.get_mut(substream as usize) {
|
||||
crypt_pair.send.apply_keystream(data);
|
||||
}
|
||||
}
|
||||
|
|
@ -81,4 +79,4 @@ impl CryptoHandlerConnectionInstance for UnsecureInstance {
|
|||
fn verify_packet(&self, _packet: &PRUDPV1Packet) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue