Compare commits
8 commits
Author | SHA1 | Date | |
---|---|---|---|
vanten-s | e4fd3224cf | ||
vanten-s | 5c24ae5f96 | ||
vanten-s | c895210cea | ||
vanten-s | 4aed403c97 | ||
vanten-s | 247f35994b | ||
vanten-s | 6eeeb4a2e8 | ||
vanten-s | 2783cc9ca8 | ||
vanten-s | bdb14a5b6d |
|
@ -1,7 +1,11 @@
|
|||
[package]
|
||||
name = "e2e-irc"
|
||||
version = "2.0.0"
|
||||
version = "3.0.0"
|
||||
edition = "2021"
|
||||
license = "GPL-3.0"
|
||||
keywords = ["irc", "encryption"]
|
||||
description = "An IRC bouncer that can send encrypted messages"
|
||||
repository = "https://forgejo.vanten-s.com/vanten-s/e2e-irc/"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
@ -10,7 +14,7 @@ argparse = "0.2.2"
|
|||
base64 = "0.21.4"
|
||||
dirs = "5.0.1"
|
||||
eyre = "0.6.8"
|
||||
ircparser = "0.2.1"
|
||||
ircparser-vanten = "0.2.1"
|
||||
openssl = "0.10"
|
||||
pgp = "0.10.2"
|
||||
rand = "0.8.5"
|
||||
|
|
|
@ -26,7 +26,7 @@ Optional arguments:
|
|||
|
||||
# Install
|
||||
```bash
|
||||
cargo install --git https://forgejo.vanten-s.com/vanten-s/e2e-irc.git
|
||||
cargo install e2e-irc
|
||||
```
|
||||
|
||||
# Run
|
||||
|
|
|
@ -1,10 +1,41 @@
|
|||
use crate::helpers::bytes_to_privmsg_base64;
|
||||
use crate::{encryption, helpers};
|
||||
use crate::{encryption, helpers, State};
|
||||
use eyre::Result;
|
||||
use pgp::{Deserializable, SignedPublicKey};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::mpsc::{Receiver, Sender};
|
||||
|
||||
#[derive(Debug)]
|
||||
struct InvalidCommand;
|
||||
|
||||
impl std::fmt::Display for InvalidCommand {
|
||||
fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for InvalidCommand {}
|
||||
|
||||
fn parse_bouncer_command(message: String, state: &mut State) -> Result<()> {
|
||||
macro_rules! unwrap_option {
|
||||
($t:expr) => {
|
||||
match $t {
|
||||
Some(val) => val,
|
||||
None => return Err(InvalidCommand.into()),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let mut splitted = message.split(' ');
|
||||
match unwrap_option!(splitted.next()) {
|
||||
"ALLOW_UNENCRYPTED" => state
|
||||
.nicks_without_encryption
|
||||
.push(unwrap_option!(splitted.next()).to_string().to_lowercase()),
|
||||
_ => return Err(InvalidCommand.into()),
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn handle_message_from_client(
|
||||
recieved: &str,
|
||||
public_key: &Vec<u8>,
|
||||
|
@ -14,10 +45,34 @@ pub fn handle_message_from_client(
|
|||
writer_channel_rx: &Receiver<String>,
|
||||
listener_channel_tx: &Sender<String>,
|
||||
_listener_channel_rx: &Receiver<String>,
|
||||
state: &mut State,
|
||||
) -> Result<()> {
|
||||
let command = &ircparser::parse(recieved).expect("Got an invalid IRC instruction")[0];
|
||||
let mut recieved = recieved.to_string();
|
||||
|
||||
if recieved.split(' ').count() == 1 {
|
||||
recieved += " ";
|
||||
}
|
||||
|
||||
let parsed = ircparser::parse(&recieved);
|
||||
let command = match parsed {
|
||||
Ok(val) => val[0].clone(),
|
||||
Err(_) => {
|
||||
writer_channel_tx.send(recieved)?;
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
|
||||
if command.command == "PRIVMSG" && !command.params[0].starts_with('#') {
|
||||
if command.params[0] == "BOUNCER" {
|
||||
return parse_bouncer_command(command.params[1].clone(), state);
|
||||
}
|
||||
if state
|
||||
.nicks_without_encryption
|
||||
.contains(&command.params[0].to_lowercase())
|
||||
{
|
||||
writer_channel_tx.send(recieved)?;
|
||||
return Ok(());
|
||||
}
|
||||
let other = &command.params[0];
|
||||
|
||||
if !keys.contains_key(other) {
|
||||
|
|
|
@ -3,7 +3,7 @@ use eyre::Result;
|
|||
use std::sync::mpsc::{self, Receiver, Sender};
|
||||
|
||||
#[derive(Debug)]
|
||||
struct IrcParseError;
|
||||
pub struct IrcParseError;
|
||||
|
||||
impl std::fmt::Display for IrcParseError {
|
||||
fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
|
@ -35,6 +35,22 @@ macro_rules! unwrap_or_return_option {
|
|||
};
|
||||
}
|
||||
|
||||
pub struct State {
|
||||
pub nicks_without_encryption: Vec<String>,
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub fn new() -> Self {
|
||||
State {
|
||||
nicks_without_encryption: vec![
|
||||
"nickserv".to_string(),
|
||||
"chanserv".to_string(),
|
||||
"hostserv".to_string(),
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn forward(
|
||||
message: String,
|
||||
stream: &Sender<String>,
|
||||
|
|
10
src/main.rs
10
src/main.rs
|
@ -1,6 +1,7 @@
|
|||
use argparse::{ArgumentParser, Store};
|
||||
use dirs::config_local_dir;
|
||||
use eyre::Result;
|
||||
use helpers::State;
|
||||
use pgp::{Deserializable, SignedPublicKey, SignedSecretKey};
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
|
@ -81,7 +82,11 @@ fn main() -> Result<()> {
|
|||
|
||||
let tmp_port = port.clone();
|
||||
thread::spawn(move || {
|
||||
listener_server::listen_to_client(listener_channel_send_tx, listener_channel_recv_rx, tmp_port)
|
||||
listener_server::listen_to_client(
|
||||
listener_channel_send_tx,
|
||||
listener_channel_recv_rx,
|
||||
tmp_port,
|
||||
)
|
||||
});
|
||||
let tmp_port = server_port.clone();
|
||||
let tmp_server = server.clone();
|
||||
|
@ -95,6 +100,7 @@ fn main() -> Result<()> {
|
|||
});
|
||||
|
||||
let mut keys: HashMap<String, SignedPublicKey> = HashMap::new();
|
||||
let mut state = State::new();
|
||||
|
||||
loop {
|
||||
match listener_channel_rx.try_recv() {
|
||||
|
@ -108,6 +114,7 @@ fn main() -> Result<()> {
|
|||
&writer_channel_rx,
|
||||
&listener_channel_tx,
|
||||
&listener_channel_rx,
|
||||
&mut state,
|
||||
);
|
||||
}
|
||||
Err(error) => match error {
|
||||
|
@ -129,6 +136,7 @@ fn main() -> Result<()> {
|
|||
&writer_channel_rx,
|
||||
&listener_channel_tx,
|
||||
&listener_channel_rx,
|
||||
&state,
|
||||
);
|
||||
}
|
||||
Err(error) => match error {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use crate::unwrap_or_return_option;
|
||||
use crate::unwrap_or_return_result;
|
||||
use crate::State;
|
||||
use crate::{encryption, helpers};
|
||||
use eyre::Result;
|
||||
use pgp::{Deserializable, SignedPublicKey, SignedSecretKey};
|
||||
|
@ -25,15 +26,20 @@ pub fn handle_message_from_server(
|
|||
writer_channel_rx: &Receiver<String>,
|
||||
listener_channel_tx: &Sender<String>,
|
||||
_listener_channel_rx: &Receiver<String>,
|
||||
state: &State,
|
||||
) -> Result<()> {
|
||||
let recieved_parsed = &unwrap_or_return_result!(ircparser::parse(recieved))[0];
|
||||
|
||||
let default_reciever = String::new();
|
||||
|
||||
let reciever = match recieved_parsed.params.get(0) {
|
||||
Some(val) => val,
|
||||
None => &default_reciever,
|
||||
};
|
||||
|
||||
if recieved_parsed.command != "PRIVMSG"
|
||||
|| recieved_parsed
|
||||
.params
|
||||
.get(0)
|
||||
.unwrap_or(&String::new())
|
||||
.starts_with('#')
|
||||
|| reciever.starts_with('#')
|
||||
|| state.nicks_without_encryption.contains(reciever)
|
||||
{
|
||||
forward(recieved, listener_channel_tx, server)?;
|
||||
return Ok(());
|
||||
|
|
|
@ -18,7 +18,7 @@ pub fn write_to_server(
|
|||
|
||||
let connector = SslConnector::builder(SslMethod::tls()).unwrap().build();
|
||||
let mut stream = connector
|
||||
.connect(&server, &tcp_stream)
|
||||
.connect(server, &tcp_stream)
|
||||
.expect("Couldn't start TLS");
|
||||
|
||||
stream
|
||||
|
|
Loading…
Reference in a new issue