~yujiri/sufec-server

e1d808743ffa74353b0f13c364c6c4b194393df7 — Yujiri 11 months ago 4b7291e
reduce logging noise and limit message size
1 files changed, 29 insertions(+), 27 deletions(-)

M src/main.rs
M src/main.rs => src/main.rs +29 -27
@@ 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))
}