upload working
All checks were successful
Build Binaries / Build & Test (push) Successful in 36s
Build Binaries / Package Library (push) Successful in 26s
Build Binaries / Package Container (push) Successful in 1m13s

This commit is contained in:
Andy Pack 2024-07-29 17:07:49 +01:00
parent 369c3617bc
commit 6a2c1ec15d
Signed by: sarsoo
GPG Key ID: A55BA3536A5E0ED7
31 changed files with 322 additions and 121 deletions

14
Cargo.lock generated
View File

@ -93,6 +93,12 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
[[package]]
name = "base64"
version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]] [[package]]
name = "base64ct" name = "base64ct"
version = "1.6.0" version = "1.6.0"
@ -251,7 +257,7 @@ dependencies = [
[[package]] [[package]]
name = "dnstp" name = "dnstp"
version = "0.1.0" version = "0.1.1"
dependencies = [ dependencies = [
"clap", "clap",
"dnstplib", "dnstplib",
@ -261,8 +267,9 @@ dependencies = [
[[package]] [[package]]
name = "dnstp-client" name = "dnstp-client"
version = "0.1.0" version = "0.1.1"
dependencies = [ dependencies = [
"base64",
"clap", "clap",
"dnstplib", "dnstplib",
"log", "log",
@ -272,9 +279,10 @@ dependencies = [
[[package]] [[package]]
name = "dnstplib" name = "dnstplib"
version = "0.1.0" version = "0.1.1"
dependencies = [ dependencies = [
"aes-gcm-siv", "aes-gcm-siv",
"base64",
"log", "log",
"p256", "p256",
"rand_core", "rand_core",

View File

@ -5,4 +5,9 @@ members = [
"dnstp", "dnstp",
"dnstp-client", "dnstp-client",
"dnstp-server", "dnstp-server",
] ]
[workspace.package]
version = "0.1.1"
authors = ["sarsoo <andy@sarsoo.xyz>"]
documentation = "https://sarsoo.github.io/dnstp"

View File

@ -1,6 +1,8 @@
[package] [package]
name = "dnstp-client" name = "dnstp-client"
version = "0.1.0" version.workspace = true
authors.workspace = true
documentation.workspace = true
edition = "2021" edition = "2021"
publish = false publish = false
@ -11,4 +13,5 @@ dnstplib = { path = "../dnstp" }
clap = { version = "4.5.11", features = ["derive"] } clap = { version = "4.5.11", features = ["derive"] }
log = "0.4.22" log = "0.4.22"
simplelog = "0.12.2" simplelog = "0.12.2"
rand = "0.8.5" rand = "0.8.5"
base64 = "0.22.1"

View File

@ -1,6 +1,6 @@
use crate::NetSettings; use crate::NetSettings;
pub fn download(net_settings: NetSettings) pub fn download(_net_settings: NetSettings)
{ {
} }

View File

@ -15,6 +15,7 @@ use crate::test::send_test_requests;
use crate::upload::upload; use crate::upload::upload;
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
#[command(name = "DNSTP")]
#[command(author, version, about, long_about = None)] #[command(author, version, about, long_about = None)]
struct Args { struct Args {
#[clap(subcommand)] #[clap(subcommand)]
@ -33,7 +34,7 @@ enum Command {
#[clap(flatten)] #[clap(flatten)]
net_options: NetSettings, net_options: NetSettings,
#[arg(short, long)] #[arg(short, long)]
value: String value: Vec<String>
}, },
/// Download a payload from the remote server /// Download a payload from the remote server
Download { Download {

View File

@ -4,7 +4,7 @@ use std::thread;
use std::time::Duration; use std::time::Duration;
use log::info; use log::info;
use rand::RngCore; use rand::RngCore;
use dnstplib::client_crypto_context::ClientCryptoContext; use dnstplib::session::client_crypto_context::ClientCryptoContext;
use dnstplib::DomainConfig; use dnstplib::DomainConfig;
use dnstplib::message::DNSMessage; use dnstplib::message::DNSMessage;
use dnstplib::net::{DNSSocket, NetworkMessage}; use dnstplib::net::{DNSSocket, NetworkMessage};
@ -42,10 +42,12 @@ pub fn send_test_requests(args: NetSettings)
let bytes = message.to_bytes(); let bytes = message.to_bytes();
tx_channel.send(Box::new(NetworkMessage { if let Err(_) = tx_channel.send(Box::new(NetworkMessage {
buffer: Box::new(bytes), buffer: Box::new(bytes),
peer: args.address.parse().unwrap() peer: args.address.parse().unwrap()
})); })) {
}
thread::sleep(Duration::from_secs(1)); thread::sleep(Duration::from_secs(1));
} }

View File

@ -3,16 +3,14 @@ use std::sync::{Arc, Mutex};
use std::thread; use std::thread;
use std::time::Duration; use std::time::Duration;
use log::info; use log::info;
use rand::RngCore;
use rand::rngs::OsRng; use rand::rngs::OsRng;
use dnstplib::client_crypto_context::ClientCryptoContext; use dnstplib::session::{ClientCryptoContext, generate_client_handshake_message, generate_string_encryption_message};
use dnstplib::{DomainConfig, send_message}; use dnstplib::{DomainConfig, send_message};
use dnstplib::message::{Direction, DNSHeader, DNSMessage, DNSQuestion, Opcode, QClass, QType, ResponseCode};
use dnstplib::net::DNSSocket; use dnstplib::net::DNSSocket;
use dnstplib::processor::ResponseProcesor; use dnstplib::processor::ResponseProcesor;
use crate::NetSettings; use crate::NetSettings;
pub fn upload(net_settings: NetSettings, value: String) pub fn upload(net_settings: NetSettings, values: Vec<String>)
{ {
let address = SocketAddr::from(([127, 0, 0, 1], 0)); let address = SocketAddr::from(([127, 0, 0, 1], 0));
@ -35,39 +33,7 @@ pub fn upload(net_settings: NetSettings, value: String)
info!("sending handshake..."); info!("sending handshake...");
let message = DNSMessage { let message = generate_client_handshake_message(&mut OsRng, &domain_config, crypto_context.clone(), &net_settings.address);
header: DNSHeader {
id: OsRng.next_u32() as u16,
direction: Direction::Request,
opcode: Opcode::Query,
authoritative: false,
truncation: false,
recursion_desired: false,
recursion_available: false,
valid_zeroes: true,
response: ResponseCode::NoError,
question_count: 2,
answer_record_count: 0,
authority_record_count: 0,
additional_record_count: 0,
},
questions: vec![
DNSQuestion {
qname: domain_config.get_fq_key_endpoint(),
qtype: QType::A,
qclass: QClass::Internet,
},
DNSQuestion {
qname: crypto_context.lock().unwrap().get_public_key_domain(&domain_config.base_domain),
qtype: QType::A,
qclass: QClass::Internet,
}
],
answer_records: vec![],
authority_records: vec![],
additional_records: vec![],
peer: net_settings.address.parse().unwrap(),
};
send_message(message, &tx_channel); send_message(message, &tx_channel);
@ -78,4 +44,19 @@ pub fn upload(net_settings: NetSettings, value: String)
} }
info!("crypto complete, sending data"); info!("crypto complete, sending data");
for v in values {
info!("sending [{}]", v);
if let Ok(encryption_message) = generate_string_encryption_message(
v,
&mut OsRng,
&domain_config,
crypto_context.clone(),
&net_settings.address
) {
send_message(encryption_message, &tx_channel);
}
}
} }

View File

@ -1,6 +1,8 @@
[package] [package]
name = "dnstp" name = "dnstp"
version = "0.1.0" version.workspace = true
authors.workspace = true
documentation.workspace = true
edition = "2021" edition = "2021"
publish = false publish = false

View File

@ -17,6 +17,7 @@ use dnstplib::processor::RequestProcesor;
/// Command-line arguments for configuring the server /// Command-line arguments for configuring the server
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
#[command(name = "DNSTPd")]
#[command(author, version, about, long_about = None)] #[command(author, version, about, long_about = None)]
struct Args { struct Args {
/// Addresses to bind server to /// Addresses to bind server to

View File

@ -1,6 +1,8 @@
[package] [package]
name = "dnstplib" name = "dnstplib"
version = "0.1.0" version.workspace = true
authors.workspace = true
documentation.workspace = true
edition = "2021" edition = "2021"
publish = ["sargit"] publish = ["sargit"]
@ -12,4 +14,5 @@ urlencoding = "2.1.3"
rand_core = { version = "0.6.4", features = ["getrandom"] } rand_core = { version = "0.6.4", features = ["getrandom"] }
p256 = { version = "0.13.2", features = ["ecdh"] } p256 = { version = "0.13.2", features = ["ecdh"] }
aes-gcm-siv = "0.11.1" aes-gcm-siv = "0.11.1"
base64 = "0.22.1"

View File

@ -49,14 +49,6 @@ pub fn get_shared_asym_secret(secret: &EphemeralSecret, opposing_public_key: &St
} }
} }
// pub fn generate_aes_nonce() -> Nonce
// {
// let mut nonce_buffer: [u8; 12] = [0; 12];
// &OsRng.fill_bytes(&mut nonce_buffer);
//
// Nonce::from(nonce_buffer)
// }
/// Generate a safe nonce to use in symmetric encryption /// Generate a safe nonce to use in symmetric encryption
pub fn generate_aes_nonce() -> Nonce pub fn generate_aes_nonce() -> Nonce
{ {

View File

@ -1,8 +1,6 @@
//! # Common Functionality //! # Common Functionality
//! The vast majority of functionality is in this library crate. The client and server executable crates are really just wiring up bits and pieces from this library. //! The vast majority of functionality is in this library crate. The client and server executable crates are really just wiring up bits and pieces from this library.
pub mod message_parser;
mod byte; mod byte;
pub mod processor; pub mod processor;
pub mod message; pub mod message;
@ -10,10 +8,9 @@ pub mod net;
pub mod string; pub mod string;
pub mod config; pub mod config;
pub mod crypto; pub mod crypto;
pub mod clients; pub mod session;
pub mod client_crypto_context;
use std::sync::mpsc::{Sender}; use std::sync::mpsc::Sender;
use log::error; use log::error;
pub use config::DomainConfig; pub use config::DomainConfig;
use crate::message::DNSMessage; use crate::message::DNSMessage;

View File

@ -102,29 +102,29 @@ impl DNSHeader {
{ {
let mut header_bytes: [u8; 12] = [0; 12]; let mut header_bytes: [u8; 12] = [0; 12];
apply_split_bytes(&mut header_bytes, self.id, crate::message_parser::ID_START); apply_split_bytes(&mut header_bytes, self.id, crate::message::message_parser::ID_START);
let mut flags: u16 = 0; let mut flags: u16 = 0;
if self.direction == Response { if self.direction == Response {
flags |= 0b1 << crate::message_parser::DIRECTION_SHIFT; flags |= 0b1 << crate::message::message_parser::DIRECTION_SHIFT;
} }
flags |= (self.opcode as u16) << crate::message_parser::OPCODE_SHIFT; flags |= (self.opcode as u16) << crate::message::message_parser::OPCODE_SHIFT;
flags |= (self.authoritative as u16) << crate::message_parser::AUTHORITATIVE_SHIFT; flags |= (self.authoritative as u16) << crate::message::message_parser::AUTHORITATIVE_SHIFT;
flags |= (self.truncation as u16) << crate::message_parser::TRUNCATION_SHIFT; flags |= (self.truncation as u16) << crate::message::message_parser::TRUNCATION_SHIFT;
flags |= (self.recursion_desired as u16) << crate::message_parser::RECURSION_DESIRED_SHIFT; flags |= (self.recursion_desired as u16) << crate::message::message_parser::RECURSION_DESIRED_SHIFT;
flags |= (self.recursion_available as u16) << crate::message_parser::RECURSION_AVAILABLE_SHIFT; flags |= (self.recursion_available as u16) << crate::message::message_parser::RECURSION_AVAILABLE_SHIFT;
flags |= self.response as u16; flags |= self.response as u16;
apply_split_bytes(&mut header_bytes, flags, crate::message_parser::FLAGS_START); apply_split_bytes(&mut header_bytes, flags, crate::message::message_parser::FLAGS_START);
apply_split_bytes(&mut header_bytes, self.question_count, crate::message_parser::QUESTION_COUNT_START); apply_split_bytes(&mut header_bytes, self.question_count, crate::message::message_parser::QUESTION_COUNT_START);
apply_split_bytes(&mut header_bytes, self.answer_record_count, crate::message_parser::ANSWER_RECORD_COUNT_START); apply_split_bytes(&mut header_bytes, self.answer_record_count, crate::message::message_parser::ANSWER_RECORD_COUNT_START);
apply_split_bytes(&mut header_bytes, self.authority_record_count, crate::message_parser::AUTHORITY_RECORD_COUNT_START); apply_split_bytes(&mut header_bytes, self.authority_record_count, crate::message::message_parser::AUTHORITY_RECORD_COUNT_START);
apply_split_bytes(&mut header_bytes, self.additional_record_count, crate::message_parser::ADDITIONAL_RECORD_COUNT_START); apply_split_bytes(&mut header_bytes, self.additional_record_count, crate::message::message_parser::ADDITIONAL_RECORD_COUNT_START);
header_bytes header_bytes
} }

View File

@ -153,7 +153,7 @@ impl DNSMessage {
response response
} }
pub fn protocol_error_from_request(&self, error_code: RequestError) -> DNSMessage pub fn protocol_error_from_request(&self, _error_code: RequestError) -> DNSMessage
{ {
let txt = Box::new(TXTRdata::from(String::new())); let txt = Box::new(TXTRdata::from(String::new()));

View File

@ -3,7 +3,7 @@
use crate::byte; use crate::byte;
use crate::message::{DNSMessage, Direction, DNSHeader, Opcode, ResponseCode, QuestionParseError, questions_from_bytes, records_from_bytes, RecordParseError}; use crate::message::{DNSMessage, Direction, DNSHeader, Opcode, ResponseCode, QuestionParseError, questions_from_bytes, records_from_bytes, RecordParseError};
use crate::net::NetworkMessage; use crate::net::NetworkMessage;
use crate::message_parser::MessageParseError::{HeaderParse, QuesionsParse}; use crate::message::MessageParseError::{HeaderParse, QuesionsParse};
pub const ID_START: usize = 0; pub const ID_START: usize = 0;
pub const FLAGS_START: usize = 2; pub const FLAGS_START: usize = 2;

View File

@ -3,8 +3,10 @@ pub mod header;
pub mod question; pub mod question;
pub mod message; pub mod message;
pub mod record; pub mod record;
pub mod message_parser;
pub use question::{DNSQuestion, QClass, QType, QuestionParseError, questions_to_bytes, questions_from_bytes}; pub use question::{DNSQuestion, QClass, QType, QuestionParseError, questions_from_bytes, questions_to_bytes};
pub use record::{ResourceRecord, RawRData, RData, ARdata, AAAARdata, TXTRdata, RecordParseError, records_to_bytes, records_from_bytes}; pub use record::{AAAARdata, ARdata, RawRData, RData, RecordParseError, records_from_bytes, records_to_bytes, ResourceRecord, TXTRdata};
pub use header::{DNSHeader, Direction, Opcode, ResponseCode, HEADER_SIZE}; pub use header::{Direction, DNSHeader, HEADER_SIZE, Opcode, ResponseCode};
pub use message::DNSMessage; pub use message::DNSMessage;
pub use message_parser::*;

View File

@ -19,7 +19,7 @@ fn one_question_back_and_forth() {
let mut q_bytes = q.to_bytes(); let mut q_bytes = q.to_bytes();
q_bytes.append(&mut vec![0, 0, 0, 0, 0, 0]); q_bytes.append(&mut vec![0, 0, 0, 0, 0, 0]);
let (q_reconstructed, q_remaining) = questions_from_bytes(q_bytes, 1).unwrap(); let (q_reconstructed, _q_remaining) = questions_from_bytes(q_bytes, 1).unwrap();
assert_questions_eq!(q, q_reconstructed[0]); assert_questions_eq!(q, q_reconstructed[0]);
} }
@ -43,7 +43,7 @@ fn two_questions_back_and_forth() {
q_bytes.append(&mut q2_bytes); q_bytes.append(&mut q2_bytes);
let (q_reconstructed, q_remaining) = questions_from_bytes(q_bytes, 2).unwrap(); let (q_reconstructed, _q_remaining) = questions_from_bytes(q_bytes, 2).unwrap();
assert_questions_eq!(q, q_reconstructed[0]); assert_questions_eq!(q, q_reconstructed[0]);
assert_questions_eq!(q2, q_reconstructed[1]); assert_questions_eq!(q2, q_reconstructed[1]);
@ -76,7 +76,7 @@ fn three_questions_back_and_forth() {
q_bytes.append(&mut q2_bytes); q_bytes.append(&mut q2_bytes);
q_bytes.append(&mut q3_bytes); q_bytes.append(&mut q3_bytes);
let (q_reconstructed, q_remaining) = questions_from_bytes(q_bytes, 3).unwrap(); let (q_reconstructed, _q_remaining) = questions_from_bytes(q_bytes, 3).unwrap();
assert_questions_eq!(q, q_reconstructed[0]); assert_questions_eq!(q, q_reconstructed[0]);
assert_questions_eq!(q2, q_reconstructed[1]); assert_questions_eq!(q2, q_reconstructed[1]);

View File

@ -28,7 +28,7 @@ fn one_answer_back_and_forth() {
let mut q_bytes = q.to_bytes(); let mut q_bytes = q.to_bytes();
q_bytes.append(&mut vec![0, 0, 0, 0, 0, 0]); q_bytes.append(&mut vec![0, 0, 0, 0, 0, 0]);
let (q_reconstructed, q_remaining) = records_from_bytes(q_bytes, 1).unwrap(); let (q_reconstructed, _q_remaining) = records_from_bytes(q_bytes, 1).unwrap();
assert_record_eq!(q, q_reconstructed[0]); assert_record_eq!(q, q_reconstructed[0]);
} }
@ -59,7 +59,7 @@ fn two_answers_back_and_forth() {
q_bytes.append(&mut q_2.to_bytes()); q_bytes.append(&mut q_2.to_bytes());
q_bytes.append(&mut vec![0, 0, 0, 0, 0, 0]); q_bytes.append(&mut vec![0, 0, 0, 0, 0, 0]);
let (q_reconstructed, q_remaining) = records_from_bytes(q_bytes, 2).unwrap(); let (q_reconstructed, _q_remaining) = records_from_bytes(q_bytes, 2).unwrap();
assert_record_eq!(q, q_reconstructed[0]); assert_record_eq!(q, q_reconstructed[0]);
assert_record_eq!(q_2, q_reconstructed[1]); assert_record_eq!(q_2, q_reconstructed[1]);

View File

@ -84,10 +84,12 @@ impl DNSSocket {
Ok((read_count, peer)) => { Ok((read_count, peer)) => {
if read_count > HEADER_SIZE { if read_count > HEADER_SIZE {
message_sender.send(Box::new(NetworkMessage { if let Err(_) = message_sender.send(Box::new(NetworkMessage {
buffer: buf, buffer: buf,
peer peer
})); })) {
}
} }
else { else {
debug!("skipping processing message from [{}], message isn't longer than standard header", peer); debug!("skipping processing message from [{}], message isn't longer than standard header", peer);
@ -155,11 +157,15 @@ impl DNSSocket {
{ {
// if let Some(t) = &mut self.thread { // if let Some(t) = &mut self.thread {
if let Some(k) = &self.rx_thread_killer { if let Some(k) = &self.rx_thread_killer {
k.send(()); if let Err(_) = k.send(()) {
}
// t.join(); // t.join();
} }
if let Some(k) = &self.tx_thread_killer { if let Some(k) = &self.tx_thread_killer {
k.send(()); if let Err(_) = k.send(()) {
}
// t.join(); // t.join();
} }
// } // }

View File

@ -7,8 +7,7 @@ use std::net::SocketAddr;
use log::error; use log::error;
pub use request::RequestProcesor; pub use request::RequestProcesor;
pub use response::ResponseProcesor; pub use response::ResponseProcesor;
use crate::message::{QuestionParseError, RecordParseError}; use crate::message::{QuestionParseError, RecordParseError, HeaderParseError, MessageParseError};
use crate::message_parser::{HeaderParseError, MessageParseError};
pub fn print_error(e: MessageParseError, peer: &SocketAddr) pub fn print_error(e: MessageParseError, peer: &SocketAddr)
{ {

View File

@ -0,0 +1,20 @@
use std::net::SocketAddr;
use std::sync::mpsc::Sender;
use std::sync::{Arc, Mutex};
use log::{error, info};
use crate::session::clients::Clients;
use crate::message::DNSMessage;
use crate::net::NetworkMessagePtr;
use crate::processor::RequestProcesor;
impl RequestProcesor {
pub fn handle_download_request(r: DNSMessage, _sending_channel: &Sender<NetworkMessagePtr>, clients: &Arc<Mutex<Clients>>, peer: SocketAddr)
{
info!("[{}] received download request", peer);
let client_id = &r.questions[0].qname;
if let Err(_) = clients.lock().unwrap().bump_last_seen(client_id) {
error!("[{}] failed to bump last seen time", peer);
}
}
}

View File

@ -1,6 +1,6 @@
use std::net::Ipv4Addr; use std::net::Ipv4Addr;
use p256::ecdh::EphemeralSecret; use p256::ecdh::EphemeralSecret;
use crate::clients::Client; use crate::session::clients::Client;
use crate::crypto::{asym_to_sym_key, get_random_asym_pair, get_shared_asym_secret, trim_public_key}; use crate::crypto::{asym_to_sym_key, get_random_asym_pair, get_shared_asym_secret, trim_public_key};
use crate::message::{ARdata, DNSMessage, QClass, QType, ResourceRecord}; use crate::message::{ARdata, DNSMessage, QClass, QType, ResourceRecord};
use crate::message::record::CnameRdata; use crate::message::record::CnameRdata;

View File

@ -2,13 +2,12 @@ use std::net::SocketAddr;
use std::sync::{Arc, mpsc, Mutex}; use std::sync::{Arc, mpsc, Mutex};
use std::sync::mpsc::{Receiver, Sender}; use std::sync::mpsc::{Receiver, Sender};
use std::thread; use std::thread;
use log::{error, info}; use log::{debug, error, info};
use crate::clients::Clients; use crate::session::Clients;
use crate::config::DomainConfig; use crate::config::DomainConfig;
use crate::message::{DNSMessage, QType}; use crate::message::{DNSMessage, QType, parse_message};
use crate::net::{NetworkMessagePtr}; use crate::net::{NetworkMessagePtr};
use crate::message_parser::parse_message;
use crate::processor::print_error; use crate::processor::print_error;
use crate::processor::request::encryption::{decode_key_request, DecodeKeyRequestError}; use crate::processor::request::encryption::{decode_key_request, DecodeKeyRequestError};
use crate::{RequestError, send_message}; use crate::{RequestError, send_message};
@ -60,7 +59,7 @@ impl RequestProcesor {
match parse_message(*m) { match parse_message(*m) {
Ok(r) => { Ok(r) => {
info!("received dns message: {:?}", r); debug!("received dns message: {:?}", r);
// If there is a question containing the protocol base domain, treat it as a dnstp request // If there is a question containing the protocol base domain, treat it as a dnstp request
// (handshake, upload, download) and handle as such // (handshake, upload, download) and handle as such
@ -156,20 +155,6 @@ impl RequestProcesor {
} }
} }
fn handle_download_request(r: DNSMessage, sending_channel: &Sender<NetworkMessagePtr>, clients: &Arc<Mutex<Clients>>, peer: SocketAddr)
{
info!("[{}] received download request", peer);
let client_id = &r.questions[0].qname;
clients.lock().unwrap().bump_last_seen(client_id);
}
fn handle_upload_request(r: DNSMessage, sending_channel: &Sender<NetworkMessagePtr>, clients: &Arc<Mutex<Clients>>, peer: SocketAddr)
{
info!("[{}] received upload request", peer);
let client_id = &r.questions[0].qname;
clients.lock().unwrap().bump_last_seen(client_id);
}
pub fn get_message_channel(&mut self) -> Option<Sender<NetworkMessagePtr>> pub fn get_message_channel(&mut self) -> Option<Sender<NetworkMessagePtr>>
{ {
self.message_channel.clone() self.message_channel.clone()

View File

@ -1,13 +1,13 @@
use crate::string::encode_domain_name; use crate::string::encode_domain_name;
use super::*; // use super::*;
use super::encryption::*; use super::encryption::*;
#[test] #[test]
fn encryption() fn encryption()
{ {
let (private, public) = get_key_request_with_base_domain(String::from("sarsoo.xyz")); let (_private, public) = get_key_request_with_base_domain(String::from("sarsoo.xyz"));
let encoded = encode_domain_name(&public); let _encoded = encode_domain_name(&public);
// let decoded = decode_domain_name(); // let decoded = decode_domain_name();
assert_eq!(1, 1); assert_eq!(1, 1);

View File

@ -0,0 +1,61 @@
use std::net::SocketAddr;
use std::sync::mpsc::Sender;
use std::sync::{Arc, Mutex};
use aes_gcm_siv::Nonce;
use log::{info, error};
use base64::prelude::*;
// use std::fs::OpenOptions;
// use std::io::prelude::*;
use crate::session::clients::Clients;
use crate::crypto::decrypt;
use crate::message::DNSMessage;
use crate::net::NetworkMessagePtr;
use crate::processor::RequestProcesor;
impl RequestProcesor {
pub fn handle_upload_request(r: DNSMessage, _sending_channel: &Sender<NetworkMessagePtr>, clients: &Arc<Mutex<Clients>>, peer: SocketAddr)
{
info!("[{}] received upload request", peer);
let client_id = &r.questions[0].qname;
if let Err(_) = clients.lock().unwrap().bump_last_seen(client_id) {
error!("[{}] failed to bump last seen time", peer);
}
let encrypted_value = BASE64_STANDARD.decode(r.questions[1].qname.clone());
let nonce_value = BASE64_STANDARD.decode(r.questions[2].qname.clone());
match (encrypted_value, nonce_value) {
(Ok(encrypted_value), Ok(nonce_value)) => {
let nonce = Nonce::from_slice(nonce_value.as_slice());
let decrypted = decrypt(clients.lock().unwrap().get_shared_key(client_id).unwrap(), nonce, &encrypted_value).unwrap();
let decrypted_string = String::from_utf8(decrypted).unwrap();
info!("[{}] decrypted [{}] from peer", peer, decrypted_string.as_str());
// let mut file = OpenOptions::new()
// .read(true)
// .write(true)
// .append(true)
// .create(true)
// .open(client_id)
// .unwrap();
//
// if let Err(e) = file.write(decrypted_string.as_bytes()) {
// error!("[{}] couldn't write to file: {}", peer, e);
// }
// if let Err(e) = file.write("\n".as_bytes()) {
// error!("[{}] couldn't write to file: {}", peer, e);
// }
}
(Err(e), _) => {
error!("[{}] failed to decode encrypted value from peer: {}", peer, e);
}
(_, Err(e)) => {
error!("[{}] failed to decode nonce from peer: {}", peer, e);
}
}
}
}

View File

@ -1,5 +1,5 @@
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use crate::client_crypto_context::ClientCryptoContext; use crate::session::client_crypto_context::ClientCryptoContext;
use crate::crypto::{asym_to_sym_key, get_shared_asym_secret}; use crate::crypto::{asym_to_sym_key, get_shared_asym_secret};
use crate::message::DNSMessage; use crate::message::DNSMessage;
use crate::string::get_fattened_public_key; use crate::string::get_fattened_public_key;

View File

@ -3,10 +3,10 @@ mod encryption;
use std::sync::{Arc, mpsc, Mutex}; use std::sync::{Arc, mpsc, Mutex};
use std::sync::mpsc::{Receiver, Sender}; use std::sync::mpsc::{Receiver, Sender};
use std::thread; use std::thread;
use log::{error, info}; use log::{error, info, debug};
use crate::client_crypto_context::ClientCryptoContext; use crate::session::client_crypto_context::ClientCryptoContext;
use crate::net::raw_request::NetworkMessagePtr; use crate::net::raw_request::NetworkMessagePtr;
use crate::message_parser::parse_message; use crate::message::parse_message;
use crate::processor::print_error; use crate::processor::print_error;
use crate::processor::response::encryption::{decode_key_response, DecodeKeyResponseError}; use crate::processor::response::encryption::{decode_key_response, DecodeKeyResponseError};
use crate::string::DomainDecodeError; use crate::string::DomainDecodeError;
@ -39,7 +39,7 @@ impl ResponseProcesor {
match parse_message(*m) { match parse_message(*m) {
Ok(r) => { Ok(r) => {
info!("received dns message: {:?}", r); debug!("received dns message: {:?}", r);
match decode_key_response(&r, crypto_context.clone()) match decode_key_response(&r, crypto_context.clone())
{ {

View File

@ -73,4 +73,15 @@ impl Clients {
} }
} }
} }
pub fn get_shared_key(&mut self, client_id: &String) -> Result<&Aes256GcmSiv, ()>
{
match self.client_map.get_mut(client_id)
{
None => Err(()),
Some(client) => {
Ok(&client.shared_key)
}
}
}
} }

View File

@ -0,0 +1,115 @@
use std::sync::{Arc, Mutex};
use base64::Engine;
use base64::prelude::BASE64_STANDARD;
use rand_core::{OsRng, RngCore};
use crate::crypto::{encrypt, generate_aes_nonce};
use crate::DomainConfig;
use crate::message::{Direction, DNSHeader, DNSMessage, DNSQuestion, Opcode, QClass, QType, ResponseCode};
use crate::session::ClientCryptoContext;
pub fn generate_client_handshake_message(rand: &mut OsRng, domain_config: &DomainConfig, crypto_context: Arc<Mutex<ClientCryptoContext>>, peer: &String) -> DNSMessage {
get_client_handshake_message(
rand.next_u32() as u16,
domain_config.get_fq_key_endpoint(),
crypto_context.lock().unwrap().get_public_key_domain(&domain_config.base_domain),
peer
)
}
pub fn get_client_handshake_message(msg_id: u16, key_domain: String, public_key_domain: String, peer: &String) -> DNSMessage {
DNSMessage {
header: DNSHeader {
id: msg_id,
direction: Direction::Request,
opcode: Opcode::Query,
authoritative: false,
truncation: false,
recursion_desired: false,
recursion_available: false,
valid_zeroes: true,
response: ResponseCode::NoError,
question_count: 2,
answer_record_count: 0,
authority_record_count: 0,
additional_record_count: 0,
},
questions: vec![
DNSQuestion {
qname: key_domain,
qtype: QType::A,
qclass: QClass::Internet,
},
DNSQuestion {
qname: public_key_domain,
qtype: QType::A,
qclass: QClass::Internet,
}
],
answer_records: vec![],
authority_records: vec![],
additional_records: vec![],
peer: peer.parse().unwrap(),
}
}
pub fn generate_string_encryption_message(value: String, rand: &mut OsRng, domain_config: &DomainConfig, crypto_context: Arc<Mutex<ClientCryptoContext>>, peer: &String) -> Result<DNSMessage, ()> {
let nonce = generate_aes_nonce();
let encrypted = encrypt(&crypto_context.lock().unwrap().shared_key.clone().unwrap(), &nonce, &value.clone().into_bytes());
if let Ok(e) = encrypted {
let encrypted_string = BASE64_STANDARD.encode(e);
let nonce_string = BASE64_STANDARD.encode(nonce);
return Ok(get_string_encryption_message(
rand.next_u32() as u16,
crypto_context.lock().unwrap().get_public_key_domain(&domain_config.base_domain),
encrypted_string,
nonce_string,
peer
))
}
Err(())
}
pub fn get_string_encryption_message(msg_id: u16, public_key_domain: String, encrypted_string: String, nonce_string: String, peer: &String) -> DNSMessage {
DNSMessage {
header: DNSHeader {
id: msg_id,
direction: Direction::Request,
opcode: Opcode::Query,
authoritative: false,
truncation: false,
recursion_desired: false,
recursion_available: false,
valid_zeroes: true,
response: ResponseCode::NoError,
question_count: 3,
answer_record_count: 0,
authority_record_count: 0,
additional_record_count: 0,
},
questions: vec![
DNSQuestion {
qname: public_key_domain,
qtype: QType::A,
qclass: QClass::Internet,
},
DNSQuestion {
qname: encrypted_string,
qtype: QType::A,
qclass: QClass::Internet,
},
DNSQuestion {
qname: nonce_string,
qtype: QType::A,
qclass: QClass::Internet,
}
],
answer_records: vec![],
authority_records: vec![],
additional_records: vec![],
peer: peer.parse().unwrap(),
}
}

7
dnstp/src/session/mod.rs Normal file
View File

@ -0,0 +1,7 @@
pub mod clients;
pub mod client_crypto_context;
mod message_generator;
pub use clients::Clients;
pub use client_crypto_context::ClientCryptoContext;
pub use message_generator::{generate_client_handshake_message, generate_string_encryption_message};