mirror of
https://github.com/ZeusWPI/ZNS.git
synced 2024-10-29 21:14:27 +01:00
Convert errors using thiserror crate
This commit is contained in:
parent
6ac9f2f36e
commit
aa94dc21bb
16 changed files with 143 additions and 212 deletions
21
Cargo.lock
generated
21
Cargo.lock
generated
|
@ -943,6 +943,26 @@ dependencies = [
|
|||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.61"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.61"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.6.0"
|
||||
|
@ -1361,5 +1381,6 @@ dependencies = [
|
|||
"int-enum",
|
||||
"reqwest",
|
||||
"ring",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
]
|
||||
|
|
|
@ -12,3 +12,4 @@ base64 = "0.22.0"
|
|||
reqwest = {version = "0.12.4", features = ["json","default"]}
|
||||
asn1 = "0.16.2"
|
||||
int-enum = "1.1"
|
||||
thiserror = "1.0"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::{
|
||||
errors::DatabaseError,
|
||||
errors::ZNSError,
|
||||
structs::{Class, Type, RR},
|
||||
};
|
||||
use diesel::prelude::*;
|
||||
|
@ -81,7 +81,7 @@ impl Record {
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn insert_into_database(rr: &RR) -> Result<(), DatabaseError> {
|
||||
pub async fn insert_into_database(rr: &RR) -> Result<(), ZNSError> {
|
||||
let db_connection = &mut establish_connection();
|
||||
let record = Record {
|
||||
name: rr.name.join("."),
|
||||
|
@ -92,7 +92,7 @@ pub async fn insert_into_database(rr: &RR) -> Result<(), DatabaseError> {
|
|||
rdata: rr.rdata.clone(),
|
||||
};
|
||||
|
||||
Record::create(db_connection, record).map_err(|e| DatabaseError {
|
||||
Record::create(db_connection, record).map_err(|e| ZNSError::Database {
|
||||
message: e.to_string(),
|
||||
})?;
|
||||
|
||||
|
@ -103,11 +103,11 @@ pub async fn get_from_database(
|
|||
name: &Vec<String>,
|
||||
_type: Type,
|
||||
class: Class,
|
||||
) -> Result<Vec<RR>, DatabaseError> {
|
||||
) -> Result<Vec<RR>, ZNSError> {
|
||||
let db_connection = &mut establish_connection();
|
||||
let records =
|
||||
Record::get(db_connection, name.join("."), _type.into(), class.into()).map_err(|e| {
|
||||
DatabaseError {
|
||||
ZNSError::Database {
|
||||
message: e.to_string(),
|
||||
}
|
||||
})?;
|
||||
|
|
124
src/errors.rs
124
src/errors.rs
|
@ -1,100 +1,44 @@
|
|||
use core::fmt;
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::structs::RCODE;
|
||||
|
||||
pub struct DNSError {
|
||||
pub message: String,
|
||||
pub rcode: RCODE,
|
||||
#[derive(Error, Debug)]
|
||||
pub enum ZNSError {
|
||||
#[error("Parse Error for {object:?}: {message:?}")]
|
||||
Parse { object: String, message: String },
|
||||
#[error("Database Error: {message:?}")]
|
||||
Database { message: String },
|
||||
#[error("Reader Error: {message:?}")]
|
||||
Reader { message: String },
|
||||
#[error("PublicKey Error: {message:?}")]
|
||||
PublicKey { message: String },
|
||||
#[error("Reqwest error")]
|
||||
Reqwest(#[from] reqwest::Error),
|
||||
|
||||
#[error("DNS Query Format Error: {message:?}")]
|
||||
Formerr { message: String },
|
||||
#[error("Domain name does not exist")]
|
||||
NXDomain { domain: String },
|
||||
#[error("NotImplemented Error for {object:?}: {message:?}")]
|
||||
NotImp { object: String, message: String },
|
||||
#[error("Authentication Error: {message:?}")]
|
||||
NotAuth { message: String },
|
||||
#[error("I refuse to answer the query: {message:?}")]
|
||||
Refused { message: String },
|
||||
}
|
||||
|
||||
impl fmt::Display for DNSError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Error: {}", self.message)
|
||||
impl ZNSError {
|
||||
pub fn rcode(&self) -> RCODE {
|
||||
match self {
|
||||
ZNSError::Formerr { .. } | ZNSError::Parse { .. } | ZNSError::Reader { .. } => {
|
||||
RCODE::FORMERR
|
||||
}
|
||||
}
|
||||
ZNSError::Database { .. } | ZNSError::Reqwest(_) => RCODE::SERVFAIL,
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ParseError {
|
||||
pub object: String,
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
impl fmt::Display for ParseError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Parse Error for {}: {}", self.object, self.message)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DatabaseError {
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
impl fmt::Display for DatabaseError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Database Error: {}", self.message)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AuthenticationError {
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
impl fmt::Display for AuthenticationError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Authentication Error: {}", self.message)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ReaderError {
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
impl fmt::Display for ReaderError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Reader Error: {}", self.message)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> From<E> for ParseError
|
||||
where
|
||||
E: Into<ReaderError>,
|
||||
{
|
||||
fn from(value: E) -> Self {
|
||||
ParseError {
|
||||
object: String::from("Reader"),
|
||||
message: value.into().to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> From<E> for DNSError
|
||||
where
|
||||
E: Into<ParseError>,
|
||||
{
|
||||
fn from(value: E) -> Self {
|
||||
DNSError {
|
||||
message: value.into().to_string(),
|
||||
rcode: RCODE::FORMERR,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait Supported {}
|
||||
|
||||
impl Supported for reqwest::Error {}
|
||||
impl Supported for DatabaseError {}
|
||||
|
||||
impl<E> From<E> for AuthenticationError
|
||||
where
|
||||
E: Supported,
|
||||
E: std::fmt::Display,
|
||||
{
|
||||
fn from(value: E) -> Self {
|
||||
AuthenticationError {
|
||||
message: value.to_string(),
|
||||
ZNSError::NotAuth { .. } | ZNSError::PublicKey { .. } => RCODE::NOTAUTH,
|
||||
ZNSError::NXDomain { .. } => RCODE::NXDOMAIN,
|
||||
ZNSError::NotImp { .. } => RCODE::NOTIMP,
|
||||
ZNSError::Refused { .. } => RCODE::REFUSED,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
errors::DNSError,
|
||||
structs::{Message, Opcode, RCODE},
|
||||
errors::ZNSError,
|
||||
structs::{Message, Opcode},
|
||||
};
|
||||
|
||||
use self::{query::QueryHandler, update::UpdateHandler};
|
||||
|
@ -9,21 +9,20 @@ mod query;
|
|||
mod update;
|
||||
|
||||
pub trait ResponseHandler {
|
||||
async fn handle(message: &Message, raw: &[u8]) -> Result<Message, DNSError>;
|
||||
async fn handle(message: &Message, raw: &[u8]) -> Result<Message, ZNSError>;
|
||||
}
|
||||
|
||||
pub struct Handler {}
|
||||
|
||||
impl ResponseHandler for Handler {
|
||||
async fn handle(message: &Message, raw: &[u8]) -> Result<Message, DNSError> {
|
||||
async fn handle(message: &Message, raw: &[u8]) -> Result<Message, ZNSError> {
|
||||
match message.get_opcode() {
|
||||
Ok(opcode) => match opcode {
|
||||
Opcode::QUERY => QueryHandler::handle(&message, raw).await,
|
||||
Opcode::UPDATE => UpdateHandler::handle(&message, raw).await,
|
||||
},
|
||||
Err(e) => Err(DNSError {
|
||||
Err(e) => Err(ZNSError::Formerr {
|
||||
message: e.to_string(),
|
||||
rcode: RCODE::FORMERR,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,11 @@
|
|||
use crate::{
|
||||
db::models::get_from_database,
|
||||
errors::DNSError,
|
||||
structs::{Message, RCODE},
|
||||
};
|
||||
use crate::{db::models::get_from_database, errors::ZNSError, structs::Message};
|
||||
|
||||
use super::ResponseHandler;
|
||||
|
||||
pub struct QueryHandler {}
|
||||
|
||||
impl ResponseHandler for QueryHandler {
|
||||
async fn handle(message: &Message, _raw: &[u8]) -> Result<Message, DNSError> {
|
||||
async fn handle(message: &Message, _raw: &[u8]) -> Result<Message, ZNSError> {
|
||||
let mut response = message.clone();
|
||||
response.header.arcount = 0; //TODO: fix this, handle unknown class values
|
||||
|
||||
|
@ -23,12 +19,16 @@ impl ResponseHandler for QueryHandler {
|
|||
|
||||
match answers {
|
||||
Ok(rrs) => {
|
||||
if rrs.len() == 0 {
|
||||
return Err(ZNSError::NXDomain {
|
||||
domain: question.qname.join("."),
|
||||
});
|
||||
}
|
||||
response.header.ancount = rrs.len() as u16;
|
||||
response.answer.extend(rrs)
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(DNSError {
|
||||
rcode: RCODE::NXDOMAIN,
|
||||
return Err(ZNSError::Database {
|
||||
message: e.to_string(),
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
use crate::{
|
||||
config::Config,
|
||||
db::models::get_from_database,
|
||||
errors::{AuthenticationError, DatabaseError},
|
||||
errors::ZNSError,
|
||||
parser::FromBytes,
|
||||
reader::Reader,
|
||||
structs::{Class, RRClass, RRType, Type},
|
||||
};
|
||||
|
||||
use super::{dnskey::DNSKeyRData, pubkeys::PublicKeyError, sig::Sig};
|
||||
use super::{dnskey::DNSKeyRData, sig::Sig};
|
||||
|
||||
pub async fn authenticate(sig: &Sig, zone: &Vec<String>) -> Result<bool, AuthenticationError> {
|
||||
pub async fn authenticate(sig: &Sig, zone: &Vec<String>) -> Result<bool, ZNSError> {
|
||||
if zone.len() >= 4 {
|
||||
let username = &zone[zone.len() - 4]; // Should match: username.users.zeus.gent
|
||||
|
||||
|
@ -21,7 +21,7 @@ pub async fn authenticate(sig: &Sig, zone: &Vec<String>) -> Result<bool, Authent
|
|||
Ok(validate_dnskey(zone, sig).await?)
|
||||
}
|
||||
} else {
|
||||
Err(AuthenticationError {
|
||||
Err(ZNSError::NotAuth {
|
||||
message: String::from("Invalid zone"),
|
||||
})
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ async fn validate_ssh(username: &String, sig: &Sig) -> Result<bool, reqwest::Err
|
|||
.any(|key| sig.verify_ssh(&key).is_ok_and(|b| b)))
|
||||
}
|
||||
|
||||
async fn validate_dnskey(zone: &Vec<String>, sig: &Sig) -> Result<bool, DatabaseError> {
|
||||
async fn validate_dnskey(zone: &Vec<String>, sig: &Sig) -> Result<bool, ZNSError> {
|
||||
Ok(
|
||||
get_from_database(zone, Type::Type(RRType::DNSKEY), Class::Class(RRClass::IN))
|
||||
.await?
|
||||
|
@ -52,11 +52,3 @@ async fn validate_dnskey(zone: &Vec<String>, sig: &Sig) -> Result<bool, Database
|
|||
}),
|
||||
)
|
||||
}
|
||||
|
||||
impl From<PublicKeyError> for AuthenticationError {
|
||||
fn from(value: PublicKeyError) -> Self {
|
||||
AuthenticationError {
|
||||
message: value.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{errors::ParseError, parser::FromBytes, reader::Reader};
|
||||
use crate::{errors::ZNSError, parser::FromBytes, reader::Reader};
|
||||
|
||||
use super::sig::Algorithm;
|
||||
|
||||
|
@ -13,7 +13,7 @@ pub struct DNSKeyRData {
|
|||
|
||||
//TODO: validate values
|
||||
impl FromBytes for DNSKeyRData {
|
||||
fn from_bytes(reader: &mut Reader) -> Result<Self, ParseError> {
|
||||
fn from_bytes(reader: &mut Reader) -> Result<Self, ZNSError> {
|
||||
Ok(DNSKeyRData {
|
||||
flags: reader.read_u16()?,
|
||||
protocol: reader.read_u8()?,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
db::models::{delete_from_database, insert_into_database},
|
||||
errors::DNSError,
|
||||
structs::{Class, Message, RRClass, RRType, Type, RCODE},
|
||||
errors::ZNSError,
|
||||
structs::{Class, Message, RRClass, RRType, Type},
|
||||
utils::vec_equal,
|
||||
};
|
||||
|
||||
|
@ -17,15 +17,14 @@ mod sig;
|
|||
pub struct UpdateHandler {}
|
||||
|
||||
impl ResponseHandler for UpdateHandler {
|
||||
async fn handle(message: &Message, raw: &[u8]) -> Result<Message, crate::errors::DNSError> {
|
||||
async fn handle(message: &Message, raw: &[u8]) -> Result<Message, ZNSError> {
|
||||
let response = message.clone();
|
||||
// Zone section (question) processing
|
||||
if (message.header.qdcount != 1)
|
||||
|| !matches!(message.question[0].qtype, Type::Type(RRType::SOA))
|
||||
{
|
||||
return Err(DNSError {
|
||||
return Err(ZNSError::Formerr {
|
||||
message: "Qdcount not one".to_string(),
|
||||
rcode: RCODE::FORMERR,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -33,9 +32,8 @@ impl ResponseHandler for UpdateHandler {
|
|||
let zone = &message.question[0];
|
||||
let zlen = zone.qname.len();
|
||||
if !(zlen >= 2 && zone.qname[zlen - 1] == "gent" && zone.qname[zlen - 2] == "zeus") {
|
||||
return Err(DNSError {
|
||||
return Err(ZNSError::Formerr {
|
||||
message: "Invalid zone".to_string(),
|
||||
rcode: RCODE::NOTAUTH,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -50,15 +48,13 @@ impl ResponseHandler for UpdateHandler {
|
|||
.await
|
||||
.is_ok_and(|x| x)
|
||||
{
|
||||
return Err(DNSError {
|
||||
return Err(ZNSError::NotAuth {
|
||||
message: "Unable to verify authentication".to_string(),
|
||||
rcode: RCODE::NOTAUTH,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
return Err(DNSError {
|
||||
return Err(ZNSError::NotAuth {
|
||||
message: "No KEY record at the end of request found".to_string(),
|
||||
rcode: RCODE::NOTAUTH,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -68,9 +64,8 @@ impl ResponseHandler for UpdateHandler {
|
|||
|
||||
// Check if rr has same zone
|
||||
if rlen < zlen || !(vec_equal(&zone.qname, &rr.name[rlen - zlen..])) {
|
||||
return Err(DNSError {
|
||||
return Err(ZNSError::Refused {
|
||||
message: "RR has different zone from Question".to_string(),
|
||||
rcode: RCODE::NOTZONE,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -84,9 +79,8 @@ impl ResponseHandler for UpdateHandler {
|
|||
.contains(&rr.class)
|
||||
{
|
||||
true => {
|
||||
return Err(DNSError {
|
||||
return Err(ZNSError::Formerr {
|
||||
message: "RR has invalid rr,ttl or class".to_string(),
|
||||
rcode: RCODE::FORMERR,
|
||||
});
|
||||
}
|
||||
false => (),
|
||||
|
@ -99,9 +93,9 @@ impl ResponseHandler for UpdateHandler {
|
|||
} else if rr.class == Class::Class(RRClass::ANY) {
|
||||
if rr._type == Type::Type(RRType::ANY) {
|
||||
if rr.name == zone.qname {
|
||||
return Err(DNSError {
|
||||
message: "Not yet implemented".to_string(),
|
||||
rcode: RCODE::NOTIMP,
|
||||
return Err(ZNSError::NotImp {
|
||||
object: String::from("Update Handler"),
|
||||
message: "rr.name == zone.qname".to_string(),
|
||||
});
|
||||
} else {
|
||||
delete_from_database(&rr.name, None, Class::Class(RRClass::IN), None).await;
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
use ring::signature;
|
||||
|
||||
use crate::{handlers::update::sig::Algorithm, reader::Reader};
|
||||
use crate::{errors::ZNSError, handlers::update::sig::Algorithm, reader::Reader};
|
||||
|
||||
use super::{PublicKey, PublicKeyError, SSH_ED25519};
|
||||
use super::{PublicKey, SSH_ED25519};
|
||||
|
||||
pub struct Ed25519PublicKey {
|
||||
data: Vec<u8>,
|
||||
}
|
||||
|
||||
impl PublicKey for Ed25519PublicKey {
|
||||
fn from_openssh(key: &[u8]) -> Result<Self, PublicKeyError>
|
||||
fn from_openssh(key: &[u8]) -> Result<Self, ZNSError>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
|
@ -21,7 +21,7 @@ impl PublicKey for Ed25519PublicKey {
|
|||
})
|
||||
}
|
||||
|
||||
fn from_dnskey(key: &[u8]) -> Result<Self, PublicKeyError>
|
||||
fn from_dnskey(key: &[u8]) -> Result<Self, ZNSError>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
|
@ -33,7 +33,7 @@ impl PublicKey for Ed25519PublicKey {
|
|||
data: &[u8],
|
||||
signature: &[u8],
|
||||
_algorithm: &Algorithm,
|
||||
) -> Result<bool, PublicKeyError> {
|
||||
) -> Result<bool, ZNSError> {
|
||||
let pkey = ring::signature::UnparsedPublicKey::new(&signature::ED25519, &self.data);
|
||||
|
||||
Ok(pkey.verify(data, signature).is_ok())
|
||||
|
|
|
@ -1,42 +1,23 @@
|
|||
mod ed25519;
|
||||
mod rsa;
|
||||
use core::fmt;
|
||||
use std::str::from_utf8;
|
||||
|
||||
use crate::{errors::ReaderError, reader::Reader};
|
||||
use crate::errors::ZNSError;
|
||||
use crate::reader::Reader;
|
||||
|
||||
pub use self::ed25519::Ed25519PublicKey;
|
||||
pub use self::rsa::RsaPublicKey;
|
||||
|
||||
use super::sig::Algorithm;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PublicKeyError {
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
impl fmt::Display for PublicKeyError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Public Key Error: {}", self.message)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ReaderError> for PublicKeyError {
|
||||
fn from(value: ReaderError) -> Self {
|
||||
PublicKeyError {
|
||||
message: value.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub const SSH_ED25519: &str = "ssh-ed25519";
|
||||
pub const SSH_RSA: &str = "ssh-rsa";
|
||||
|
||||
pub trait PublicKey {
|
||||
fn verify_ssh_type(reader: &mut Reader, key_type: &str) -> Result<(), PublicKeyError> {
|
||||
fn verify_ssh_type(reader: &mut Reader, key_type: &str) -> Result<(), ZNSError> {
|
||||
let type_size = reader.read_i32()?;
|
||||
let read = reader.read(type_size as usize)?;
|
||||
let algo_type = from_utf8(&read).map_err(|e| PublicKeyError {
|
||||
let algo_type = from_utf8(&read).map_err(|e| ZNSError::PublicKey {
|
||||
message: format!(
|
||||
"Could not convert type name bytes to string: {}",
|
||||
e.to_string()
|
||||
|
@ -46,17 +27,17 @@ pub trait PublicKey {
|
|||
if algo_type == key_type {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(PublicKeyError {
|
||||
Err(ZNSError::PublicKey {
|
||||
message: String::from("ssh key type does not match identifier"),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn from_openssh(key: &[u8]) -> Result<Self, PublicKeyError>
|
||||
fn from_openssh(key: &[u8]) -> Result<Self, ZNSError>
|
||||
where
|
||||
Self: Sized;
|
||||
|
||||
fn from_dnskey(key: &[u8]) -> Result<Self, PublicKeyError>
|
||||
fn from_dnskey(key: &[u8]) -> Result<Self, ZNSError>
|
||||
where
|
||||
Self: Sized;
|
||||
|
||||
|
@ -65,5 +46,5 @@ pub trait PublicKey {
|
|||
data: &[u8],
|
||||
signature: &[u8],
|
||||
algorithm: &Algorithm,
|
||||
) -> Result<bool, PublicKeyError>;
|
||||
) -> Result<bool, ZNSError>;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use ring::signature;
|
||||
|
||||
use crate::{handlers::update::sig::Algorithm, reader::Reader};
|
||||
use crate::{errors::ZNSError, handlers::update::sig::Algorithm, reader::Reader};
|
||||
|
||||
use super::{PublicKey, PublicKeyError, SSH_RSA};
|
||||
use super::{PublicKey, SSH_RSA};
|
||||
|
||||
pub struct RsaPublicKey {
|
||||
e: Vec<u8>,
|
||||
|
@ -16,7 +16,7 @@ struct RsaAsn1<'a> {
|
|||
}
|
||||
|
||||
impl PublicKey for RsaPublicKey {
|
||||
fn from_openssh(key: &[u8]) -> Result<Self, PublicKeyError>
|
||||
fn from_openssh(key: &[u8]) -> Result<Self, ZNSError>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
|
@ -34,19 +34,19 @@ impl PublicKey for RsaPublicKey {
|
|||
data: &[u8],
|
||||
signature: &[u8],
|
||||
algorithm: &Algorithm,
|
||||
) -> Result<bool, PublicKeyError> {
|
||||
) -> Result<bool, ZNSError> {
|
||||
let result = asn1::write_single(&RsaAsn1 {
|
||||
n: asn1::BigInt::new(&self.n),
|
||||
e: asn1::BigInt::new(&self.e),
|
||||
})
|
||||
.map_err(|e| PublicKeyError {
|
||||
.map_err(|e| ZNSError::PublicKey {
|
||||
message: format!("Verify Error: {}", e),
|
||||
})?;
|
||||
|
||||
let signature_type = match algorithm {
|
||||
Algorithm::RSASHA512 => Ok(&signature::RSA_PKCS1_2048_8192_SHA512),
|
||||
Algorithm::RSASHA256 => Ok(&signature::RSA_PKCS1_2048_8192_SHA256),
|
||||
_ => Err(PublicKeyError {
|
||||
_ => Err(ZNSError::PublicKey {
|
||||
message: format!("RsaPublicKey: invalid verify algorithm",),
|
||||
}),
|
||||
}?;
|
||||
|
@ -56,7 +56,7 @@ impl PublicKey for RsaPublicKey {
|
|||
Ok(pkey.verify(data, signature).is_ok())
|
||||
}
|
||||
|
||||
fn from_dnskey(key: &[u8]) -> Result<Self, PublicKeyError>
|
||||
fn from_dnskey(key: &[u8]) -> Result<Self, ZNSError>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
|
|
|
@ -2,7 +2,7 @@ use base64::prelude::*;
|
|||
use int_enum::IntEnum;
|
||||
|
||||
use crate::{
|
||||
errors::ParseError,
|
||||
errors::ZNSError,
|
||||
parser::FromBytes,
|
||||
reader::Reader,
|
||||
structs::{LabelString, RR},
|
||||
|
@ -10,7 +10,7 @@ use crate::{
|
|||
|
||||
use super::{
|
||||
dnskey::DNSKeyRData,
|
||||
pubkeys::{Ed25519PublicKey, PublicKey, PublicKeyError, RsaPublicKey, SSH_ED25519, SSH_RSA},
|
||||
pubkeys::{Ed25519PublicKey, PublicKey, RsaPublicKey, SSH_ED25519, SSH_RSA},
|
||||
};
|
||||
|
||||
pub struct Sig {
|
||||
|
@ -41,9 +41,8 @@ pub enum Algorithm {
|
|||
}
|
||||
|
||||
impl Algorithm {
|
||||
pub fn from(value: u8) -> Result<Self, ParseError> {
|
||||
Algorithm::try_from(value).map_err(|a| ParseError {
|
||||
// TODO: Should respond with error code refused or notimpl
|
||||
pub fn from(value: u8) -> Result<Self, ZNSError> {
|
||||
Algorithm::try_from(value).map_err(|a| ZNSError::NotImp {
|
||||
object: String::from("Algorithm"),
|
||||
message: format!("Usupported algorithm: {}", a),
|
||||
})
|
||||
|
@ -51,9 +50,9 @@ impl Algorithm {
|
|||
}
|
||||
|
||||
impl FromBytes for SigRData {
|
||||
fn from_bytes(reader: &mut Reader) -> Result<Self, ParseError> {
|
||||
fn from_bytes(reader: &mut Reader) -> Result<Self, ZNSError> {
|
||||
if reader.unread_bytes() < 18 {
|
||||
Err(ParseError {
|
||||
Err(ZNSError::Parse {
|
||||
object: String::from("KeyRData"),
|
||||
message: String::from("invalid rdata"),
|
||||
})
|
||||
|
@ -74,7 +73,7 @@ impl FromBytes for SigRData {
|
|||
}
|
||||
|
||||
impl Sig {
|
||||
pub fn new(rr: &RR, datagram: &[u8]) -> Result<Self, ParseError> {
|
||||
pub fn new(rr: &RR, datagram: &[u8]) -> Result<Self, ZNSError> {
|
||||
let mut request = datagram[0..datagram.len() - 11 - rr.rdlength as usize].to_vec();
|
||||
request[11] -= 1; // Decrease arcount
|
||||
|
||||
|
@ -90,7 +89,7 @@ impl Sig {
|
|||
})
|
||||
}
|
||||
|
||||
fn verify(&self, key: impl PublicKey) -> Result<bool, PublicKeyError> {
|
||||
fn verify(&self, key: impl PublicKey) -> Result<bool, ZNSError> {
|
||||
key.verify(
|
||||
&self.raw_data,
|
||||
&self.key_rdata.signature,
|
||||
|
@ -98,7 +97,7 @@ impl Sig {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn verify_ssh(&self, key: &str) -> Result<bool, PublicKeyError> {
|
||||
pub fn verify_ssh(&self, key: &str) -> Result<bool, ZNSError> {
|
||||
let key_split: Vec<&str> = key.split_ascii_whitespace().collect();
|
||||
let bin = BASE64_STANDARD.decode(key_split[1]).unwrap();
|
||||
|
||||
|
@ -111,7 +110,7 @@ impl Sig {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn verify_dnskey(&self, key: DNSKeyRData) -> Result<bool, PublicKeyError> {
|
||||
pub fn verify_dnskey(&self, key: DNSKeyRData) -> Result<bool, ZNSError> {
|
||||
if self.key_rdata.algo != key.algorithm {
|
||||
Ok(false)
|
||||
} else {
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
use std::{mem::size_of, vec};
|
||||
use std::mem::size_of;
|
||||
|
||||
use crate::{
|
||||
errors::ParseError,
|
||||
errors::ZNSError,
|
||||
reader::Reader,
|
||||
structs::{Class, Header, LabelString, Message, Opcode, Question, RRClass, RRType, Type, RR},
|
||||
};
|
||||
|
||||
type Result<T> = std::result::Result<T, ParseError>;
|
||||
type Result<T> = std::result::Result<T, ZNSError>;
|
||||
|
||||
impl From<Type> for u16 {
|
||||
fn from(value: Type) -> Self {
|
||||
|
@ -83,7 +83,7 @@ pub trait ToBytes {
|
|||
impl FromBytes for Header {
|
||||
fn from_bytes(reader: &mut Reader) -> Result<Self> {
|
||||
if reader.unread_bytes() < size_of::<Header>() {
|
||||
Err(ParseError {
|
||||
Err(ZNSError::Parse {
|
||||
object: String::from("Header"),
|
||||
message: String::from("Size of Header does not match"),
|
||||
})
|
||||
|
@ -124,7 +124,7 @@ impl FromBytes for LabelString {
|
|||
while code != 0 && (code & 0b11000000 == 0) && reader.unread_bytes() > code as usize {
|
||||
out.push(
|
||||
String::from_utf8(reader.read(code as usize)?.to_vec()).map_err(|e| {
|
||||
ParseError {
|
||||
ZNSError::Parse {
|
||||
object: String::from("Label"),
|
||||
message: e.to_string(),
|
||||
}
|
||||
|
@ -159,7 +159,7 @@ impl FromBytes for Question {
|
|||
fn from_bytes(reader: &mut Reader) -> Result<Self> {
|
||||
// 16 for length octet + zero length octet
|
||||
if reader.unread_bytes() < 2 + size_of::<Class>() + size_of::<Type>() {
|
||||
Err(ParseError {
|
||||
Err(ZNSError::Parse {
|
||||
object: String::from("Question"),
|
||||
message: String::from("len of bytes smaller then minimum size"),
|
||||
})
|
||||
|
@ -167,7 +167,7 @@ impl FromBytes for Question {
|
|||
let qname = LabelString::from_bytes(reader)?;
|
||||
|
||||
if reader.unread_bytes() < 4 {
|
||||
Err(ParseError {
|
||||
Err(ZNSError::Parse {
|
||||
object: String::from("Question"),
|
||||
message: String::from("len of rest bytes smaller then minimum size"),
|
||||
})
|
||||
|
@ -201,7 +201,7 @@ impl FromBytes for RR {
|
|||
fn from_bytes(reader: &mut Reader) -> Result<Self> {
|
||||
let name = LabelString::from_bytes(reader)?;
|
||||
if reader.unread_bytes() < size_of::<Type>() + size_of::<Class>() + 6 {
|
||||
Err(ParseError {
|
||||
Err(ZNSError::Parse {
|
||||
object: String::from("RR"),
|
||||
message: String::from("len of rest of bytes smaller then minimum size"),
|
||||
})
|
||||
|
@ -211,7 +211,7 @@ impl FromBytes for RR {
|
|||
let ttl = reader.read_i32()?;
|
||||
let rdlength = reader.read_u16()?;
|
||||
if reader.unread_bytes() < rdlength as usize {
|
||||
Err(ParseError {
|
||||
Err(ZNSError::Parse {
|
||||
object: String::from("RR"),
|
||||
message: String::from("len of rest of bytes not equal to rdlength"),
|
||||
})
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
use std::array::TryFromSliceError;
|
||||
|
||||
use crate::errors::ReaderError;
|
||||
use crate::errors::ZNSError;
|
||||
|
||||
pub struct Reader<'a> {
|
||||
buffer: &'a [u8],
|
||||
position: usize,
|
||||
}
|
||||
|
||||
type Result<T> = std::result::Result<T, ReaderError>;
|
||||
type Result<T> = std::result::Result<T, ZNSError>;
|
||||
|
||||
impl<'a> Reader<'a> {
|
||||
pub fn new(buffer: &[u8]) -> Reader {
|
||||
|
@ -23,7 +23,7 @@ impl<'a> Reader<'a> {
|
|||
|
||||
pub fn read(&mut self, size: usize) -> Result<Vec<u8>> {
|
||||
if size > self.unread_bytes() {
|
||||
Err(ReaderError {
|
||||
Err(ZNSError::Reader {
|
||||
message: String::from("cannot read enough bytes"),
|
||||
})
|
||||
} else {
|
||||
|
@ -41,7 +41,7 @@ impl<'a> Reader<'a> {
|
|||
let result = u16::from_be_bytes(
|
||||
self.buffer[self.position..self.position + 2]
|
||||
.try_into()
|
||||
.map_err(|e: TryFromSliceError| ReaderError {
|
||||
.map_err(|e: TryFromSliceError| ZNSError::Reader {
|
||||
message: e.to_string(),
|
||||
})?,
|
||||
);
|
||||
|
@ -53,7 +53,7 @@ impl<'a> Reader<'a> {
|
|||
let result = i32::from_be_bytes(
|
||||
self.buffer[self.position..self.position + 4]
|
||||
.try_into()
|
||||
.map_err(|e: TryFromSliceError| ReaderError {
|
||||
.map_err(|e: TryFromSliceError| ZNSError::Reader {
|
||||
message: e.to_string(),
|
||||
})?,
|
||||
);
|
||||
|
@ -65,7 +65,7 @@ impl<'a> Reader<'a> {
|
|||
let result = u32::from_be_bytes(
|
||||
self.buffer[self.position..self.position + 4]
|
||||
.try_into()
|
||||
.map_err(|e: TryFromSliceError| ReaderError {
|
||||
.map_err(|e: TryFromSliceError| ZNSError::Reader {
|
||||
message: e.to_string(),
|
||||
})?,
|
||||
);
|
||||
|
@ -75,7 +75,7 @@ impl<'a> Reader<'a> {
|
|||
|
||||
pub fn seek(&self, position: usize) -> Result<Self> {
|
||||
if position >= self.position {
|
||||
Err(ReaderError {
|
||||
Err(ZNSError::Reader {
|
||||
message: String::from("Seeking into the future is not allowed!!"),
|
||||
})
|
||||
} else {
|
||||
|
|
|
@ -4,7 +4,7 @@ use std::sync::Arc;
|
|||
|
||||
use tokio::net::UdpSocket;
|
||||
|
||||
use crate::errors::ParseError;
|
||||
use crate::errors::ZNSError;
|
||||
use crate::handlers::{Handler, ResponseHandler};
|
||||
use crate::parser::{FromBytes, ToBytes};
|
||||
use crate::reader::Reader;
|
||||
|
@ -12,7 +12,7 @@ use crate::structs::{Header, Message, RCODE};
|
|||
|
||||
const MAX_DATAGRAM_SIZE: usize = 4096;
|
||||
|
||||
fn handle_parse_error(bytes: &[u8], err: ParseError) -> Message {
|
||||
fn handle_parse_error(bytes: &[u8], err: ZNSError) -> Message {
|
||||
eprintln!("{}", err);
|
||||
let mut reader = Reader::new(bytes);
|
||||
let mut header = Header::from_bytes(&mut reader).unwrap_or(Header {
|
||||
|
@ -50,7 +50,7 @@ async fn get_response(bytes: &[u8]) -> Message {
|
|||
}
|
||||
Err(e) => {
|
||||
eprintln!("{}", e.to_string());
|
||||
message.set_response(e.rcode);
|
||||
message.set_response(e.rcode());
|
||||
message
|
||||
}
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue