From 6a2c1ec15dd3c9aa66f41193de968924d614ca5a Mon Sep 17 00:00:00 2001 From: Andy Pack Date: Mon, 29 Jul 2024 17:07:49 +0100 Subject: [PATCH] upload working --- Cargo.lock | 14 ++- Cargo.toml | 7 +- dnstp-client/Cargo.toml | 7 +- dnstp-client/src/download.rs | 2 +- dnstp-client/src/main.rs | 3 +- dnstp-client/src/test.rs | 8 +- dnstp-client/src/upload.rs | 55 +++------ dnstp-server/Cargo.toml | 4 +- dnstp-server/src/main.rs | 1 + dnstp/Cargo.toml | 7 +- dnstp/src/crypto/mod.rs | 8 -- dnstp/src/lib.rs | 7 +- dnstp/src/message/header.rs | 24 ++-- dnstp/src/message/message.rs | 2 +- dnstp/src/{ => message}/message_parser.rs | 2 +- dnstp/src/message/mod.rs | 10 +- dnstp/src/message/question/tests.rs | 6 +- dnstp/src/message/record/tests.rs | 4 +- dnstp/src/net/socket.rs | 14 ++- dnstp/src/processor/mod.rs | 3 +- dnstp/src/processor/request/download.rs | 20 +++ dnstp/src/processor/request/encryption.rs | 2 +- dnstp/src/processor/request/mod.rs | 23 +--- dnstp/src/processor/request/tests.rs | 6 +- dnstp/src/processor/request/upload.rs | 61 ++++++++++ dnstp/src/processor/response/encryption.rs | 2 +- dnstp/src/processor/response/mod.rs | 8 +- .../{ => session}/client_crypto_context.rs | 0 dnstp/src/{ => session}/clients.rs | 11 ++ dnstp/src/session/message_generator.rs | 115 ++++++++++++++++++ dnstp/src/session/mod.rs | 7 ++ 31 files changed, 322 insertions(+), 121 deletions(-) rename dnstp/src/{ => message}/message_parser.rs (99%) rename dnstp/src/{ => session}/client_crypto_context.rs (100%) rename dnstp/src/{ => session}/clients.rs (86%) create mode 100644 dnstp/src/session/message_generator.rs create mode 100644 dnstp/src/session/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 1daca8e..4f0bae2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -93,6 +93,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "base64ct" version = "1.6.0" @@ -251,7 +257,7 @@ dependencies = [ [[package]] name = "dnstp" -version = "0.1.0" +version = "0.1.1" dependencies = [ "clap", "dnstplib", @@ -261,8 +267,9 @@ dependencies = [ [[package]] name = "dnstp-client" -version = "0.1.0" +version = "0.1.1" dependencies = [ + "base64", "clap", "dnstplib", "log", @@ -272,9 +279,10 @@ dependencies = [ [[package]] name = "dnstplib" -version = "0.1.0" +version = "0.1.1" dependencies = [ "aes-gcm-siv", + "base64", "log", "p256", "rand_core", diff --git a/Cargo.toml b/Cargo.toml index 97e7792..95a93e1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,4 +5,9 @@ members = [ "dnstp", "dnstp-client", "dnstp-server", -] \ No newline at end of file +] + +[workspace.package] +version = "0.1.1" +authors = ["sarsoo "] +documentation = "https://sarsoo.github.io/dnstp" \ No newline at end of file diff --git a/dnstp-client/Cargo.toml b/dnstp-client/Cargo.toml index f7619ac..d5c11c9 100644 --- a/dnstp-client/Cargo.toml +++ b/dnstp-client/Cargo.toml @@ -1,6 +1,8 @@ [package] name = "dnstp-client" -version = "0.1.0" +version.workspace = true +authors.workspace = true +documentation.workspace = true edition = "2021" publish = false @@ -11,4 +13,5 @@ dnstplib = { path = "../dnstp" } clap = { version = "4.5.11", features = ["derive"] } log = "0.4.22" simplelog = "0.12.2" -rand = "0.8.5" \ No newline at end of file +rand = "0.8.5" +base64 = "0.22.1" \ No newline at end of file diff --git a/dnstp-client/src/download.rs b/dnstp-client/src/download.rs index 5e9564f..ed96110 100644 --- a/dnstp-client/src/download.rs +++ b/dnstp-client/src/download.rs @@ -1,6 +1,6 @@ use crate::NetSettings; -pub fn download(net_settings: NetSettings) +pub fn download(_net_settings: NetSettings) { } \ No newline at end of file diff --git a/dnstp-client/src/main.rs b/dnstp-client/src/main.rs index c3075b1..84aee3c 100644 --- a/dnstp-client/src/main.rs +++ b/dnstp-client/src/main.rs @@ -15,6 +15,7 @@ use crate::test::send_test_requests; use crate::upload::upload; #[derive(Parser, Debug)] +#[command(name = "DNSTP")] #[command(author, version, about, long_about = None)] struct Args { #[clap(subcommand)] @@ -33,7 +34,7 @@ enum Command { #[clap(flatten)] net_options: NetSettings, #[arg(short, long)] - value: String + value: Vec }, /// Download a payload from the remote server Download { diff --git a/dnstp-client/src/test.rs b/dnstp-client/src/test.rs index c3cd29b..ae9fc7d 100644 --- a/dnstp-client/src/test.rs +++ b/dnstp-client/src/test.rs @@ -4,7 +4,7 @@ use std::thread; use std::time::Duration; use log::info; use rand::RngCore; -use dnstplib::client_crypto_context::ClientCryptoContext; +use dnstplib::session::client_crypto_context::ClientCryptoContext; use dnstplib::DomainConfig; use dnstplib::message::DNSMessage; use dnstplib::net::{DNSSocket, NetworkMessage}; @@ -42,10 +42,12 @@ pub fn send_test_requests(args: NetSettings) let bytes = message.to_bytes(); - tx_channel.send(Box::new(NetworkMessage { + if let Err(_) = tx_channel.send(Box::new(NetworkMessage { buffer: Box::new(bytes), peer: args.address.parse().unwrap() - })); + })) { + + } thread::sleep(Duration::from_secs(1)); } diff --git a/dnstp-client/src/upload.rs b/dnstp-client/src/upload.rs index 0bee69e..03b7053 100644 --- a/dnstp-client/src/upload.rs +++ b/dnstp-client/src/upload.rs @@ -3,16 +3,14 @@ use std::sync::{Arc, Mutex}; use std::thread; use std::time::Duration; use log::info; -use rand::RngCore; 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::message::{Direction, DNSHeader, DNSMessage, DNSQuestion, Opcode, QClass, QType, ResponseCode}; use dnstplib::net::DNSSocket; use dnstplib::processor::ResponseProcesor; use crate::NetSettings; -pub fn upload(net_settings: NetSettings, value: String) +pub fn upload(net_settings: NetSettings, values: Vec) { let address = SocketAddr::from(([127, 0, 0, 1], 0)); @@ -35,39 +33,7 @@ pub fn upload(net_settings: NetSettings, value: String) info!("sending handshake..."); - let message = DNSMessage { - 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(), - }; + let message = generate_client_handshake_message(&mut OsRng, &domain_config, crypto_context.clone(), &net_settings.address); send_message(message, &tx_channel); @@ -78,4 +44,19 @@ pub fn upload(net_settings: NetSettings, value: String) } 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); + } + } } \ No newline at end of file diff --git a/dnstp-server/Cargo.toml b/dnstp-server/Cargo.toml index 079f0b2..80045ce 100644 --- a/dnstp-server/Cargo.toml +++ b/dnstp-server/Cargo.toml @@ -1,6 +1,8 @@ [package] name = "dnstp" -version = "0.1.0" +version.workspace = true +authors.workspace = true +documentation.workspace = true edition = "2021" publish = false diff --git a/dnstp-server/src/main.rs b/dnstp-server/src/main.rs index a684105..1d2b881 100644 --- a/dnstp-server/src/main.rs +++ b/dnstp-server/src/main.rs @@ -17,6 +17,7 @@ use dnstplib::processor::RequestProcesor; /// Command-line arguments for configuring the server #[derive(Parser, Debug)] +#[command(name = "DNSTPd")] #[command(author, version, about, long_about = None)] struct Args { /// Addresses to bind server to diff --git a/dnstp/Cargo.toml b/dnstp/Cargo.toml index 9910988..5f8c23e 100644 --- a/dnstp/Cargo.toml +++ b/dnstp/Cargo.toml @@ -1,6 +1,8 @@ [package] name = "dnstplib" -version = "0.1.0" +version.workspace = true +authors.workspace = true +documentation.workspace = true edition = "2021" publish = ["sargit"] @@ -12,4 +14,5 @@ urlencoding = "2.1.3" rand_core = { version = "0.6.4", features = ["getrandom"] } p256 = { version = "0.13.2", features = ["ecdh"] } -aes-gcm-siv = "0.11.1" \ No newline at end of file +aes-gcm-siv = "0.11.1" +base64 = "0.22.1" \ No newline at end of file diff --git a/dnstp/src/crypto/mod.rs b/dnstp/src/crypto/mod.rs index d0d2c31..bc2f829 100644 --- a/dnstp/src/crypto/mod.rs +++ b/dnstp/src/crypto/mod.rs @@ -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 pub fn generate_aes_nonce() -> Nonce { diff --git a/dnstp/src/lib.rs b/dnstp/src/lib.rs index c76129f..4abce77 100644 --- a/dnstp/src/lib.rs +++ b/dnstp/src/lib.rs @@ -1,8 +1,6 @@ //! # 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. -pub mod message_parser; - mod byte; pub mod processor; pub mod message; @@ -10,10 +8,9 @@ pub mod net; pub mod string; pub mod config; pub mod crypto; -pub mod clients; -pub mod client_crypto_context; +pub mod session; -use std::sync::mpsc::{Sender}; +use std::sync::mpsc::Sender; use log::error; pub use config::DomainConfig; use crate::message::DNSMessage; diff --git a/dnstp/src/message/header.rs b/dnstp/src/message/header.rs index 5cc436a..09481eb 100644 --- a/dnstp/src/message/header.rs +++ b/dnstp/src/message/header.rs @@ -102,29 +102,29 @@ impl DNSHeader { { 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; 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.truncation as u16) << crate::message_parser::TRUNCATION_SHIFT; - flags |= (self.recursion_desired as u16) << crate::message_parser::RECURSION_DESIRED_SHIFT; - flags |= (self.recursion_available as u16) << crate::message_parser::RECURSION_AVAILABLE_SHIFT; + flags |= (self.authoritative as u16) << crate::message::message_parser::AUTHORITATIVE_SHIFT; + flags |= (self.truncation as u16) << crate::message::message_parser::TRUNCATION_SHIFT; + flags |= (self.recursion_desired as u16) << crate::message::message_parser::RECURSION_DESIRED_SHIFT; + flags |= (self.recursion_available as u16) << crate::message::message_parser::RECURSION_AVAILABLE_SHIFT; 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.answer_record_count, crate::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.additional_record_count, crate::message_parser::ADDITIONAL_RECORD_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::message_parser::ANSWER_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::message_parser::ADDITIONAL_RECORD_COUNT_START); header_bytes } diff --git a/dnstp/src/message/message.rs b/dnstp/src/message/message.rs index 5458e28..8e3edc3 100644 --- a/dnstp/src/message/message.rs +++ b/dnstp/src/message/message.rs @@ -153,7 +153,7 @@ impl DNSMessage { 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())); diff --git a/dnstp/src/message_parser.rs b/dnstp/src/message/message_parser.rs similarity index 99% rename from dnstp/src/message_parser.rs rename to dnstp/src/message/message_parser.rs index ad5d54f..4fdeb07 100644 --- a/dnstp/src/message_parser.rs +++ b/dnstp/src/message/message_parser.rs @@ -3,7 +3,7 @@ use crate::byte; use crate::message::{DNSMessage, Direction, DNSHeader, Opcode, ResponseCode, QuestionParseError, questions_from_bytes, records_from_bytes, RecordParseError}; 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 FLAGS_START: usize = 2; diff --git a/dnstp/src/message/mod.rs b/dnstp/src/message/mod.rs index 457754b..f90b47d 100644 --- a/dnstp/src/message/mod.rs +++ b/dnstp/src/message/mod.rs @@ -3,8 +3,10 @@ pub mod header; pub mod question; pub mod message; pub mod record; +pub mod message_parser; -pub use question::{DNSQuestion, QClass, QType, QuestionParseError, questions_to_bytes, questions_from_bytes}; -pub use record::{ResourceRecord, RawRData, RData, ARdata, AAAARdata, TXTRdata, RecordParseError, records_to_bytes, records_from_bytes}; -pub use header::{DNSHeader, Direction, Opcode, ResponseCode, HEADER_SIZE}; -pub use message::DNSMessage; \ No newline at end of file +pub use question::{DNSQuestion, QClass, QType, QuestionParseError, questions_from_bytes, questions_to_bytes}; +pub use record::{AAAARdata, ARdata, RawRData, RData, RecordParseError, records_from_bytes, records_to_bytes, ResourceRecord, TXTRdata}; +pub use header::{Direction, DNSHeader, HEADER_SIZE, Opcode, ResponseCode}; +pub use message::DNSMessage; +pub use message_parser::*; \ No newline at end of file diff --git a/dnstp/src/message/question/tests.rs b/dnstp/src/message/question/tests.rs index a5a9d2c..f9d858f 100644 --- a/dnstp/src/message/question/tests.rs +++ b/dnstp/src/message/question/tests.rs @@ -19,7 +19,7 @@ fn one_question_back_and_forth() { let mut q_bytes = q.to_bytes(); 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]); } @@ -43,7 +43,7 @@ fn two_questions_back_and_forth() { 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!(q2, q_reconstructed[1]); @@ -76,7 +76,7 @@ fn three_questions_back_and_forth() { q_bytes.append(&mut q2_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!(q2, q_reconstructed[1]); diff --git a/dnstp/src/message/record/tests.rs b/dnstp/src/message/record/tests.rs index 870ac71..0df097e 100644 --- a/dnstp/src/message/record/tests.rs +++ b/dnstp/src/message/record/tests.rs @@ -28,7 +28,7 @@ fn one_answer_back_and_forth() { let mut q_bytes = q.to_bytes(); 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]); } @@ -59,7 +59,7 @@ fn two_answers_back_and_forth() { q_bytes.append(&mut q_2.to_bytes()); 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_2, q_reconstructed[1]); diff --git a/dnstp/src/net/socket.rs b/dnstp/src/net/socket.rs index 8629697..d4c41ff 100644 --- a/dnstp/src/net/socket.rs +++ b/dnstp/src/net/socket.rs @@ -84,10 +84,12 @@ impl DNSSocket { Ok((read_count, peer)) => { if read_count > HEADER_SIZE { - message_sender.send(Box::new(NetworkMessage { + if let Err(_) = message_sender.send(Box::new(NetworkMessage { buffer: buf, peer - })); + })) { + + } } else { 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(k) = &self.rx_thread_killer { - k.send(()); + if let Err(_) = k.send(()) { + + } // t.join(); } if let Some(k) = &self.tx_thread_killer { - k.send(()); + if let Err(_) = k.send(()) { + + } // t.join(); } // } diff --git a/dnstp/src/processor/mod.rs b/dnstp/src/processor/mod.rs index 90a2e8c..b7a8b17 100644 --- a/dnstp/src/processor/mod.rs +++ b/dnstp/src/processor/mod.rs @@ -7,8 +7,7 @@ use std::net::SocketAddr; use log::error; pub use request::RequestProcesor; pub use response::ResponseProcesor; -use crate::message::{QuestionParseError, RecordParseError}; -use crate::message_parser::{HeaderParseError, MessageParseError}; +use crate::message::{QuestionParseError, RecordParseError, HeaderParseError, MessageParseError}; pub fn print_error(e: MessageParseError, peer: &SocketAddr) { diff --git a/dnstp/src/processor/request/download.rs b/dnstp/src/processor/request/download.rs index e69de29..d806605 100644 --- a/dnstp/src/processor/request/download.rs +++ b/dnstp/src/processor/request/download.rs @@ -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, clients: &Arc>, 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); + } + } +} \ No newline at end of file diff --git a/dnstp/src/processor/request/encryption.rs b/dnstp/src/processor/request/encryption.rs index 975343c..bdd0656 100644 --- a/dnstp/src/processor/request/encryption.rs +++ b/dnstp/src/processor/request/encryption.rs @@ -1,6 +1,6 @@ use std::net::Ipv4Addr; 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::message::{ARdata, DNSMessage, QClass, QType, ResourceRecord}; use crate::message::record::CnameRdata; diff --git a/dnstp/src/processor/request/mod.rs b/dnstp/src/processor/request/mod.rs index 5bee0c7..fa64b73 100644 --- a/dnstp/src/processor/request/mod.rs +++ b/dnstp/src/processor/request/mod.rs @@ -2,13 +2,12 @@ use std::net::SocketAddr; use std::sync::{Arc, mpsc, Mutex}; use std::sync::mpsc::{Receiver, Sender}; use std::thread; -use log::{error, info}; -use crate::clients::Clients; +use log::{debug, error, info}; +use crate::session::Clients; use crate::config::DomainConfig; -use crate::message::{DNSMessage, QType}; +use crate::message::{DNSMessage, QType, parse_message}; use crate::net::{NetworkMessagePtr}; -use crate::message_parser::parse_message; use crate::processor::print_error; use crate::processor::request::encryption::{decode_key_request, DecodeKeyRequestError}; use crate::{RequestError, send_message}; @@ -60,7 +59,7 @@ impl RequestProcesor { match parse_message(*m) { 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 // (handshake, upload, download) and handle as such @@ -156,20 +155,6 @@ impl RequestProcesor { } } - fn handle_download_request(r: DNSMessage, sending_channel: &Sender, clients: &Arc>, 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, clients: &Arc>, 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> { self.message_channel.clone() diff --git a/dnstp/src/processor/request/tests.rs b/dnstp/src/processor/request/tests.rs index aaa5a01..f77aa62 100644 --- a/dnstp/src/processor/request/tests.rs +++ b/dnstp/src/processor/request/tests.rs @@ -1,13 +1,13 @@ use crate::string::encode_domain_name; -use super::*; +// use super::*; use super::encryption::*; #[test] 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(); assert_eq!(1, 1); diff --git a/dnstp/src/processor/request/upload.rs b/dnstp/src/processor/request/upload.rs index e69de29..c6b228e 100644 --- a/dnstp/src/processor/request/upload.rs +++ b/dnstp/src/processor/request/upload.rs @@ -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, clients: &Arc>, 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); + } + } + } +} \ No newline at end of file diff --git a/dnstp/src/processor/response/encryption.rs b/dnstp/src/processor/response/encryption.rs index 1e32289..3da9bf8 100644 --- a/dnstp/src/processor/response/encryption.rs +++ b/dnstp/src/processor/response/encryption.rs @@ -1,5 +1,5 @@ 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::message::DNSMessage; use crate::string::get_fattened_public_key; diff --git a/dnstp/src/processor/response/mod.rs b/dnstp/src/processor/response/mod.rs index 55602bb..6295849 100644 --- a/dnstp/src/processor/response/mod.rs +++ b/dnstp/src/processor/response/mod.rs @@ -3,10 +3,10 @@ mod encryption; use std::sync::{Arc, mpsc, Mutex}; use std::sync::mpsc::{Receiver, Sender}; use std::thread; -use log::{error, info}; -use crate::client_crypto_context::ClientCryptoContext; +use log::{error, info, debug}; +use crate::session::client_crypto_context::ClientCryptoContext; 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::response::encryption::{decode_key_response, DecodeKeyResponseError}; use crate::string::DomainDecodeError; @@ -39,7 +39,7 @@ impl ResponseProcesor { match parse_message(*m) { Ok(r) => { - info!("received dns message: {:?}", r); + debug!("received dns message: {:?}", r); match decode_key_response(&r, crypto_context.clone()) { diff --git a/dnstp/src/client_crypto_context.rs b/dnstp/src/session/client_crypto_context.rs similarity index 100% rename from dnstp/src/client_crypto_context.rs rename to dnstp/src/session/client_crypto_context.rs diff --git a/dnstp/src/clients.rs b/dnstp/src/session/clients.rs similarity index 86% rename from dnstp/src/clients.rs rename to dnstp/src/session/clients.rs index 079201d..f5f6db0 100644 --- a/dnstp/src/clients.rs +++ b/dnstp/src/session/clients.rs @@ -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) + } + } + } } \ No newline at end of file diff --git a/dnstp/src/session/message_generator.rs b/dnstp/src/session/message_generator.rs new file mode 100644 index 0000000..4d90154 --- /dev/null +++ b/dnstp/src/session/message_generator.rs @@ -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>, 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>, peer: &String) -> Result { + + 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(), + } +} \ No newline at end of file diff --git a/dnstp/src/session/mod.rs b/dnstp/src/session/mod.rs new file mode 100644 index 0000000..c75f741 --- /dev/null +++ b/dnstp/src/session/mod.rs @@ -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};