#include "base64.hh"
#include "validate-recursor.hh"
#include "threadname.hh"
+#include "iputils.hh"
+#include "bridge.hh"
::rust::Vec<::rust::String> pdns::settings::rec::getStrings(const std::string& name)
{
return false;
}
}
+
+namespace pdns::rust::web::rec
+{
+NetmaskGroup::NetmaskGroup(const ::NetmaskGroup& arg) :
+ d_ptr(std::make_unique<::NetmaskGroup>(arg))
+{
+}
+NetmaskGroup::~NetmaskGroup() = default;
+
+
+ComboAddress::ComboAddress(const ::ComboAddress& arg) :
+ d_ptr(std::make_unique<::ComboAddress>(arg))
+{
+}
+ComboAddress::~ComboAddress() = default;
+
+std::unique_ptr<ComboAddress> comboaddress(::rust::Str str)
+{
+ return std::make_unique<ComboAddress>(::ComboAddress(std::string(str)));
+}
+
+[[nodiscard]] const ::NetmaskGroup& NetmaskGroup::get() const
+{
+ return *d_ptr;
+}
+
+[[nodiscard]] const ::ComboAddress& ComboAddress::get() const
+{
+ return *d_ptr;
+}
+
+bool matches(const std::unique_ptr<NetmaskGroup>& nmg, const std::unique_ptr<ComboAddress>& address)
+{
+ return nmg->get().match(address->get());
+}
+}
// .file("src/source.cc") Code callable from Rust is in ../cxxsupport.cc
.flag_if_supported("-std=c++17")
.flag("-Isrc")
+ .flag("-I../../..")
.compile("settings");
}
#pragma once
#include "rust/cxx.h"
-#include "../../../credentials.hh"
-
+#include "credentials.hh"
namespace pdns::rust::settings::rec
{
void setThreadName(::rust::Str str);
}
+class NetmaskGroup;
+union ComboAddress;
+
namespace pdns::rust::web::rec
{
using CredentialsHolder = ::CredentialsHolder;
+ //using NetmaskGroup = ::NetmaskGroup;
struct KeyValue;
struct Request;
struct Response;
+class NetmaskGroup
+{
+public:
+ NetmaskGroup(const ::NetmaskGroup& arg);
+ ~NetmaskGroup();
+ [[nodiscard]] const ::NetmaskGroup& get() const;
+private:
+ std::unique_ptr<::NetmaskGroup> d_ptr;
+};
+class ComboAddress
+{
+public:
+ ComboAddress(const ::ComboAddress& arg);
+ ~ComboAddress();
+ [[nodiscard]] const ::ComboAddress& get() const;
+private:
+ std::unique_ptr<::ComboAddress> d_ptr;
+};
+
void apiServer(const Request& rustRequest, Response& rustResponse);
void apiDiscovery(const Request& rustRequest, Response& rustResponse);
void apiDiscoveryV1(const Request& rustRequest, Response& rustResponse);
void apiServerZoneDetailGET(const Request& rustRequest, Response& rustResponse);
void apiServerZoneDetailPUT(const Request& rustRequest, Response& rustResponse);
void apiServerZoneDetailDELETE(const Request& rustRequest, Response& rustResponse);
+std::unique_ptr<pdns::rust::web::rec::ComboAddress> comboaddress(::rust::Str str);
+bool matches(const std::unique_ptr<NetmaskGroup>& nmg, const std::unique_ptr<ComboAddress>& address);
}
urls: Vec<String>,
password_ch: cxx::UniquePtr<rustweb::CredentialsHolder>,
api_ch: cxx::UniquePtr<rustweb::CredentialsHolder>,
+ acl: cxx::UniquePtr<rustweb::NetmaskGroup>,
counter: Mutex<u32>,
}
// We start a loop to continuously accept incoming connections
loop {
let ctx = Arc::clone(&ctx);
- let ctx2 = Arc::clone(&ctx);
let (stream, _) = listener.accept().await?;
+ match stream.peer_addr() {
+ Ok(address) => {
+ eprintln!("Peer: {:?}", address);
+ let combo = rustweb::comboaddress(&address.to_string());
+ if !rustweb::matches(&ctx.acl, &combo) {
+ eprintln!("No acl match! {:?}", address);
+ continue;
+ }
+ }
+ Err(err) => {
+ eprintln!("Can't get: {:?}", err);
+ continue; // If we can't determine the peer address, don't
+ }
+ }
// Use an adapter to access something implementing `tokio::io` traits as if they implement
// `hyper::rt` IO traits.
let io = TokioIo::new(stream);
}
}
-pub fn serveweb(addresses: &Vec<String>, urls: &[String], password_ch: cxx::UniquePtr<rustweb::CredentialsHolder>, api_ch: cxx::UniquePtr<rustweb::CredentialsHolder>) -> Result<(), std::io::Error> {
+pub fn serveweb(addresses: &Vec<String>, urls: &[String], password_ch: cxx::UniquePtr<rustweb::CredentialsHolder>, api_ch: cxx::UniquePtr<rustweb::CredentialsHolder>, acl: cxx::UniquePtr<rustweb::NetmaskGroup>) -> Result<(), std::io::Error> {
// Context (R/O for now)
let ctx = Arc::new(Context {
urls: urls.to_vec(),
password_ch,
api_ch,
+ acl,
counter: Mutex::new(0),
});
unsafe impl Send for rustweb::CredentialsHolder {}
unsafe impl Sync for rustweb::CredentialsHolder {}
+unsafe impl Send for rustweb::NetmaskGroup {}
+unsafe impl Sync for rustweb::NetmaskGroup {}
#[cxx::bridge(namespace = "pdns::rust::web::rec")]
mod rustweb {
extern "C++" {
- type CredentialsHolder;
+ type CredentialsHolder;
+ type NetmaskGroup;
+ type ComboAddress;
}
/*
* Functions callable from C++
*/
extern "Rust" {
- fn serveweb(addreses: &Vec<String>, urls: &[String], pwch: UniquePtr<CredentialsHolder>, apikeych: UniquePtr<CredentialsHolder>) -> Result<()>;
+ fn serveweb(addreses: &Vec<String>, urls: &[String], pwch: UniquePtr<CredentialsHolder>, apikeych: UniquePtr<CredentialsHolder>, acl: UniquePtr<NetmaskGroup>) -> Result<()>;
}
struct KeyValue {
fn serveStuff(request: &Request, response: &mut Response) -> Result<()>;
fn matches(self: &CredentialsHolder, str: &CxxString) -> bool;
+ fn comboaddress(address: &str) -> UniquePtr<ComboAddress>;
+ fn matches(nmg: &UniquePtr<NetmaskGroup>, address: &UniquePtr<ComboAddress>) -> bool; // match is a keyword
}
}
#include "tcpiohandler.hh"
#include "rec-main.hh"
#include "settings/cxxsettings.hh" // IWYU pragma: keep, needed by included generated file
+#include "settings/rust/src/bridge.hh"
#include "settings/rust/web.rs.h"
using json11::Json;
if (!apikeyString.empty()) {
apikey = std::make_unique<CredentialsHolder>(std::move(apikeyString), arg().mustDo("webserver-hash-plaintext-credentials"));
}
- pdns::rust::web::rec::serveweb({::rust::String(address.toStringWithPort())}, ::rust::Slice<const ::rust::String>{urls.data(), urls.size()}, std::move(password), std::move(apikey));
+ NetmaskGroup acl;
+ acl.toMasks(::arg()["webserver-allow-from"]);
+ auto aclPtr = std::make_unique<pdns::rust::web::rec::NetmaskGroup>(acl);
+
+ pdns::rust::web::rec::serveweb({::rust::String(address.toStringWithPort())}, ::rust::Slice<const ::rust::String>{urls.data(), urls.size()}, std::move(password), std::move(apikey), std::move(aclPtr));
}
static void fromCxxToRust(const HttpResponse& cxxresp, pdns::rust::web::rec::Response& rustResponse)