Skip to content

Commit

Permalink
Respond with fixed SOA of zones
Browse files Browse the repository at this point in the history
  • Loading branch information
xerbalind committed Sep 25, 2024
1 parent 4939d2b commit c9767db
Show file tree
Hide file tree
Showing 13 changed files with 209 additions and 95 deletions.
9 changes: 3 additions & 6 deletions zns-daemon/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
use std::{env, net::IpAddr, sync::OnceLock};

use dotenvy::dotenv;
use zns::labelstring::LabelString;

static CONFIG: OnceLock<Config> = OnceLock::new();

pub struct Config {
pub zauth_url: String,
pub db_uri: String,
pub authoritative_zone: Vec<String>,
pub authoritative_zone: LabelString,
pub port: u16,
pub address: IpAddr,
}
Expand All @@ -25,11 +26,7 @@ impl Config {
Config {
db_uri: env::var("DATABASE_URL").expect("DATABASE_URL must be set"),
zauth_url: env::var("ZAUTH_URL").expect("ZAUTH_URL must be set"),
authoritative_zone: env::var("ZONE")
.expect("ZONE must be set")
.split('.')
.map(str::to_string)
.collect(),
authoritative_zone: LabelString::from(&env::var("ZONE").expect("ZONE must be set")),
port: env::var("ZNS_PORT")
.map(|v| v.parse::<u16>().expect("ZNS_PORT is invalid"))
.unwrap_or(5333),
Expand Down
13 changes: 7 additions & 6 deletions zns-daemon/src/db/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use diesel::prelude::*;
use diesel::sql_types::Text;
use zns::{
errors::ZNSError,
labelstring::LabelString,
structs::{Class, Type, RR},
};

Expand Down Expand Up @@ -103,7 +104,7 @@ pub fn insert_into_database(rr: &RR, connection: &mut PgConnection) -> Result<()
}

let record = Record {
name: rr.name.join("."),
name: rr.name.to_string(),
_type: rr._type.clone().into(),
class: rr.class.clone().into(),
ttl: rr.ttl,
Expand All @@ -119,14 +120,14 @@ pub fn insert_into_database(rr: &RR, connection: &mut PgConnection) -> Result<()
}

pub fn get_from_database(
name: &[String],
name: &LabelString,
_type: Option<Type>,
class: Class,
connection: &mut PgConnection,
) -> Result<Vec<RR>, ZNSError> {
let records = Record::get(
connection,
name.join("."),
name.to_string(),
_type.map(|t| t.into()),
class.into(),
)
Expand All @@ -137,7 +138,7 @@ pub fn get_from_database(
Ok(records
.into_iter()
.map(|record| RR {
name: record.name.split('.').map(str::to_string).collect(),
name: LabelString::from(&record.name),
_type: Type::from(record._type as u16),
class: Class::from(record.class as u16),
ttl: record.ttl,
Expand All @@ -149,15 +150,15 @@ pub fn get_from_database(

//TODO: cleanup models
pub fn delete_from_database(
name: &[String],
name: &LabelString,
_type: Option<Type>,
class: Class,
rdata: Option<Vec<u8>>,
connection: &mut PgConnection,
) {
let _ = Record::delete(
connection,
name.join("."),
name.to_string(),
_type.map(|f| f.into()),
class.into(),
rdata,
Expand Down
65 changes: 56 additions & 9 deletions zns-daemon/src/handlers/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ use diesel::PgConnection;

use zns::{
errors::ZNSError,
structs::{Message, Question, RR},
labelstring::LabelString,
parser::ToBytes,
structs::{Class, Message, Question, RRClass, RRType, SoaRData, Type, RR},
};

use crate::{config::Config, db::models::get_from_database};
Expand Down Expand Up @@ -35,10 +37,14 @@ impl ResponseHandler for QueryHandler {
if rrs.is_empty() {
rrs.extend(try_wildcard(question, connection)?);
if rrs.is_empty() {
return Err(ZNSError::NXDomain {
domain: question.qname.join("."),
qtype: question.qtype.clone(),
});
if question.qtype == Type::Type(RRType::SOA) {
rrs.extend([get_soa(&question.qname)?])
} else {
return Err(ZNSError::NXDomain {
domain: question.qname.to_string(),
qtype: question.qtype.clone(),
});
}
}
}
response.header.ancount += rrs.len() as u16;
Expand All @@ -59,13 +65,13 @@ impl ResponseHandler for QueryHandler {
fn try_wildcard(question: &Question, connection: &mut PgConnection) -> Result<Vec<RR>, ZNSError> {
let records = get_from_database(&question.qname, None, question.qclass.clone(), connection)?;

if !records.is_empty() || question.qname.is_empty() {
if !records.is_empty() || question.qname.as_slice().is_empty() {
Ok(vec![])
} else {
let mut qname = question.qname.clone();
qname[0] = String::from("*");
let qname = question.qname.clone().to_vec();
qname.to_vec()[0] = String::from("*");
Ok(get_from_database(
&qname,
&qname.into(),
Some(question.qtype.clone()),
question.qclass.clone(),
connection,
Expand All @@ -79,6 +85,47 @@ fn try_wildcard(question: &Question, connection: &mut PgConnection) -> Result<Ve
}
}

fn get_soa(name: &LabelString) -> Result<RR, ZNSError> {
let auth_zone = Config::get().authoritative_zone.clone();
let rdata = if &Config::get().authoritative_zone == name {
// Recommended values taken from wikipedia: https://en.wikipedia.org/wiki/SOA_record
Ok(SoaRData {
mname: auth_zone,
rname: LabelString::from("admin.zeus.ugent.be"),
serial: 1,
refresh: 86400,
retry: 7200,
expire: 3600000,
minimum: 172800,
})
} else if name.len() > auth_zone.len() {
let zone: LabelString = name.as_slice()[name.len() - auth_zone.len() - 1..].into();
Ok(SoaRData {
mname: zone.clone(),
rname: LabelString::from(&format!("{}.zeus.ugent.be", zone.as_slice()[0])),
serial: 1,
refresh: 86400,
retry: 7200,
expire: 3600000,
minimum: 172800,
})
} else {
Err(ZNSError::NXDomain {
domain: name.to_string(),
qtype: Type::Type(RRType::SOA),
})
}?;

Ok(RR {
name: name.to_owned(),
_type: Type::Type(RRType::SOA),
class: Class::Class(RRClass::IN),
ttl: 11200,
rdlength: 0,
rdata: SoaRData::to_bytes(rdata),
})
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
10 changes: 6 additions & 4 deletions zns-daemon/src/handlers/update/authenticate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ use crate::{config::Config, db::models::get_from_database};

use zns::{
errors::ZNSError,
labelstring::LabelString,
parser::FromBytes,
reader::Reader,
structs::{Class, LabelString, RRClass, RRType, Type},
structs::{Class, RRClass, RRType, Type},
};

use super::{dnskey::DNSKeyRData, sig::Sig};
Expand All @@ -17,8 +18,9 @@ pub async fn authenticate(
zone: &LabelString,
connection: &mut PgConnection,
) -> Result<bool, ZNSError> {
if zone.len() > Config::get().authoritative_zone.len() {
let username = &zone[zone.len() - Config::get().authoritative_zone.len() - 1];
if zone.as_slice().len() > Config::get().authoritative_zone.as_slice().len() {
let username = &zone.as_slice()
[zone.as_slice().len() - Config::get().authoritative_zone.as_slice().len() - 1];

let ssh_verified = validate_ssh(&username.to_lowercase(), sig)
.await
Expand Down Expand Up @@ -62,7 +64,7 @@ async fn validate_ssh(username: &String, sig: &Sig) -> Result<bool, reqwest::Err
}

async fn validate_dnskey(
zone: &[String],
zone: &LabelString,
sig: &Sig,
connection: &mut PgConnection,
) -> Result<bool, ZNSError> {
Expand Down
8 changes: 4 additions & 4 deletions zns-daemon/src/handlers/update/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use crate::{
db::models::{delete_from_database, insert_into_database},
};

use zns::errors::ZNSError;
use zns::structs::{Class, Message, RRClass, RRType, Type};
use zns::{errors::ZNSError, utils::labels_equal};

use self::sig::Sig;

Expand Down Expand Up @@ -41,7 +41,7 @@ impl ResponseHandler for UpdateHandler {
// Check Prerequisite TODO: implement this

let zone = &message.question[0];
let zlen = zone.qname.len();
let zlen = zone.qname.as_slice().len();

//TODO: this code is ugly
let last = message.additional.last();
Expand All @@ -61,10 +61,10 @@ impl ResponseHandler for UpdateHandler {

// Update Section Prescan
for rr in &message.authority {
let rlen = rr.name.len();
let rlen = rr.name.as_slice().len();

// Check if rr has same zone
if rlen < zlen || !(labels_equal(&zone.qname, &rr.name[rlen - zlen..].into())) {
if rlen < zlen || !(&zone.qname == &rr.name.as_slice()[rlen - zlen..].into()) {
return Err(ZNSError::Refused {
message: "RR has different zone from Question".to_string(),
});
Expand Down
5 changes: 1 addition & 4 deletions zns-daemon/src/handlers/update/sig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@ use base64::prelude::*;
use int_enum::IntEnum;

use zns::{
errors::ZNSError,
parser::FromBytes,
reader::Reader,
structs::{LabelString, RR},
errors::ZNSError, labelstring::LabelString, parser::FromBytes, reader::Reader, structs::RR,
};

use super::{
Expand Down
85 changes: 85 additions & 0 deletions zns/src/labelstring.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
use std::fmt::Display;


#[derive(Debug, Clone)]
pub struct LabelString(Vec<String>);

pub fn labels_equal(vec1: &LabelString, vec2: &LabelString) -> bool {
if vec1.as_slice().len() != vec2.as_slice().len() {
return false;
}

for (elem1, elem2) in vec1.as_slice().iter().zip(vec2.as_slice().iter()) {
if elem1.to_lowercase() != elem2.to_lowercase() {
return false;
}
}

true
}

impl LabelString {
pub fn from(string: &str) -> Self {
LabelString(string.split('.').map(str::to_string).collect())
}

pub fn as_slice(&self) -> &[String] {
self.0.as_slice()
}

pub fn to_vec(self) -> Vec<String> {
self.0
}

pub fn len(&self) -> usize {
self.0.len()
}

#[must_use]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}

impl PartialEq for LabelString {
fn eq(&self, other: &Self) -> bool {
labels_equal(self, other)
}
}

impl From<&[String]> for LabelString {
fn from(value: &[String]) -> Self {
LabelString(value.to_vec())
}
}

impl From<Vec<String>> for LabelString {
fn from(value: Vec<String>) -> Self {
LabelString(value)
}
}

impl Display for LabelString {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0.join("."))
}
}

#[cfg(test)]
mod tests {

use super::*;

#[test]
fn test_labels_equal() {
assert!(labels_equal(
&LabelString::from("one.two"),
&LabelString::from("oNE.two")
));

assert!(!labels_equal(
&LabelString::from("onne.two"),
&LabelString::from("oNEe.two")
));
}
}
2 changes: 1 addition & 1 deletion zns/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
pub mod errors;
pub mod labelstring;
pub mod message;
pub mod parser;
pub mod reader;
pub mod structs;

pub mod test_utils;
pub mod utils;
Loading

0 comments on commit c9767db

Please sign in to comment.