Horrible and in need of refactoring but it can send and request keys, can't respond or send messages tho :/
This commit is contained in:
commit
cd5e0b6b9e
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
/target
|
||||
secret.asc
|
||||
public.asc
|
1381
Cargo.lock
generated
Normal file
1381
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
12
Cargo.toml
Normal file
12
Cargo.toml
Normal file
|
@ -0,0 +1,12 @@
|
|||
[package]
|
||||
name = "irc-e2e"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
base64 = "0.21.4"
|
||||
ircparser = "0.2.1"
|
||||
openssl = "0.10"
|
||||
pgp = "0.10.2"
|
37
src/encryption.rs
Normal file
37
src/encryption.rs
Normal file
|
@ -0,0 +1,37 @@
|
|||
use ircparser;
|
||||
use pgp::{composed::signed_key::*, Deserializable};
|
||||
use std::sync::mpsc;
|
||||
|
||||
fn initialize_connection(
|
||||
tx: mpsc::Sender<String>,
|
||||
rx: mpsc::Receiver<String>,
|
||||
person: &str,
|
||||
key_string: &str,
|
||||
) -> Result<SignedPublicKey, pgp::errors::Error> {
|
||||
tx.send(format!("PRIVMSG {person} INITIALIZE"))
|
||||
.expect("Closed");
|
||||
|
||||
for line in key_string.split('\n') {
|
||||
tx.send(format!("PRIVMSG {person} {line}")).unwrap();
|
||||
}
|
||||
|
||||
let mut key_lines: Vec<String> = vec![];
|
||||
let mut line: String = String::new();
|
||||
|
||||
while line != "END" {
|
||||
key_lines.push(line);
|
||||
line = match ircparser::parse(&rx.recv().expect("Channel Closed")) {
|
||||
Ok(parsed) => {
|
||||
let line = &parsed[0];
|
||||
|
||||
line.params[1].clone()
|
||||
}
|
||||
Err(e) => {
|
||||
println!("WARN: got invalid line {e}");
|
||||
String::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(SignedPublicKey::from_string(&key_lines.join("\n"))?.0)
|
||||
}
|
43
src/listener_server.rs
Normal file
43
src/listener_server.rs
Normal file
|
@ -0,0 +1,43 @@
|
|||
use std::io::{self, Read, Write};
|
||||
use std::net::TcpListener;
|
||||
use std::sync::mpsc;
|
||||
use std::time::Duration;
|
||||
|
||||
pub fn listen_to_client(tx: mpsc::Sender<String>, rx: mpsc::Receiver<String>) {
|
||||
let listener = TcpListener::bind("127.0.0.1:6666").unwrap();
|
||||
let mut stream = listener.accept().unwrap().0;
|
||||
|
||||
stream
|
||||
.set_read_timeout(Some(Duration::from_millis(10)))
|
||||
.expect("Couldn't set timeout!!");
|
||||
|
||||
loop {
|
||||
let mut buffer: Vec<u8> = Vec::new();
|
||||
let mut buf: [u8; 1] = [0];
|
||||
let newline: u8 = b'\n';
|
||||
|
||||
while buf[0] != newline {
|
||||
match stream.read(&mut buf) {
|
||||
Ok(_length) => {
|
||||
buffer.push(buf[0]);
|
||||
}
|
||||
Err(_error) => match _error.kind() {
|
||||
io::ErrorKind::TimedOut => {}
|
||||
_ => {}
|
||||
},
|
||||
}
|
||||
|
||||
match rx.try_recv() {
|
||||
Ok(value) => {
|
||||
match stream.write_all(value.as_bytes()) {
|
||||
Ok(_) => {}
|
||||
Err(_e) => println!("Couldn't send {value}"),
|
||||
};
|
||||
}
|
||||
Err(_e) => {}
|
||||
}
|
||||
}
|
||||
|
||||
let _ = tx.send(String::from_utf8_lossy(&buffer).to_string());
|
||||
}
|
||||
}
|
135
src/main.rs
Normal file
135
src/main.rs
Normal file
|
@ -0,0 +1,135 @@
|
|||
use base64::{engine::general_purpose, Engine as _};
|
||||
use ircparser;
|
||||
use std::collections::HashMap;
|
||||
use std::net::{Shutdown, TcpStream};
|
||||
use std::sync::mpsc;
|
||||
use std::thread;
|
||||
use std::{env, fs};
|
||||
|
||||
mod encryption;
|
||||
mod listener_server;
|
||||
mod message_stream;
|
||||
mod writer_client;
|
||||
|
||||
macro_rules! try_recv {
|
||||
($rx:ident) => {
|
||||
match $rx.try_recv() {
|
||||
Ok(recieved) => recieved,
|
||||
Err(_e) => match _e {
|
||||
mpsc::TryRecvError::Empty => String::new(),
|
||||
mpsc::TryRecvError::Disconnected => {
|
||||
panic!("Error!")
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let args = env::args();
|
||||
|
||||
let server = args.collect::<Vec<String>>()[1].clone();
|
||||
|
||||
let stream = TcpStream::connect(format!("{server}:6697"))?;
|
||||
|
||||
let public_key = general_purpose::STANDARD.encode(fs::read("public.asc")?);
|
||||
let secret_key = general_purpose::STANDARD.encode(fs::read("secret.asc")?);
|
||||
|
||||
let reader_stream = match stream.try_clone() {
|
||||
Ok(stream) => stream,
|
||||
Err(_error) => {
|
||||
let _ = stream.shutdown(Shutdown::Both);
|
||||
panic!("Failed to create the reader stream")
|
||||
}
|
||||
};
|
||||
|
||||
let writer_stream = match stream.try_clone() {
|
||||
Ok(stream) => stream,
|
||||
Err(_error) => {
|
||||
let _ = stream.shutdown(Shutdown::Both);
|
||||
let _ = reader_stream.shutdown(Shutdown::Both);
|
||||
panic!("Failed to create the writer stream")
|
||||
}
|
||||
};
|
||||
|
||||
let (listener_channel_send_tx, listener_channel_rx) = mpsc::channel();
|
||||
let (listener_channel_tx, listener_channel_recv_rx) = mpsc::channel();
|
||||
|
||||
let (writer_channel_tx, writer_channel_send_rx) = mpsc::channel();
|
||||
let (writer_channel_recv_tx, writer_channel_rx) = mpsc::channel();
|
||||
|
||||
thread::spawn(|| {
|
||||
listener_server::listen_to_client(listener_channel_send_tx, listener_channel_recv_rx)
|
||||
});
|
||||
thread::spawn(|| {
|
||||
writer_client::write_to_server(
|
||||
writer_stream,
|
||||
server,
|
||||
writer_channel_send_rx,
|
||||
writer_channel_recv_tx,
|
||||
)
|
||||
});
|
||||
|
||||
let mut negotiated_users: HashMap<String, bool> = HashMap::new();
|
||||
|
||||
loop {
|
||||
let recieved = try_recv!(listener_channel_rx);
|
||||
|
||||
if recieved != "" {
|
||||
let command = &ircparser::parse(&recieved).expect("Got an invalid IRC instruction")[0];
|
||||
|
||||
if command.command == "PRIVMSG" && !command.params[0].starts_with("#") {
|
||||
if !negotiated_users.get(&command.params[0]).is_none() {
|
||||
dbg!(recieved);
|
||||
let reciever = &command.params[0];
|
||||
|
||||
writer_channel_tx.send(format!("PRIVMSG {reciever} START_KEY\n"))?;
|
||||
for line in public_key
|
||||
.chars()
|
||||
.collect::<Vec<char>>()
|
||||
.chunks(50)
|
||||
.map(|c| c.iter().collect::<String>())
|
||||
.collect::<Vec<String>>()
|
||||
{
|
||||
dbg!(&line);
|
||||
writer_channel_tx
|
||||
.send(format!("PRIVMSG {reciever} {}", line.clone() + "\n"))?;
|
||||
}
|
||||
writer_channel_tx.send(format!("PRIVMSG {reciever} END_KEY\n"))?;
|
||||
|
||||
let mut foreign_key: Vec<String> = Vec::new();
|
||||
while !foreign_key.contains(&"END_KEY".to_string()) {
|
||||
dbg!("Trying to recv");
|
||||
let recieved_raw = writer_channel_rx.recv()?;
|
||||
dbg!(&recieved_raw);
|
||||
|
||||
let recieved = &ircparser::parse(&recieved_raw).unwrap()[0];
|
||||
let begin_source_reciever = format!(":{reciever}!");
|
||||
if recieved.command != "PRIVMSG"
|
||||
|| !recieved
|
||||
.source
|
||||
.clone()
|
||||
.unwrap_or("".to_string())
|
||||
.starts_with(&begin_source_reciever)
|
||||
{
|
||||
writer_channel_tx.send(recieved_raw)?;
|
||||
continue;
|
||||
}
|
||||
|
||||
foreign_key.push(recieved.params[1].clone());
|
||||
}
|
||||
foreign_key.pop();
|
||||
}
|
||||
} else {
|
||||
dbg!(&recieved);
|
||||
writer_channel_tx.send(recieved)?;
|
||||
}
|
||||
}
|
||||
|
||||
let recieved = try_recv!(writer_channel_rx);
|
||||
if recieved != "" {
|
||||
dbg!(&recieved);
|
||||
listener_channel_tx.send(recieved)?;
|
||||
}
|
||||
}
|
||||
}
|
46
src/message_stream.rs
Normal file
46
src/message_stream.rs
Normal file
|
@ -0,0 +1,46 @@
|
|||
use ircparser;
|
||||
use std::io::{Read, Write};
|
||||
|
||||
struct MessageStream<'a, StreamType: Write + Read + ?Sized> {
|
||||
stream: Box<StreamType>,
|
||||
reciver: &'a str,
|
||||
sender: &'a str,
|
||||
}
|
||||
|
||||
trait Stream: Write + Read {}
|
||||
|
||||
impl Write for MessageStream<'_, dyn Stream> {
|
||||
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
||||
let to_send = "PRIVMSG".to_owned() + self.sender + &String::from_utf8_lossy(buf) + "\n";
|
||||
self.stream.write(to_send.as_bytes())?;
|
||||
Ok(buf.len())
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> std::io::Result<()> {
|
||||
self.stream.flush()
|
||||
}
|
||||
}
|
||||
|
||||
impl Read for MessageStream<'_, dyn Stream> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
||||
let mut readed = String::new();
|
||||
let _ = self.stream.read_to_string(&mut readed);
|
||||
let commands = ircparser::parse(&readed).unwrap();
|
||||
|
||||
let mut messages: Vec<String> = vec![];
|
||||
|
||||
for command in commands {
|
||||
let command_string = &command.command;
|
||||
let command_reciver = &command.params[0];
|
||||
let command_sender = command.source.unwrap_or("".to_string());
|
||||
if command_string == "PRIVMSG"
|
||||
&& command_reciver == self.sender
|
||||
&& command_sender.starts_with(&format!(":{}", self.reciver))
|
||||
{
|
||||
messages.push(command.params[1].clone());
|
||||
}
|
||||
}
|
||||
|
||||
Ok(messages.join("\n").as_bytes().read(buf)?)
|
||||
}
|
||||
}
|
60
src/writer_client.rs
Normal file
60
src/writer_client.rs
Normal file
|
@ -0,0 +1,60 @@
|
|||
use openssl::ssl::{SslConnector, SslMethod};
|
||||
use std::io::{ErrorKind, Write};
|
||||
use std::net::TcpStream;
|
||||
use std::sync::mpsc;
|
||||
use std::time::Duration;
|
||||
|
||||
pub fn write_to_server(
|
||||
tcp_stream: TcpStream,
|
||||
server: String,
|
||||
rx: mpsc::Receiver<String>,
|
||||
tx: mpsc::Sender<String>,
|
||||
) {
|
||||
let connector = SslConnector::builder(SslMethod::tls()).unwrap().build();
|
||||
let mut stream = connector
|
||||
.connect(&server, &tcp_stream)
|
||||
.expect("Couldn't start TLS");
|
||||
|
||||
tcp_stream
|
||||
.set_read_timeout(Some(Duration::from_millis(10)))
|
||||
.expect("Couldn't set timeout!!");
|
||||
|
||||
loop {
|
||||
let mut buffer: Vec<u8> = Vec::new();
|
||||
let mut buf: [u8; 1] = [0];
|
||||
let newline: u8 = b'\n';
|
||||
|
||||
while buf[0] != newline {
|
||||
match stream.ssl_read(&mut buf) {
|
||||
Ok(_length) => {
|
||||
buffer.push(buf[0]);
|
||||
}
|
||||
Err(_error) => match _error.io_error() {
|
||||
None => {
|
||||
panic!("TLS Error")
|
||||
}
|
||||
Some(error) => match error.kind() {
|
||||
ErrorKind::TimedOut => {}
|
||||
ErrorKind::WouldBlock => {}
|
||||
_ => {
|
||||
dbg!(error.kind());
|
||||
println!("Couldn't read the stream");
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
match rx.try_recv() {
|
||||
Ok(value) => {
|
||||
match stream.write_all(value.as_bytes()) {
|
||||
Ok(_) => {}
|
||||
Err(_e) => println!("Couldn't send {value}"),
|
||||
};
|
||||
}
|
||||
Err(_e) => {}
|
||||
}
|
||||
}
|
||||
|
||||
let _ = tx.send(String::from_utf8_lossy(&buffer).to_string());
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue