@@ 10,6 10,7 @@ use std::time::{Duration, UNIX_EPOCH};
use std::os::unix::ffi::OsStringExt;
const PORT: u16 = 49002;
+pub const MAX_FILE_SIZE: usize = 1024*1024*5; // 5 MiB
type DeviceId = [u8; 4];
fn base64_encode<T: AsRef<[u8]>>(input: T) -> String {
@@ 106,25 107,21 @@ fn main() -> anyhow::Result<()> {
let listener = TcpListener::bind(format!("{}:{}", addr, PORT)).context("failed to bind socket")?;
for client in listener.incoming() {
let seckey = seckey.clone();
- thread::spawn(move || {
- if let Err(e) = handle_client(client.unwrap(), pubkey, seckey) {
- eprintln!("{:?}", e);
- }
- });
+ thread::spawn(move || handle_client(client.unwrap(), pubkey, seckey));
}
Ok(())
}
fn handle_client(mut stream: TcpStream, pubkey: PublicKey, seckey: SecretKey) -> anyhow::Result<()> {
// Send the server's public key.
- stream.write_all(&pubkey.0).context("failed to send server's public key")?;
+ stream.write_all(&pubkey.0)?;
// Read the intent indicator byte.
let mut b = [0];
- stream.read_exact(&mut b).context("failed to read intent indicator byte")?;
+ stream.read_exact(&mut b)?;
match b[0] {
- 0 => handle_receiver(stream, &pubkey, &seckey).context("error handling receiver"),
- 1 => handle_sender(stream, &pubkey, &seckey).context("error handling sender"),
- 2 => handle_remover(stream, &pubkey, &seckey).context("error handling remover"),
+ 0 => handle_receiver(stream, &pubkey, &seckey),
+ 1 => handle_sender(stream, &pubkey, &seckey),
+ 2 => handle_remover(stream, &pubkey, &seckey),
_ => Ok(()),
}
}
@@ 132,37 129,41 @@ fn handle_client(mut stream: TcpStream, pubkey: PublicKey, seckey: SecretKey) ->
fn handle_sender(mut stream: TcpStream, pubkey: &PublicKey, seckey: &SecretKey) -> anyhow::Result<()> {
// Read session key.
let mut session_key_buf = [0; PRECOMPUTEDKEYBYTES + SEALBYTES];
- stream.read_exact(&mut session_key_buf).context("failed to read session key")?;
+ stream.read_exact(&mut session_key_buf)?;
let session_key_raw = sealedbox::open(&session_key_buf, pubkey, seckey)
.map_err(|_| anyhow!("failed to decrypt session key"))?;
- let session_key = PrecomputedKey::from_slice(&session_key_raw).ok_or_else(|| anyhow!("invalid session key"))?;
+ let session_key = PrecomputedKey::from_slice(&session_key_raw).unwrap();
let mut stream = EncryptedStream{stream, key: session_key, nonce: Nonce([0; NONCEBYTES])};
// See who they want to message.
- let recipient_buf = stream.receive(PUBLICKEYBYTES).context("failed to read recipient ID")?;
+ let recipient_buf = stream.receive(PUBLICKEYBYTES)?;
let recipient = PublicKey(recipient_buf.try_into().unwrap());
// Return that user's ephemeral keys.
let keys = get_eph_keys(recipient).context("failed to get recipient's keys")?;
let keys_buf = keys.iter().map(|(_device, key)| key.0).collect::<Vec<[u8; 32]>>().concat();
- stream.send(&[keys.len() as u8]).context("failed to send number of keys")?;
- stream.send(&keys_buf).context("failed to send recipient's keys")?;
+ stream.send(&[keys.len() as u8])?;
+ stream.send(&keys_buf)?;
// Read message length.
- let length_buf = stream.receive(4).context("failed to read message length")?;
+ let length_buf = stream.receive(4)?;
let length = u32::from_be_bytes(length_buf.try_into().unwrap()) as usize;
+ // 84283 is the max amount by which this transmission can be bigger than the max file size.
+ // Subtract the MAC bytes since those will be added in EncryptedStream::receive.
+ if length > MAX_FILE_SIZE + 84283 - MACBYTES { return Ok(()) }
// Receive a copy of the message for each key.
for key in keys {
// Read message.
- let message = stream.receive(length).context("failed to read message")?;
+ let message = stream.receive(length)?;
// Store message.
- save_message(recipient, key.0, message).context("failed to store message")?;
+ save_message(recipient, key.0, message)?;
}
- stream.send(&[0]).context("failed to send receipt")
+ stream.send(&[0])?;
+ Ok(())
}
fn handle_receiver(mut stream: TcpStream, pubkey: &PublicKey, seckey: &SecretKey) -> anyhow::Result<()> {
let (user_id, session_key) = handshake(&mut stream, pubkey, seckey)?;
let mut stream = EncryptedStream{stream, key: session_key, nonce: Nonce([0; NONCEBYTES])};
// Read their device ID and new receiving key.
- let buf = stream.receive(4+PUBLICKEYBYTES).context("failed to read device ID and new receiving key")?;
+ let buf = stream.receive(4+PUBLICKEYBYTES)?;
let device_id: [u8; 4] = buf[0..4].try_into().unwrap();
let key = PublicKey(buf[4..].try_into().unwrap());
update_eph_key(user_id, device_id, key).context("failed to update ephemeral key")?;
@@ 170,9 171,9 @@ fn handle_receiver(mut stream: TcpStream, pubkey: &PublicKey, seckey: &SecretKey
loop {
thread::sleep(Duration::from_millis(10));
if let Some((timestamp, msg)) = get_message(user_id, device_id).context("failed to get stored messages")? {
- stream.send((msg.len() as u32).to_be_bytes()).context("failed to send message length")?;
- stream.send(msg).context("failed to send message")?;
- _ = stream.receive(1).context("failed to read receipt")?;
+ stream.send((msg.len() as u32).to_be_bytes())?;
+ stream.send(msg)?;
+ _ = stream.receive(1)?;
remove_message(user_id, device_id, timestamp).context("failed to remove downloaded message")?;
}
}
@@ 182,20 183,21 @@ fn handle_remover(mut stream: TcpStream, pubkey: &PublicKey, seckey: &SecretKey)
let (user_id, session_key) = handshake(&mut stream, pubkey, seckey)?;
let mut stream = EncryptedStream{stream, key: session_key, nonce: Nonce([0; NONCEBYTES])};
// Read the device ID to revoke.
- let device_id = stream.receive(4).context("failed to read device ID")?;
+ let device_id = stream.receive(4)?;
let path = format!("{}/{}", base64_encode(user_id.0), base64_encode(device_id));
fs::remove_dir_all(format!("inboxes/{}", path)).context("failed to remove inbox")?;
fs::remove_file(format!("keys/{}", path)).context("failed to remove key")?;
- stream.send(&[0]).context("failed to send receipt")
+ stream.send(&[0])?;
+ Ok(())
}
fn handshake(stream: &mut TcpStream, pubkey: &PublicKey, seckey: &SecretKey) -> anyhow::Result<(PublicKey, PrecomputedKey)> {
// We have already sent the server's public key.
// Read the client's ID.
let mut buf = [0; PUBLICKEYBYTES + SEALBYTES];
- stream.read_exact(&mut buf).context("failed to read user's ID")?;
+ stream.read_exact(&mut buf)?;
let user_id_buf = sealedbox::open(&buf, pubkey, seckey).map_err(|_| anyhow!("failed to decrypt user's ID"))?;
- let user_id = PublicKey::from_slice(&user_id_buf).context("user's ID is invalid")?;
+ let user_id = PublicKey::from_slice(&user_id_buf).unwrap();
let session_key = precompute(&user_id, seckey);
Ok((user_id, session_key))
}