bool CredentialsHolder::matches(const std::string& password) const
{
- cerr << "matches " << d_isHashed << ' ' << password << ' ' << d_credentials.getString() << endl;
if (d_isHashed) {
- cerr << "Case 1" << endl;
return verifyPassword(d_credentials.getString(), d_salt, d_workFactor, d_parallelFactor, d_blockSize, password);
}
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
DNSName g_dns64PrefixReverse;
unsigned int g_maxChainLength;
LockGuarded<std::shared_ptr<SyncRes::domainmap_t>> g_initialDomainMap; // new threads needs this to be setup
-std::shared_ptr<NetmaskGroup> g_initialAllowFrom; // new thread needs to be setup with this
-std::shared_ptr<NetmaskGroup> g_initialAllowNotifyFrom; // new threads need this to be setup
-std::shared_ptr<notifyset_t> g_initialAllowNotifyFor; // new threads need this to be setup
+LockGuarded<std::shared_ptr<NetmaskGroup>> g_initialAllowFrom; // new thread needs to be setup with this
+LockGuarded<std::shared_ptr<NetmaskGroup>> g_initialAllowNotifyFrom; // new threads need this to be setup
+LockGuarded<std::shared_ptr<notifyset_t>> g_initialAllowNotifyFor; // new threads need this to be setup
bool g_logRPZChanges{false};
static time_t s_statisticsInterval;
static std::atomic<uint32_t> s_counter;
allowFrom = nullptr;
}
- g_initialAllowFrom = allowFrom;
+ *g_initialAllowFrom.lock() = allowFrom;
// coverity[copy_constructor_call] maybe this can be avoided, but be careful as pointers get passed to other threads
broadcastFunction([=] { return pleaseSupplantAllowFrom(allowFrom); });
auto allowNotifyFrom = parseACL("allow-notify-from-file", "allow-notify-from", log);
- g_initialAllowNotifyFrom = allowNotifyFrom;
+ *g_initialAllowNotifyFrom.lock() = allowNotifyFrom;
// coverity[copy_constructor_call] maybe this can be avoided, but be careful as pointers get passed to other threads
broadcastFunction([=] { return pleaseSupplantAllowNotifyFrom(allowNotifyFrom); });
}
g_networkTimeoutMsec = ::arg().asNum("network-timeout");
- std::tie(*g_initialDomainMap.lock(), g_initialAllowNotifyFor) = parseZoneConfiguration(g_yamlSettings);
+ std::tie(*g_initialDomainMap.lock(), *g_initialAllowNotifyFor.lock()) = parseZoneConfiguration(g_yamlSettings);
g_latencyStatSize = ::arg().asNum("latency-statistic-size");
{
SyncRes tmp(g_now); // make sure it allocates tsstorage before we do anything, like primeHints or so..
SyncRes::setDomainMap(*g_initialDomainMap.lock());
- t_allowFrom = g_initialAllowFrom;
- t_allowNotifyFrom = g_initialAllowNotifyFrom;
- t_allowNotifyFor = g_initialAllowNotifyFor;
+ t_allowFrom = *g_initialAllowFrom.lock();
+ t_allowNotifyFrom = *g_initialAllowNotifyFrom.lock();
+ t_allowNotifyFor = *g_initialAllowNotifyFor.lock();
t_udpclientsocks = std::make_unique<UDPClientSocks>();
t_tcpClientCounts = std::make_unique<tcpClientCounts_t>();
if (g_proxyMapping) {
extern int g_argc;
extern char** g_argv;
extern LockGuarded<std::shared_ptr<SyncRes::domainmap_t>> g_initialDomainMap; // new threads needs this to be setup
-extern std::shared_ptr<NetmaskGroup> g_initialAllowFrom; // new thread needs to be setup with this
-extern std::shared_ptr<NetmaskGroup> g_initialAllowNotifyFrom; // new threads need this to be setup
-extern std::shared_ptr<notifyset_t> g_initialAllowNotifyFor; // new threads need this to be setup
+extern LockGuarded<std::shared_ptr<NetmaskGroup>> g_initialAllowFrom; // new thread needs to be setup with this
+extern LockGuarded<std::shared_ptr<NetmaskGroup>> g_initialAllowNotifyFrom; // new threads need this to be setup
+extern LockGuarded<std::shared_ptr<notifyset_t>> g_initialAllowNotifyFor; // new threads need this to be setup
extern thread_local std::shared_ptr<Regex> t_traceRegex;
extern thread_local FDWrapper t_tracefd;
extern string g_programname;
}
extern LockGuarded<std::shared_ptr<SyncRes::domainmap_t>> g_initialDomainMap; // XXX
*g_initialDomainMap.lock() = newDomainMap;
+ extern LockGuarded<std::shared_ptr<notifyset_t>> g_initialAllowNotifyFor; // XXX
+ *g_initialAllowNotifyFor.lock() = newNotifySet;
return "ok\n";
}
catch (const std::exception& e) {
TODO
- Logging
-- Table based routing including OPTIONS request handling
- ACLs of webserver
-- ACL handling; thread local does not work, see how domains are done
- Authorization: metrics and plain files (and more?) are not subject to password auth
- Allow multipe listen addreses in settings (singlevalued right now)
- TLS?
if lcase.starts_with(b"basic ") {
let cookie = &authorization.as_bytes()[6..];
if let Ok(plain) = BASE64_STANDARD.decode(cookie) {
- println!("plain {:?}", plain);
let mut split = plain.split(|i| *i == b':');
- println!("split {:?}", split);
if split.next().is_some() {
- println!("split {:?}", split);
if let Some(split) = split.next() {
- println!("split {:?}", split);
cxx::let_cxx_string!(s = &split);
auth_ok = ctx.password_ch.as_ref().unwrap().matches(&s);
- println!("OK4 {}", auth_ok);
}
}
}
}
}
- println!("OK5 {}", auth_ok);
} else {
auth_ok = true;
}
// XXX AUDIT!
let mut auth_ok = false;
- println!("OK0 {}", auth_ok);
+
if let Some(api) = reqheaders.get("x-api-key") {
cxx::let_cxx_string!(s = &api.as_bytes());
auth_ok = ctx.api_ch.as_ref().unwrap().matches(&s);
- println!("OK1 {}", auth_ok);
}
if !auth_ok {
for kv in &request.vars {
cxx::let_cxx_string!(s = &kv.value);
if kv.key == "x-api-key" && ctx.api_ch.as_ref().unwrap().matches(&s) {
auth_ok = true;
- println!("OK2 {}", auth_ok);
break;
}
}
}
- println!("OK3 {}", auth_ok);
if !auth_ok && allow_password {
auth_ok = compare_authorization(ctx, reqheaders);
if !auth_ok {
vars: vec![],
parameters: vec![],
};
- println!("MATCH? {}", path);
matcher(&method, path, &mut apifunc, &mut rawfunc, &mut filefunc, &mut allow_password, &mut request);
if apifunc.is_some() || rawfunc.is_some() /* || filefunc.is_some() */ {
- println!("MATCH");
methods.push(method.to_string());
}
}
eprintln!("Error serving connection: {:?}", err);
}
});
- eprintln!("{}", ctx2.counter.lock().await);
}
}
{
// Return currently configured ACLs
vector<string> entries;
- if (t_allowFrom && aclType == "allow-from") {
- entries = t_allowFrom->toStringVector();
+ auto lock1 = g_initialAllowFrom.lock();
+ auto lock2 = g_initialAllowNotifyFrom.lock();
+ if (*lock1 && aclType == "allow-from") {
+ entries = (*lock1)->toStringVector();
}
- else if (t_allowNotifyFrom && aclType == "allow-notify-from") {
- entries = t_allowNotifyFrom->toStringVector();
+ else if (*lock2 && aclType == "allow-notify-from") {
+ entries = (*lock2)->toStringVector();
}
resp->setJsonBody(Json::object{
apiServerConfigACLPUT("allow-notify-from", req, resp);
}
+static bool isAllowedNotify(DNSName qname)
+{
+ auto lock = g_initialAllowNotifyFor.lock();
+
+ if (*lock == nullptr || (*lock)->empty()) {
+ return false;
+ }
+
+ do {
+ auto ret = (*lock)->find(qname);
+ if (ret != (*lock)->end()) {
+ return true;
+ }
+ } while (qname.chopOff());
+ return false;
+}
+
static void fillZone(const DNSName& zonename, HttpResponse* resp)
{
auto lock = g_initialDomainMap.lock();
{"kind", zone.d_servers.empty() ? "Native" : "Forwarded"},
{"servers", servers},
{"recursion_desired", zone.d_servers.empty() ? false : zone.d_rdForward},
- {"notify_allowed", isAllowNotifyForZone(zonename)},
+ {"notify_allowed", isAllowedNotify(zonename)},
{"records", records}};
resp->setJsonBody(doc);
throw ApiException("Query q can't be blank");
}
+ auto lock = g_initialDomainMap.lock();
Json::array doc;
- for (const SyncRes::domainmap_t::value_type& val : *SyncRes::t_sstorage.domainmap) {
+ for (const SyncRes::domainmap_t::value_type& val : **lock) {
string zoneId = apiZoneNameToId(val.first);
string zoneName = val.first.toString();
if (pdns_ci_find(zoneName, qVar) != string::npos) {