|
|
@ -26,26 +26,29 @@ use crate::crypt; |
|
|
|
|
|
|
|
|
|
|
|
pub fn send_packet<W>(conn: &mut W, packet: &Packet, encr_type: u8, key: &Vec<u8>) -> Result<(), Error> |
|
|
|
pub fn send_packet<W>(conn: &mut W, packet: &Packet, encr_type: u8, key: &Vec<u8>) -> Result<(), Error> |
|
|
|
where W: Write { |
|
|
|
where W: Write { |
|
|
|
let mut packet_bytes: Vec<u8> = Vec::<u8>::new(); |
|
|
|
// ready-to-transport packet bytes
|
|
|
|
|
|
|
|
let mut packet_bytes: Vec<u8> = Vec::with_capacity(packet.contents.len() + 1); |
|
|
|
let packet_contents = packet.contents; |
|
|
|
packet_bytes.extend_from_slice(&packet.header.to_be_bytes()); |
|
|
|
|
|
|
|
packet_bytes.extend_from_slice(&packet.contents); |
|
|
|
|
|
|
|
|
|
|
|
match encr_type { |
|
|
|
match encr_type { |
|
|
|
ECRYPTION_XOR => { |
|
|
|
ECRYPTION_XOR => { |
|
|
|
crypt::xor::encrypt(&mut packet_contents, &crypt::keys::Key8bit::new(key[0])); |
|
|
|
crypt::xor::encrypt(&mut packet_bytes, &crypt::keys::Key8bit::new(key[0])); |
|
|
|
let packet_len: usize = packet_contents.len(); |
|
|
|
|
|
|
|
packet_bytes.extend_from_slice(&(packet_len as u128).to_be_bytes()); |
|
|
|
|
|
|
|
packet_bytes.extend_from_slice(&packet_contents);
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
_ | ENCRYPTION_NO_ENCRYPTION => { |
|
|
|
ENCRYPTION_NO_ENCRYPTION | _ => {} |
|
|
|
let packet_len: usize = packet_contents.len(); |
|
|
|
|
|
|
|
packet_bytes.extend_from_slice(&(packet_len as u128).to_be_bytes()); |
|
|
|
|
|
|
|
packet_bytes.extend_from_slice(&packet_contents); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
match conn.write_all(&packet_bytes) { |
|
|
|
|
|
|
|
|
|
|
|
// get total length and add it to the beginning
|
|
|
|
|
|
|
|
let total_packet_len: u128 = packet_bytes.len() as u128; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut transport_bytes: Vec<u8> = Vec::with_capacity((total_packet_len + 16) as usize); |
|
|
|
|
|
|
|
transport_bytes.extend_from_slice(&total_packet_len.to_be_bytes()); |
|
|
|
|
|
|
|
transport_bytes.append(&mut packet_bytes); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// send packet
|
|
|
|
|
|
|
|
match conn.write_all(&transport_bytes) { |
|
|
|
Ok(()) => { |
|
|
|
Ok(()) => { |
|
|
|
return Ok(()); |
|
|
|
return Ok(()); |
|
|
|
} |
|
|
|
} |
|
|
@ -103,16 +106,13 @@ pub fn read_next_packet<R>(conn: &mut R, encr_type: u8, key: &Vec<u8>) -> Result |
|
|
|
crypt::xor::decrypt(&mut packet_bytes, &crypt::keys::Key8bit::new(key[0])); |
|
|
|
crypt::xor::decrypt(&mut packet_bytes, &crypt::keys::Key8bit::new(key[0])); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
_ | ENCRYPTION_NO_ENCRYPTION => {} |
|
|
|
ENCRYPTION_NO_ENCRYPTION | _ => {} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
let mut packet_contents: Vec<u8> = Vec::with_capacity(packet_bytes[1..].len()); |
|
|
|
|
|
|
|
packet_contents.extend_from_slice(&packet_bytes[1..]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return Ok( |
|
|
|
return Ok( |
|
|
|
Packet{ |
|
|
|
Packet{ |
|
|
|
header: packet_bytes[0].to_be(), |
|
|
|
header: packet_bytes[0].to_be(), |
|
|
|
contents: packet_contents, |
|
|
|
contents: Vec::from(&packet_bytes[1..]), |
|
|
|
} |
|
|
|
} |
|
|
|
); |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
@ -127,12 +127,6 @@ pub struct Text { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
impl Text { |
|
|
|
impl Text { |
|
|
|
pub fn empty() -> Text { |
|
|
|
|
|
|
|
return Text{ |
|
|
|
|
|
|
|
text: "".to_string(), |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn new(txt: &str) -> Text { |
|
|
|
pub fn new(txt: &str) -> Text { |
|
|
|
return Text { |
|
|
|
return Text { |
|
|
|
text: txt.to_string(), |
|
|
|
text: txt.to_string(), |
|
|
@ -142,7 +136,7 @@ impl Text { |
|
|
|
pub fn as_raw(&self) -> Packet { |
|
|
|
pub fn as_raw(&self) -> Packet { |
|
|
|
let mut raw_packet: Packet = Packet{ |
|
|
|
let mut raw_packet: Packet = Packet{ |
|
|
|
header: TEXT_PACKET_ID, |
|
|
|
header: TEXT_PACKET_ID, |
|
|
|
contents: Vec::<u8>::new(), |
|
|
|
contents: Vec::with_capacity(self.text.len()), |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
let text_length: u128 = self.text.len() as u128; |
|
|
|
let text_length: u128 = self.text.len() as u128; |
|
|
@ -157,29 +151,29 @@ impl Text { |
|
|
|
return Err(Error::new("it is not a text packet")); |
|
|
|
return Err(Error::new("it is not a text packet")); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if raw_packet.contents.len() < 18 { |
|
|
|
if raw_packet.contents.len() < 17 { |
|
|
|
return Err( |
|
|
|
return Err( |
|
|
|
Error::new(format!("{} bytes is too small for a text packet to be valid", raw_packet.contents.len()).as_str() |
|
|
|
Error::new(format!("{} bytes is too small for a text packet to be valid", raw_packet.contents.len()).as_str() |
|
|
|
)); |
|
|
|
)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// get text length
|
|
|
|
// get text length
|
|
|
|
let text_length: u128 = read_u128_slice_be(&raw_packet.contents[1..17]); |
|
|
|
let text_length: u128 = read_u128_slice_be(&raw_packet.contents[0..16]); |
|
|
|
|
|
|
|
|
|
|
|
if text_length as usize > raw_packet.contents[17..].len() { |
|
|
|
if text_length as usize > raw_packet.contents[16..16+text_length as usize].len() { |
|
|
|
return Err( |
|
|
|
return Err( |
|
|
|
Error::new( |
|
|
|
Error::new( |
|
|
|
format!( |
|
|
|
format!( |
|
|
|
"text length ({}) is bigger than provided packet bytes length ({})", |
|
|
|
"text length ({}) is bigger than provided packet bytes length ({})", |
|
|
|
text_length, |
|
|
|
text_length, |
|
|
|
raw_packet.contents[16..].len() |
|
|
|
raw_packet.contents[16..16+text_length as usize].len() |
|
|
|
).as_str() |
|
|
|
).as_str() |
|
|
|
) |
|
|
|
) |
|
|
|
); |
|
|
|
); |
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// extract text
|
|
|
|
// extract text
|
|
|
|
let packet_text = read_utf8_string_slice(&raw_packet.contents[17..]); |
|
|
|
let packet_text = read_utf8_string_slice(&raw_packet.contents[16..16+text_length as usize]); |
|
|
|
|
|
|
|
|
|
|
|
return Ok( |
|
|
|
return Ok( |
|
|
|
Text{ |
|
|
|
Text{ |
|
|
@ -198,7 +192,7 @@ pub struct FileInfo { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
impl FileInfo { |
|
|
|
impl FileInfo { |
|
|
|
pub fn empty() -> FileInfo { |
|
|
|
fn empty() -> FileInfo { |
|
|
|
return FileInfo{ |
|
|
|
return FileInfo{ |
|
|
|
file_id: 0, |
|
|
|
file_id: 0, |
|
|
|
filename: String::new(), |
|
|
|
filename: String::new(), |
|
|
@ -273,7 +267,7 @@ impl FileInfo { |
|
|
|
return Err(Error::new("it is not a fileinfo packet")); |
|
|
|
return Err(Error::new("it is not a fileinfo packet")); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if raw_packet.contents.len() < 16+16+16+16+1+1 { |
|
|
|
if raw_packet.contents.len() < 16+16+16+16 { |
|
|
|
return Err( |
|
|
|
return Err( |
|
|
|
Error::new(format!("{} bytes is too small for a fileinfo packet to be valid", raw_packet.contents.len()).as_str() |
|
|
|
Error::new(format!("{} bytes is too small for a fileinfo packet to be valid", raw_packet.contents.len()).as_str() |
|
|
|
)); |
|
|
|
)); |
|
|
@ -284,17 +278,17 @@ impl FileInfo { |
|
|
|
|
|
|
|
|
|
|
|
// get filename
|
|
|
|
// get filename
|
|
|
|
let filename_length: u128 = read_u128_slice_be(&raw_packet.contents[16..32]); |
|
|
|
let filename_length: u128 = read_u128_slice_be(&raw_packet.contents[16..32]); |
|
|
|
let filename = read_utf8_string_slice(&raw_packet.contents[32..(filename_length+32) as usize]); |
|
|
|
let filename = read_utf8_string_slice(&raw_packet.contents[32..32+filename_length as usize]); |
|
|
|
|
|
|
|
|
|
|
|
// filesize
|
|
|
|
// filesize
|
|
|
|
let filesize = read_u128_slice_be(&raw_packet.contents[(filename_length+32) as usize..(filename_length+32+16) as usize]); |
|
|
|
let filesize = read_u128_slice_be(&raw_packet.contents[32+filename_length as usize..32+16+filename_length as usize]); |
|
|
|
|
|
|
|
|
|
|
|
// relative path
|
|
|
|
// relative path
|
|
|
|
let rel_path_length: u128 = read_u128_slice_be( |
|
|
|
let rel_path_length: u128 = read_u128_slice_be( |
|
|
|
&raw_packet.contents[(filename_length+32+16) as usize..(filename_length+32+16+16)as usize] |
|
|
|
&raw_packet.contents[32+16+filename_length as usize..32+16+16+filename_length as usize] |
|
|
|
); |
|
|
|
); |
|
|
|
let relative_path = read_utf8_string_slice( |
|
|
|
let relative_path = read_utf8_string_slice( |
|
|
|
&raw_packet.contents[(filename_length+32+16+16) as usize..(filename_length+32+16+16+rel_path_length) as usize] |
|
|
|
&raw_packet.contents[32+16+16+filename_length as usize..(filename_length+32+16+16+rel_path_length) as usize] |
|
|
|
); |
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
return Ok( |
|
|
|
return Ok( |
|
|
@ -316,14 +310,6 @@ pub struct FileData { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
impl FileData { |
|
|
|
impl FileData { |
|
|
|
pub fn empty() -> FileData { |
|
|
|
|
|
|
|
return FileData { |
|
|
|
|
|
|
|
file_id: 0, |
|
|
|
|
|
|
|
chunk_no: 0, |
|
|
|
|
|
|
|
chunk: Vec::new(), |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn as_raw(&self) -> Packet { |
|
|
|
pub fn as_raw(&self) -> Packet { |
|
|
|
let mut raw_packet: Packet = Packet{ |
|
|
|
let mut raw_packet: Packet = Packet{ |
|
|
|
header: FILEDATA_PACKET_ID, |
|
|
|
header: FILEDATA_PACKET_ID, |
|
|
@ -348,7 +334,7 @@ impl FileData { |
|
|
|
return Err(Error::new("it is not a filedata packet")); |
|
|
|
return Err(Error::new("it is not a filedata packet")); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if raw_packet.contents.len() < 16+16+16+1 { |
|
|
|
if raw_packet.contents.len() < 16+16+16 { |
|
|
|
return Err( |
|
|
|
return Err( |
|
|
|
Error::new(format!("{} bytes is too small for a fileinfo packet to be valid", raw_packet.contents.len()).as_str() |
|
|
|
Error::new(format!("{} bytes is too small for a fileinfo packet to be valid", raw_packet.contents.len()).as_str() |
|
|
|
)); |
|
|
|
)); |
|
|
@ -412,14 +398,6 @@ pub struct Handshake { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
impl Handshake { |
|
|
|
impl Handshake { |
|
|
|
pub fn empty() -> Handshake { |
|
|
|
|
|
|
|
return Handshake{ |
|
|
|
|
|
|
|
protocol_version: PROTOCOL_LATEST_VERSION, |
|
|
|
|
|
|
|
encryption_type: ENCRYPTION_NO_ENCRYPTION, |
|
|
|
|
|
|
|
encryption_key: crypt::keys::Key8bit::new(0).as_bytes(), |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn as_raw(&self) -> Packet { |
|
|
|
pub fn as_raw(&self) -> Packet { |
|
|
|
let mut raw_packet: Packet = Packet{ |
|
|
|
let mut raw_packet: Packet = Packet{ |
|
|
|
header: HANDSHAKE_PACKET_ID, |
|
|
|
header: HANDSHAKE_PACKET_ID, |
|
|
@ -440,7 +418,11 @@ impl Handshake { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub fn from_raw(raw_packet: &Packet) -> Result<Handshake, Error> { |
|
|
|
pub fn from_raw(raw_packet: &Packet) -> Result<Handshake, Error> { |
|
|
|
if raw_packet.contents.len() < 1+1+1+16+1 { |
|
|
|
if raw_packet.header != HANDSHAKE_PACKET_ID { |
|
|
|
|
|
|
|
return Err(Error::new("it is not a handshake packet")); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if raw_packet.contents.len() < 1+1+16 { |
|
|
|
return Err( |
|
|
|
return Err( |
|
|
|
Error::new(format!("{} bytes is too small for a handshake packet to be valid", raw_packet.contents.len()).as_str()) |
|
|
|
Error::new(format!("{} bytes is too small for a handshake packet to be valid", raw_packet.contents.len()).as_str()) |
|
|
|
); |
|
|
|
); |
|
|
@ -453,14 +435,16 @@ impl Handshake { |
|
|
|
let encryption_type = raw_packet.contents[1].to_be(); |
|
|
|
let encryption_type = raw_packet.contents[1].to_be(); |
|
|
|
|
|
|
|
|
|
|
|
// key
|
|
|
|
// key
|
|
|
|
let key_len: u128 = read_u128_slice_be(&raw_packet.contents[1..17]); |
|
|
|
let key_len: u128 = read_u128_slice_be(&raw_packet.contents[2..18]); |
|
|
|
let mut encryption_key: Vec<u8> = Vec::with_capacity(key_len as usize); |
|
|
|
let mut encryption_key: Vec<u8> = vec!(0; key_len as usize); |
|
|
|
for i in 17..(17+key_len) as usize { |
|
|
|
if key_len == 0 { |
|
|
|
encryption_key[i-17] = raw_packet.contents[i].to_be(); |
|
|
|
encryption_key = Vec::new(); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
for i in 18..(18+key_len) as usize { |
|
|
|
|
|
|
|
encryption_key[i-18] = raw_packet.contents[i].to_be(); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
println!("from bytes function handshake bytes: {:?}", raw_packet.contents); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return Ok( |
|
|
|
return Ok( |
|
|
|
Handshake{ |
|
|
|
Handshake{ |
|
|
|
protocol_version: protocol_version, |
|
|
|
protocol_version: protocol_version, |
|
|
|