🚧 wip: working on insecure chat prototype

main
_ 2022-10-16 22:24:15 +00:00
parent 57d6086ea7
commit 2de0c5d6a7
5 changed files with 353 additions and 48 deletions

115
Cargo.lock generated
View File

@ -81,9 +81,9 @@ dependencies = [
[[package]]
name = "autocfg"
version = "1.0.1"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "base64"
@ -272,7 +272,7 @@ version = "3.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a19c6cedffdc8c03a3346d723eb20bd85a13362bb96dc2ac000842c6381ec7bf"
dependencies = [
"nix",
"nix 0.23.1",
"winapi",
]
@ -722,6 +722,10 @@ name = "insecure_chat"
version = "0.1.0"
dependencies = [
"mac_address",
"nix 0.25.0",
"ptth_diceware",
"thiserror",
"tokio",
]
[[package]]
@ -768,9 +772,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.122"
version = "0.2.135"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec647867e2bf0772e28c8bcde4f0d19a9216916e890543b5a03ed8ef27b8f259"
checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"
[[package]]
name = "lock_api"
@ -796,7 +800,7 @@ version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b238e3235c8382b7653c6408ed1b08dd379bdb9fdf990fb0bbae3db2cc0ae963"
dependencies = [
"nix",
"nix 0.23.1",
"winapi",
]
@ -852,25 +856,14 @@ checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
[[package]]
name = "mio"
version = "0.8.2"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9"
checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf"
dependencies = [
"libc",
"log",
"miow",
"ntapi",
"wasi 0.11.0+wasi-snapshot-preview1",
"winapi",
]
[[package]]
name = "miow"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
dependencies = [
"winapi",
"windows-sys 0.36.1",
]
[[package]]
@ -905,12 +898,17 @@ dependencies = [
]
[[package]]
name = "ntapi"
version = "0.3.6"
name = "nix"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44"
checksum = "e322c04a9e3440c327fca7b6c8a63e6890a32fa2ad689db972425f07e0d22abb"
dependencies = [
"winapi",
"autocfg",
"bitflags",
"cfg-if",
"libc",
"memoffset",
"pin-utils",
]
[[package]]
@ -1013,7 +1011,7 @@ dependencies = [
"libc",
"redox_syscall",
"smallvec",
"windows-sys",
"windows-sys 0.34.0",
]
[[package]]
@ -1985,18 +1983,18 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.29"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "602eca064b2d83369e2b2f34b09c70b605402801927c65c11071ac911d299b88"
checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.29"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bad553cc2c78e8de258400763a647e80e6d1b31ee237275d756f6836d204494c"
checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb"
dependencies = [
"proc-macro2",
"quote",
@ -2040,16 +2038,16 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "tokio"
version = "1.17.0"
version = "1.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee"
checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099"
dependencies = [
"autocfg",
"bytes",
"libc",
"memchr",
"mio",
"num_cpus",
"once_cell",
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
@ -2506,11 +2504,24 @@ version = "0.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5acdd78cb4ba54c0045ac14f62d8f94a03d10047904ae2a40afa1e99d8f70825"
dependencies = [
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_msvc",
"windows_aarch64_msvc 0.34.0",
"windows_i686_gnu 0.34.0",
"windows_i686_msvc 0.34.0",
"windows_x86_64_gnu 0.34.0",
"windows_x86_64_msvc 0.34.0",
]
[[package]]
name = "windows-sys"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
dependencies = [
"windows_aarch64_msvc 0.36.1",
"windows_i686_gnu 0.36.1",
"windows_i686_msvc 0.36.1",
"windows_x86_64_gnu 0.36.1",
"windows_x86_64_msvc 0.36.1",
]
[[package]]
@ -2519,30 +2530,60 @@ version = "0.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d"
[[package]]
name = "windows_aarch64_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
[[package]]
name = "windows_i686_gnu"
version = "0.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed"
[[package]]
name = "windows_i686_gnu"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
[[package]]
name = "windows_i686_msvc"
version = "0.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956"
[[package]]
name = "windows_i686_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
[[package]]
name = "windows_x86_64_gnu"
version = "0.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4"
[[package]]
name = "windows_x86_64_gnu"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
[[package]]
name = "windows_x86_64_msvc"
version = "0.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9"
[[package]]
name = "windows_x86_64_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
[[package]]
name = "winreg"
version = "0.10.1"

View File

@ -7,3 +7,7 @@ edition = "2021"
[dependencies]
mac_address = "1.1.4"
nix = "0.25.0"
ptth_diceware = { path = "../ptth_diceware" }
thiserror = "1.0.37"
tokio = { version = "1.21.2", features = ["net", "rt-multi-thread", "fs"] }

View File

@ -0,0 +1,125 @@
// IP address module
// Copied from the `lookaround` project
use std::{
net::Ipv4Addr,
process::Command,
str::FromStr,
};
#[derive (Debug, thiserror::Error)]
pub enum Error {
#[error (transparent)]
Io (#[from] std::io::Error),
#[error (transparent)]
FromUtf8 (#[from] std::string::FromUtf8Error),
#[error ("Self-IP detection is not implemented on Mac OS")]
NotImplementedOnMac,
}
#[cfg(target_os = "linux")]
pub fn get_ips () -> Result <Vec <Ipv4Addr>, Error> {
let output = linux::get_ip_addr_output ()?;
Ok (linux::parse_ip_addr_output (&output))
}
#[cfg(target_os = "macos")]
pub fn get_ips () -> Result <Vec <Ipv4Addr>, Error> {
Err (Error::NotImplementedOnMac)
}
#[cfg(target_os = "windows")]
pub fn get_ips () -> Result <Vec <Ipv4Addr>, Error> {
let output = windows::get_ip_config_output ()?;
Ok (windows::parse_ip_config_output (&output))
}
#[cfg(target_os = "linux")]
pub mod linux {
use super::*;
pub fn get_ip_addr_output () -> Result <String, Error> {
let output = Command::new ("ip")
.arg ("addr")
.output ()?;
let output = output.stdout.as_slice ();
let output = String::from_utf8 (output.to_vec ())?;
Ok (output)
}
pub fn parse_ip_addr_output (output: &str) -> Vec <Ipv4Addr> {
// I wrote this in FP style because I was bored.
output.lines ()
.map (|l| l.trim_start ())
.filter_map (|l| l.strip_prefix ("inet "))
.filter_map (|l| l.find ('/').map (|x| &l [0..x]))
.filter_map (|l| Ipv4Addr::from_str (l).ok ())
.filter (|a| ! a.is_loopback ())
.collect ()
}
}
#[cfg(target_os = "windows")]
pub mod windows {
use super::*;
pub fn get_ip_config_output () -> Result <String, Error> {
let output = Command::new ("ipconfig")
.output ()?;
let output = output.stdout.as_slice ();
let output = String::from_utf8 (output.to_vec ())?;
Ok (output)
}
pub fn parse_ip_config_output (output: &str) -> Vec <Ipv4Addr> {
let mut addrs = vec! [];
for line in output.lines () {
let line = line.trim_start ();
// Maybe only works on English locales?
if ! line.starts_with ("IPv4 Address") {
continue;
}
let colon_pos = match line.find (':') {
None => continue,
Some (x) => x,
};
let line = &line [colon_pos + 2..];
let addr = match Ipv4Addr::from_str (line) {
Err (_) => continue,
Ok (x) => x,
};
addrs.push (addr);
}
addrs
}
#[cfg (test)]
mod test {
use super::*;
#[test]
fn test () {
for (input, expected) in [
(
r"
IPv4 Address . . .. . . . : 192.168.1.1
",
vec! [
Ipv4Addr::new (192, 168, 1, 1),
]
),
] {
let actual = parse_ip_config_output (input);
assert_eq! (actual, expected);
}
}
}
}

View File

@ -1,18 +1,150 @@
use std::{
net::{
IpAddr,
SocketAddr,
Ipv4Addr,
SocketAddrV4,
UdpSocket,
},
};
fn main () {
mod ip;
fn main () -> Result <(), Error>
{
let mut args = std::env::args ();
let mut bail_unknown = true;
// let mut name =
let mut last_unknown = None;
let mut name = ptth_diceware::passphrase ("_", 3);
let mut subcommand_count = 0;
let mut subcommand = None;
for arg in args.next () {
args.next ();
while let Some (arg) = args.next () {
if arg == "--ignore-unknown" {
bail_unknown = false;
}
if arg == "--name" {
name = args.next ().unwrap ().to_string ();
}
else if arg == "sender" {
subcommand = Some (Subcommand::Sender);
subcommand_count += 1;
}
else if arg == "spy" {
subcommand = Some (Subcommand::Spy);
subcommand_count += 1;
}
else {
last_unknown = Some (arg);
}
}
unimplemented!();
if bail_unknown {
if let Some (last_unknown) = last_unknown {
eprintln! ("Unknown argument `{}`", last_unknown);
return Err (Error::Args);
}
}
if subcommand_count >= 2 {
eprintln! ("Detected {} subcommands in arguments", subcommand_count);
return Err (Error::Args)
}
let rt = tokio::runtime::Runtime::new ()?;
let params = Params::default ();
rt.block_on (async {
if let Some (cmd) = subcommand {
return match cmd {
Subcommand::Sender => sender (params).await,
Subcommand::Spy => spy (params),
};
}
println! ("Name is `{}`", name);
Ok::<_, Error> (())
})?;
Ok (())
}
enum Subcommand {
Sender,
Spy,
}
struct Params {
multicast_group: (Ipv4Addr, u16),
}
impl Default for Params {
fn default () -> Self {
let multicast_group = (Ipv4Addr::new (225, 100, 99, 98), 9041);
Self {
multicast_group,
}
}
}
async fn sender (params: Params) -> Result <(), Error>
{
let socket = tokio::net::UdpSocket::bind (SocketAddrV4::new (Ipv4Addr::UNSPECIFIED, 0)).await?;
let (multicast_addr, multicast_port) = params.multicast_group;
socket.join_multicast_v4 (multicast_addr, Ipv4Addr::UNSPECIFIED)?;
eprintln! ("Multicast group is {:?}", params.multicast_group);
eprintln! ("Local addr is {}", socket.local_addr ()?);
socket.send_to (&[], params.multicast_group).await?;
Ok (())
}
fn spy (params: Params) -> Result <(), Error>
{
let (multicast_addr, multicast_port) = params.multicast_group;
let socket = match UdpSocket::bind (SocketAddrV4::new (Ipv4Addr::UNSPECIFIED, multicast_port)) {
Ok (x) => x,
Err (e) => if e.kind () == std::io::ErrorKind::AddrInUse {
eprintln! ("Address in use. You can only run 1 instance of Insecure Chat at a time, even in spy mode.");
return Err (Error::AddrInUse);
}
else {
return Err (e.into ());
}
};
for bind_addr in ip::get_ips ()? {
socket.join_multicast_v4 (&multicast_addr, &bind_addr)?;
// eprintln! ("Joined multicast with {}", bind_addr);
}
eprintln! ("Multicast addr is {}", multicast_addr);
eprintln! ("Local addr is {}", socket.local_addr ()?);
loop {
let mut buf = vec! [0u8; 2048];
eprintln! ("Listening for UDP packets...");
let (bytes_recved, remote_addr) = socket.recv_from (&mut buf)?;
buf.truncate (bytes_recved);
println! ("Received {} bytes from {}", bytes_recved, remote_addr);
}
}
#[derive (Debug, thiserror::Error)]
enum Error {
#[error ("Address in use")]
AddrInUse,
#[error ("CLI args")]
Args,
#[error (transparent)]
Io (#[from] std::io::Error),
#[error (transparent)]
Ip (#[from] ip::Error),
}

View File

@ -1,15 +1,18 @@
use rand::Rng;
pub fn main () {
let passphrase = passphrase (" ", 8);
println! ("{}", passphrase);
}
pub fn passphrase (separator: &str, len: usize) -> String {
let diceware = Diceware::default ();
let random_words: Vec <&str> = (0..8)
let random_words: Vec <&str> = (0..len)
.map (|_| diceware.random_word ())
.collect ();
let passphrase = random_words.join (" ");
println! ("{}", passphrase);
random_words.join (separator)
}
pub struct Diceware {