From: Fred Morcos Date: Tue, 12 Dec 2023 13:48:15 +0000 (+0100) Subject: Format ws-auth.cc X-Git-Tag: auth-4.9.0-alpha1~23^2~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=212f57b8e17fd45aa2ada6ebc5e04f16f2420c0b;p=thirdparty%2Fpdns.git Format ws-auth.cc --- diff --git a/.not-formatted b/.not-formatted index ef633d28a5..8c59a1ea66 100644 --- a/.not-formatted +++ b/.not-formatted @@ -299,7 +299,6 @@ ./pdns/webserver.hh ./pdns/ws-api.cc ./pdns/ws-api.hh -./pdns/ws-auth.cc ./pdns/xpf.cc ./pdns/xpf.hh ./pdns/zone2json.cc diff --git a/pdns/ws-auth.cc b/pdns/ws-auth.cc index 42a462fa36..4d2482cc0d 100644 --- a/pdns/ws-auth.cc +++ b/pdns/ws-auth.cc @@ -56,9 +56,9 @@ extern StatBag S; static void patchZone(UeberBackend& B, const DNSName& zonename, DomainInfo& di, HttpRequest* req, HttpResponse* resp); // QTypes that MUST NOT have multiple records of the same type in a given RRset. -static const std::set onlyOneEntryTypes = { QType::CNAME, QType::DNAME, QType::SOA }; +static const std::set onlyOneEntryTypes = {QType::CNAME, QType::DNAME, QType::SOA}; // QTypes that MUST NOT be used with any other QType on the same name. -static const std::set exclusiveEntryTypes = { QType::CNAME }; +static const std::set exclusiveEntryTypes = {QType::CNAME}; // QTypes that MUST be at apex. static const std::set atApexTypes = {QType::SOA, QType::DNSKEY}; // QTypes that are NOT allowed at apex. @@ -89,9 +89,9 @@ AuthWebServer::AuthWebServer() : void AuthWebServer::go() { S.doRings(); - std::thread webT([this](){webThread();}); + std::thread webT([this]() { webThread(); }); webT.detach(); - std::thread statT([this](){statThread();}); + std::thread statT([this]() { statThread(); }); statT.detach(); } @@ -99,7 +99,7 @@ void AuthWebServer::statThread() { try { setThreadName("pdns/statHelper"); - for(;;) { + for (;;) { d_queries.submit(S.read("udp-queries")); d_cachehits.submit(S.read("packetcache-hit")); d_cachemisses.submit(S.read("packetcache-miss")); @@ -108,15 +108,16 @@ void AuthWebServer::statThread() Utility::sleep(1); } } - catch(...) { - g_log< >ring=S.getRing(ringname); + int tot = 0; + int entries = 0; + vector> ring = S.getRing(ringname); - for(const auto & i : ring) { - tot+=i.second; + for (const auto& i : ring) { + tot += i.second; entries++; } - ret<<"
"; - ret<<"Reset"<"<"<"; - ret<<"Showing: Top "<"<Resize: "; - unsigned int sizes[]={10,100,500,1000,10000,500000,0}; - for(int i=0;sizes[i];++i) { - if(S.getRingSize(ringname)!=sizes[i]) - ret<<""< "; + ret << "
"; + ret << "Reset" << endl; + ret << "

" << title << "

" << endl; + ret << "
"; + ret << "Showing: Top " << limit << " of " << entries << "" << endl; + ret << "Resize: "; + unsigned int sizes[] = {10, 100, 500, 1000, 10000, 500000, 0}; + for (int i = 0; sizes[i]; ++i) { + if (S.getRingSize(ringname) != sizes[i]) + ret << "" << sizes[i] << " "; else - ret<<"("<
"; + ret << "
"; - ret<<""; - int printed=0; - int total=max(1,tot); - for(vector >::const_iterator i=ring.begin();limit && i!=ring.end();++i,--limit) { - ret<<""<second; + ret << "
"<first)<<""<second<<""<< AuthWebServer::makePercentage(i->second*100.0/total)<<"
"; + int printed = 0; + int total = max(1, tot); + for (vector>::const_iterator i = ring.begin(); limit && i != ring.end(); ++i, --limit) { + ret << "" << endl; + printed += i->second; } - ret<<""<"<" << endl; + if (printed != tot) + ret << "" << endl; - ret<<""; - ret<<"
" << htmlescape(i->first) << "" << i->second << "" << AuthWebServer::makePercentage(i->second * 100.0 / total) << "
Rest:"<"<< AuthWebServer::makePercentage((tot-printed)*100.0/total)<<"
Rest:" << tot - printed << "" << AuthWebServer::makePercentage((tot - printed) * 100.0 / total) << "
Total:"<100%
"<Total:" << tot << "100%"; + ret << "" << endl; } -void AuthWebServer::printvars(ostringstream &ret) +void AuthWebServer::printvars(ostringstream& ret) { - ret<<"

Variables

"<

Variables

" << endl; - vectorentries=S.getEntries(); - for(const auto & entry : entries) { - ret<<"" << endl; } - ret<<"
"<"<"<"< entries = S.getEntries(); + for (const auto& entry : entries) { + ret << "
" << entry << "" << S.read(entry) << "" << S.getDescrip(entry) << "
"<" << endl; } -void AuthWebServer::printargs(ostringstream &ret) +void AuthWebServer::printargs(ostringstream& ret) { - ret<Arguments)"<Arguments)" << endl; - vectorentries=arg().list(); - for(const auto & entry : entries) { - ret<<""<"<"<"< entries = arg().list(); + for (const auto& entry : entries) { + ret << "" << entry << "" << arg()[entry] << "" << arg().getHelp(entry) << "" << endl; } } @@ -207,15 +208,15 @@ string AuthWebServer::makePercentage(const double& val) void AuthWebServer::indexfunction(HttpRequest* req, HttpResponse* resp) { - if(!req->getvars["resetring"].empty()) { + if (!req->getvars["resetring"].empty()) { if (S.ringExists(req->getvars["resetring"])) S.resetRing(req->getvars["resetring"]); resp->status = 302; resp->headers["Location"] = req->url.path; return; } - if(!req->getvars["resizering"].empty()){ - int size=std::stoi(req->getvars["size"]); + if (!req->getvars["resizering"].empty()) { + int size = std::stoi(req->getvars["size"]); if (S.ringExists(req->getvars["resizering"]) && size > 0 && size <= 500000) S.resizeRing(req->getvars["resizering"], std::stoi(req->getvars["size"])); resp->status = 302; @@ -225,94 +226,80 @@ void AuthWebServer::indexfunction(HttpRequest* req, HttpResponse* resp) ostringstream ret; - ret<<""<"<PowerDNS Authoritative Server Monitor"<)"<"<"<"; - ret<PowerDNS )"<"<"; - ret<
)"; - - time_t passed=time(nullptr)-g_starttime; - - ret<<"

Uptime: "<< - humanDuration(passed)<< - "
"<"<0) - ret<<"Cache hitrate, 1, 5, 10 minute averages: "<< - makePercentage((d_cachehits.get1()*100.0)/((d_cachehits.get1())+(d_cachemisses.get1())))<<", "<< - makePercentage((d_cachehits.get5()*100.0)/((d_cachehits.get5())+(d_cachemisses.get5())))<<", "<< - makePercentage((d_cachehits.get10()*100.0)/((d_cachehits.get10())+(d_cachemisses.get10())))<< - "
"<0) - ret<<"Backend query cache hitrate, 1, 5, 10 minute averages: "<"<"<
"<getvars["ring"].empty()) { + ret << "" << endl; + ret << "" << endl; + ret << "PowerDNS Authoritative Server Monitor" << endl; + ret << R"()" << endl; + ret << "" << endl; + + ret << "

"; + ret << R"(
)"; + + time_t passed = time(nullptr) - g_starttime; + + ret << "

Uptime: " << humanDuration(passed) << "
" << endl; + + ret << "Queries/second, 1, 5, 10 minute averages: " << std::setprecision(3) << (int)d_queries.get1() << ", " << (int)d_queries.get5() << ", " << (int)d_queries.get10() << ". Max queries/second: " << (int)d_queries.getMax() << "
" << endl; + + if (d_cachemisses.get10() + d_cachehits.get10() > 0) + ret << "Cache hitrate, 1, 5, 10 minute averages: " << makePercentage((d_cachehits.get1() * 100.0) / ((d_cachehits.get1()) + (d_cachemisses.get1()))) << ", " << makePercentage((d_cachehits.get5() * 100.0) / ((d_cachehits.get5()) + (d_cachemisses.get5()))) << ", " << makePercentage((d_cachehits.get10() * 100.0) / ((d_cachehits.get10()) + (d_cachemisses.get10()))) << "
" << endl; + + if (d_qcachemisses.get10() + d_qcachehits.get10() > 0) + ret << "Backend query cache hitrate, 1, 5, 10 minute averages: " << std::setprecision(2) << makePercentage((d_qcachehits.get1() * 100.0) / ((d_qcachehits.get1()) + (d_qcachemisses.get1()))) << ", " << makePercentage((d_qcachehits.get5() * 100.0) / ((d_qcachehits.get5()) + (d_qcachemisses.get5()))) << ", " << makePercentage((d_qcachehits.get10() * 100.0) / ((d_qcachehits.get10()) + (d_qcachemisses.get10()))) << "
" << endl; + + ret << "Backend query load, 1, 5, 10 minute averages: " << std::setprecision(3) << (int)d_qcachemisses.get1() << ", " << (int)d_qcachemisses.get5() << ", " << (int)d_qcachemisses.get10() << ". Max queries/second: " << (int)d_qcachemisses.getMax() << "
" << endl; + + ret << "Total queries: " << S.read("udp-queries") << ". Question/answer latency: " << S.read("latency") / 1000.0 << "ms


" << endl; + if (req->getvars["ring"].empty()) { auto entries = S.listRings(); - for(const auto &i: entries) { + for (const auto& i : entries) { printtable(ret, i, S.getRingTitle(i)); } printvars(ret); - if(arg().mustDo("webserver-print-arguments")) + if (arg().mustDo("webserver-print-arguments")) printargs(ret); } - else if(S.ringExists(req->getvars["ring"])) - printtable(ret,req->getvars["ring"],S.getRingTitle(req->getvars["ring"]),100); + else if (S.ringExists(req->getvars["ring"])) + printtable(ret, req->getvars["ring"], S.getRingTitle(req->getvars["ring"]), 100); - ret<<"
"<"<© PowerDNS.COM BV."<"<
" << endl; + ret << "" << endl; + ret << "" << endl; resp->body = ret.str(); resp->status = 200; } /** Helper to build a record content as needed. */ -static inline string makeRecordContent(const QType& qtype, const string& content, bool noDot) { +static inline string makeRecordContent(const QType& qtype, const string& content, bool noDot) +{ // noDot: for backend storage, pass true. for API users, pass false. auto drc = DNSRecordContent::make(qtype.getCode(), QClass::IN, content); return drc->getZoneRepresentation(noDot); } /** "Normalize" record content for API consumers. */ -static inline string makeApiRecordContent(const QType& qtype, const string& content) { +static inline string makeApiRecordContent(const QType& qtype, const string& content) +{ return makeRecordContent(qtype, content, false); } /** "Normalize" record content for backend storage. */ -static inline string makeBackendRecordContent(const QType& qtype, const string& content) { +static inline string makeBackendRecordContent(const QType& qtype, const string& content) +{ return makeRecordContent(qtype, content, true); } -static Json::object getZoneInfo(const DomainInfo& di, DNSSECKeeper* dk) { +static Json::object getZoneInfo(const DomainInfo& di, DNSSECKeeper* dk) +{ string zoneId = apiZoneNameToId(di.zone); vector primaries; primaries.reserve(di.primaries.size()); @@ -341,17 +328,19 @@ static Json::object getZoneInfo(const DomainInfo& di, DNSSECKeeper* dk) { return obj; } -static bool shouldDoRRSets(HttpRequest* req) { +static bool shouldDoRRSets(HttpRequest* req) +{ if (req->getvars.count("rrsets") == 0 || req->getvars["rrsets"] == "true") return true; if (req->getvars["rrsets"] == "false") return false; - throw ApiException("'rrsets' request parameter value '"+req->getvars["rrsets"]+"' is not supported"); + throw ApiException("'rrsets' request parameter value '" + req->getvars["rrsets"] + "' is not supported"); } -static void fillZone(UeberBackend& B, const DNSName& zonename, HttpResponse* resp, HttpRequest* req) { +static void fillZone(UeberBackend& B, const DNSName& zonename, HttpResponse* resp, HttpRequest* req) +{ DomainInfo di; - if(!B.getDomainInfo(zonename, di)) { + if (!B.getDomainInfo(zonename, di)) { throw HttpNotFoundException(); } @@ -410,47 +399,49 @@ static void fillZone(UeberBackend& B, const DNSName& zonename, HttpResponse* res DNSResourceRecord rr; if (req->getvars.count("rrset_name") == 0) { di.backend->list(zonename, di.id, true); // incl. disabled - } else { + } + else { QType qt; if (req->getvars.count("rrset_type") == 0) { qt = QType::ANY; - } else { + } + else { qt = req->getvars["rrset_type"]; } di.backend->lookup(qt, DNSName(req->getvars["rrset_name"]), di.id); } - while(di.backend->get(rr)) { + while (di.backend->get(rr)) { if (!rr.qtype.getCode()) continue; // skip empty non-terminals records.push_back(rr); } sort(records.begin(), records.end(), [](const DNSResourceRecord& a, const DNSResourceRecord& b) { - /* if you ever want to update this comparison function, - please be aware that you will also need to update the conditions in the code merging - the records and comments below */ - if (a.qname == b.qname) { - return b.qtype < a.qtype; - } - return b.qname < a.qname; - }); + /* if you ever want to update this comparison function, + please be aware that you will also need to update the conditions in the code merging + the records and comments below */ + if (a.qname == b.qname) { + return b.qtype < a.qtype; + } + return b.qname < a.qname; + }); } // load all comments + sort { Comment comment; di.backend->listComments(di.id); - while(di.backend->getComment(comment)) { + while (di.backend->getComment(comment)) { comments.push_back(comment); } sort(comments.begin(), comments.end(), [](const Comment& a, const Comment& b) { - /* if you ever want to update this comparison function, - please be aware that you will also need to update the conditions in the code merging - the records and comments below */ - if (a.qname == b.qname) { - return b.qtype < a.qtype; - } - return b.qname < a.qname; - }); + /* if you ever want to update this comparison function, + please be aware that you will also need to update the conditions in the code merging + the records and comments below */ + if (a.qname == b.qname) { + return b.qtype < a.qtype; + } + return b.qname < a.qname; + }); } Json::array rrsets; @@ -469,26 +460,25 @@ static void fillZone(UeberBackend& B, const DNSName& zonename, HttpResponse* res current_qname = rit->qname; current_qtype = rit->qtype; ttl = rit->ttl; - } else { + } + else { current_qname = cit->qname; current_qtype = cit->qtype; ttl = 0; } - while(rit != records.end() && rit->qname == current_qname && rit->qtype == current_qtype) { + while (rit != records.end() && rit->qname == current_qname && rit->qtype == current_qtype) { ttl = min(ttl, rit->ttl); - rrset_records.push_back(Json::object { - { "disabled", rit->disabled }, - { "content", makeApiRecordContent(rit->qtype, rit->content) } - }); + rrset_records.push_back(Json::object{ + {"disabled", rit->disabled}, + {"content", makeApiRecordContent(rit->qtype, rit->content)}}); rit++; } while (cit != comments.end() && cit->qname == current_qname && cit->qtype == current_qtype) { - rrset_comments.push_back(Json::object { - { "modified_at", (double)cit->modified_at }, - { "account", cit->account }, - { "content", cit->content } - }); + rrset_comments.push_back(Json::object{ + {"modified_at", (double)cit->modified_at}, + {"account", cit->account}, + {"content", cit->content}}); cit++; } @@ -509,10 +499,10 @@ static void fillZone(UeberBackend& B, const DNSName& zonename, HttpResponse* res resp->setJsonBody(doc); } -void productServerStatisticsFetch(map& out) +void productServerStatisticsFetch(map& out) { vector items = S.getEntries(); - for(const string& item : items) { + for (const string& item : items) { out[item] = std::to_string(S.read(item)); } @@ -531,13 +521,15 @@ std::optional productServerStatisticsFetch(const std::string& name) } } -static void validateGatheredRRType(const DNSResourceRecord& rr) { +static void validateGatheredRRType(const DNSResourceRecord& rr) +{ if (rr.qtype.getCode() == QType::OPT || rr.qtype.getCode() == QType::TSIG) { - throw ApiException("RRset "+rr.qname.toString()+" IN "+rr.qtype.toString()+": invalid type given"); + throw ApiException("RRset " + rr.qname.toString() + " IN " + rr.qtype.toString() + ": invalid type given"); } } -static void gatherRecords(const Json& container, const DNSName& qname, const QType& qtype, const uint32_t ttl, vector& new_records) { +static void gatherRecords(const Json& container, const DNSName& qname, const QType& qtype, const uint32_t ttl, vector& new_records) +{ DNSResourceRecord rr; rr.qname = qname; rr.qtype = qtype; @@ -546,10 +538,10 @@ static void gatherRecords(const Json& container, const DNSName& qname, const QTy validateGatheredRRType(rr); const auto& items = container["records"].array_items(); - for(const auto& record : items) { + for (const auto& record : items) { string content = stringFromJson(record, "content"); rr.disabled = false; - if(!record["disabled"].is_null()) { + if (!record["disabled"].is_null()) { rr.disabled = boolFromJson(record, "disabled"); } @@ -558,9 +550,10 @@ static void gatherRecords(const Json& container, const DNSName& qname, const QTy if (rr.qtype.getCode() != QType::AAAA) { string tmp = makeApiRecordContent(rr.qtype, content); if (!pdns_iequals(tmp, content)) { - throw std::runtime_error("Not in expected format (parsed as '"+tmp+"')"); + throw std::runtime_error("Not in expected format (parsed as '" + tmp + "')"); } - } else { + } + else { struct in6_addr tmpbuf; if (inet_pton(AF_INET6, content.c_str(), &tmpbuf) != 1 || content.find('.') != string::npos) { throw std::runtime_error("Invalid IPv6 address"); @@ -568,16 +561,16 @@ static void gatherRecords(const Json& container, const DNSName& qname, const QTy } rr.content = makeBackendRecordContent(rr.qtype, content); } - catch(std::exception& e) - { - throw ApiException("Record "+rr.qname.toString()+"/"+rr.qtype.toString()+" '"+content+"': "+e.what()); + catch (std::exception& e) { + throw ApiException("Record " + rr.qname.toString() + "/" + rr.qtype.toString() + " '" + content + "': " + e.what()); } new_records.push_back(rr); } } -static void gatherComments(const Json& container, const DNSName& qname, const QType& qtype, vector& new_comments) { +static void gatherComments(const Json& container, const DNSName& qname, const QType& qtype, vector& new_comments) +{ Comment c; c.qname = qname; c.qtype = qtype; @@ -592,7 +585,8 @@ static void gatherComments(const Json& container, const DNSName& qname, const QT } } -static void checkDefaultDNSSECAlgos() { +static void checkDefaultDNSSECAlgos() +{ int k_algo = DNSSECKeeper::shorthand2algorithm(::arg()["default-ksk-algorithm"]); int z_algo = DNSSECKeeper::shorthand2algorithm(::arg()["default-zsk-algorithm"]); int k_size = arg().asNum("default-ksk-size"); @@ -603,26 +597,28 @@ static void checkDefaultDNSSECAlgos() { if (k_algo == -1) throw ApiException("default-ksk-algorithm setting is set to unknown algorithm: " + ::arg()["default-ksk-algorithm"]); else if (k_algo <= 10 && k_size == 0) - throw ApiException("default-ksk-algorithm is set to an algorithm("+::arg()["default-ksk-algorithm"]+") that requires a non-zero default-ksk-size!"); + throw ApiException("default-ksk-algorithm is set to an algorithm(" + ::arg()["default-ksk-algorithm"] + ") that requires a non-zero default-ksk-size!"); } if (::arg()["default-zsk-algorithm"] != "") { if (z_algo == -1) throw ApiException("default-zsk-algorithm setting is set to unknown algorithm: " + ::arg()["default-zsk-algorithm"]); else if (z_algo <= 10 && z_size == 0) - throw ApiException("default-zsk-algorithm is set to an algorithm("+::arg()["default-zsk-algorithm"]+") that requires a non-zero default-zsk-size!"); + throw ApiException("default-zsk-algorithm is set to an algorithm(" + ::arg()["default-zsk-algorithm"] + ") that requires a non-zero default-zsk-size!"); } } -static void throwUnableToSecure(const DNSName& zonename) { +static void throwUnableToSecure(const DNSName& zonename) +{ throw ApiException("No backend was able to secure '" + zonename.toString() + "', most likely because no DNSSEC" - + "capable backends are loaded, or because the backends have DNSSEC disabled. Check your configuration."); + + "capable backends are loaded, or because the backends have DNSSEC disabled. Check your configuration."); } /* * Add KSK and ZSK to an existing zone. Algorithms and sizes will be chosen per configuration. -*/ -static void addDefaultDNSSECKeys(DNSSECKeeper& dk, const DNSName& zonename) { + */ +static void addDefaultDNSSECKeys(DNSSECKeeper& dk, const DNSName& zonename) +{ checkDefaultDNSSECAlgos(); int k_algo = DNSSECKeeper::shorthand2algorithm(::arg()["default-ksk-algorithm"]); int z_algo = DNSSECKeeper::shorthand2algorithm(::arg()["default-zsk-algorithm"]); @@ -644,7 +640,8 @@ static void addDefaultDNSSECKeys(DNSSECKeeper& dk, const DNSName& zonename) { } } -static bool isZoneApiRectifyEnabled(const DomainInfo& di) { +static bool isZoneApiRectifyEnabled(const DomainInfo& di) +{ string api_rectify; di.backend->getDomainMetadataOne(di.zone, "API-RECTIFY", api_rectify); if (api_rectify.empty() && ::arg().mustDo("default-api-rectify")) { @@ -657,23 +654,26 @@ static void extractDomainInfoFromDocument(const Json& document, boost::optional< { if (document["kind"].is_string()) { kind = DomainInfo::stringToKind(stringFromJson(document, "kind")); - } else { + } + else { kind = boost::none; } if (document["masters"].is_array()) { primaries = vector(); - for(const auto& value : document["masters"].array_items()) { + for (const auto& value : document["masters"].array_items()) { string primary = value.string_value(); if (primary.empty()) throw ApiException("Primary can not be an empty string"); try { primaries->emplace_back(primary, 53); - } catch (const PDNSException &e) { + } + catch (const PDNSException& e) { throw ApiException("Primary (" + primary + ") is not an IP address: " + e.reason); } } - } else { + } + else { primaries = boost::none; } @@ -687,7 +687,8 @@ static void extractDomainInfoFromDocument(const Json& document, boost::optional< if (document["account"].is_string()) { account = document["account"].string_value(); - } else { + } + else { account = boost::none; } } @@ -696,21 +697,23 @@ static void extractDomainInfoFromDocument(const Json& document, boost::optional< * Build vector of TSIG Key ids from domain update document. * jsonArray: JSON array element to extract TSIG key ids from. * metadata: returned list of domain key ids for setDomainMetadata -*/ -static void extractJsonTSIGKeyIds(UeberBackend& B, const Json& jsonArray, vector& metadata) { - for(const auto& value : jsonArray.array_items()) { + */ +static void extractJsonTSIGKeyIds(UeberBackend& B, const Json& jsonArray, vector& metadata) +{ + for (const auto& value : jsonArray.array_items()) { auto keyname(apiZoneIdToName(value.string_value())); DNSName keyAlgo; string keyContent; if (!B.getTSIGKey(keyname, keyAlgo, keyContent)) { - throw ApiException("A TSIG key with the name '"+keyname.toLogString()+"' does not exist"); + throw ApiException("A TSIG key with the name '" + keyname.toLogString() + "' does not exist"); } metadata.push_back(keyname.toString()); } } // Must be called within backend transaction. -static void updateDomainSettingsFromDocument(UeberBackend& B, DomainInfo& di, const DNSName& zonename, const Json& document, bool zoneWasModified) { +static void updateDomainSettingsFromDocument(UeberBackend& B, DomainInfo& di, const DNSName& zonename, const Json& document, bool zoneWasModified) +{ boost::optional kind; boost::optional> primaries; boost::optional catalog; @@ -742,8 +745,8 @@ static void updateDomainSettingsFromDocument(UeberBackend& B, DomainInfo& di, co bool api_rectify = boolFromJson(document, "api_rectify"); di.backend->setDomainMetadataOne(zonename, "API-RECTIFY", api_rectify ? "1" : "0"); } - catch (const JsonException&) {} - + catch (const JsonException&) { + } DNSSECKeeper dk(&B); bool shouldRectify = zoneWasModified; @@ -757,14 +760,15 @@ static void updateDomainSettingsFromDocument(UeberBackend& B, DomainInfo& di, co dnssecDocVal = boolFromJson(document, "dnssec"); dnssecInJSON = true; } - catch (const JsonException&) {} + catch (const JsonException&) { + } try { nsec3paramDocVal = stringFromJson(document, "nsec3param"); nsec3paramInJSON = true; } - catch (const JsonException&) {} - + catch (const JsonException&) { + } bool isDNSSECZone = dk.isSecuredZone(zonename); bool isPresigned = dk.isPresigned(zonename); @@ -783,16 +787,17 @@ static void updateDomainSettingsFromDocument(UeberBackend& B, DomainInfo& di, co shouldRectify = true; updateNsec3Param = true; } - } else { + } + else { // "dnssec": false in json if (isDNSSECZone) { string info, error; if (!dk.unSecureZone(zonename, error)) { - throw ApiException("Error while un-securing zone '"+ zonename.toString()+"': " + error); + throw ApiException("Error while un-securing zone '" + zonename.toString() + "': " + error); } isDNSSECZone = dk.isSecuredZone(zonename, false); if (isDNSSECZone) { - throw ApiException("Unable to un-secure zone '"+ zonename.toString()+"'"); + throw ApiException("Unable to un-secure zone '" + zonename.toString() + "'"); } shouldRectify = true; updateNsec3Param = true; @@ -817,11 +822,10 @@ static void updateDomainSettingsFromDocument(UeberBackend& B, DomainInfo& di, co NSEC3PARAMRecordContent ns3pr(nsec3paramDocVal); string error_msg = ""; if (!dk.checkNSEC3PARAM(ns3pr, error_msg)) { - throw ApiException("NSEC3PARAMs provided for zone '"+zonename.toString()+"' are invalid. " + error_msg); + throw ApiException("NSEC3PARAMs provided for zone '" + zonename.toString() + "' are invalid. " + error_msg); } if (!dk.setNSEC3PARAM(zonename, ns3pr, boolFromJson(document, "nsec3narrow", false))) { - throw ApiException("NSEC3PARAMs provided for zone '" + zonename.toString() + - "' passed our basic sanity checks, but cannot be used with the current backend."); + throw ApiException("NSEC3PARAMs provided for zone '" + zonename.toString() + "' passed our basic sanity checks, but cannot be used with the current backend."); } } } @@ -873,8 +877,9 @@ static void updateDomainSettingsFromDocument(UeberBackend& B, DomainInfo& di, co } } -static bool isValidMetadataKind(const string& kind, bool readonly) { - static vector builtinOptions { +static bool isValidMetadataKind(const string& kind, bool readonly) +{ + static vector builtinOptions{ "ALLOW-AXFR-FROM", "AXFR-SOURCE", "ALLOW-DNSUPDATE-FROM", @@ -896,19 +901,17 @@ static bool isValidMetadataKind(const string& kind, bool readonly) { "SLAVE-RENOTIFY", "SOA-EDIT", "TSIG-ALLOW-AXFR", - "TSIG-ALLOW-DNSUPDATE" - }; + "TSIG-ALLOW-DNSUPDATE"}; // the following options do not allow modifications via API - static vector protectedOptions { + static vector protectedOptions{ "API-RECTIFY", "AXFR-MASTER-TSIG", "NSEC3NARROW", "NSEC3PARAM", "PRESIGNED", "LUA-AXFR-SCRIPT", - "TSIG-ALLOW-AXFR" - }; + "TSIG-ALLOW-AXFR"}; if (kind.find("X-") == 0) return true; @@ -931,16 +934,17 @@ static bool isValidMetadataKind(const string& kind, bool readonly) { // this is easier as macro since we need UeberBackend instance in most places // NOLINTBEGIN(cppcoreguidelines-macro-usage, readability-identifier-length) -#define zoneFromId(req) \ - DNSName zonename = apiZoneIdToName((req)->parameters["id"]); \ - UeberBackend B; \ - DNSSECKeeper dk(&B); \ - DomainInfo di; \ - try { \ - if (!B.getDomainInfo(zonename, di)) { \ - throw HttpNotFoundException(); \ - } \ - } catch(const PDNSException &e) { \ +#define zoneFromId(req) \ + DNSName zonename = apiZoneIdToName((req)->parameters["id"]); \ + UeberBackend B; \ + DNSSECKeeper dk(&B); \ + DomainInfo di; \ + try { \ + if (!B.getDomainInfo(zonename, di)) { \ + throw HttpNotFoundException(); \ + } \ + } \ + catch (const PDNSException& e) { \ throw HttpInternalServerErrorException("Could not retrieve Domain Info: " + e.reason); \ } // NOLINTEND(cppcoreguidelines-macro-usage, readability-identifier-length) @@ -949,20 +953,24 @@ static bool isValidMetadataKind(const string& kind, bool readonly) { */ #include "apidocfiles.h" -void apiDocs(HttpRequest* req, HttpResponse* resp) { +void apiDocs(HttpRequest* req, HttpResponse* resp) +{ if (req->accept_yaml) { resp->setYamlBody(g_api_swagger_yaml); - } else if (req->accept_json) { + } + else if (req->accept_json) { resp->setJsonBody(g_api_swagger_json); - } else { + } + else { resp->setPlainBody(g_api_swagger_yaml); } } -static void apiZoneMetadataGET(HttpRequest* req, HttpResponse *resp) { +static void apiZoneMetadataGET(HttpRequest* req, HttpResponse* resp) +{ zoneFromId(req); - map > metas; + map> metas; Json::array document; if (!B.getAllDomainMetadata(zonename, metas)) { @@ -975,17 +983,17 @@ static void apiZoneMetadataGET(HttpRequest* req, HttpResponse *resp) { entries.push_back(value); } - Json::object key { - { "type", "Metadata" }, - { "kind", meta.first }, - { "metadata", entries } - }; + Json::object key{ + {"type", "Metadata"}, + {"kind", meta.first}, + {"metadata", entries}}; document.push_back(key); } resp->setJsonBody(document); } -static void apiZoneMetadataPOST(HttpRequest* req, HttpResponse *resp) { +static void apiZoneMetadataPOST(HttpRequest* req, HttpResponse* resp) +{ zoneFromId(req); const auto& document = req->json(); @@ -994,8 +1002,9 @@ static void apiZoneMetadataPOST(HttpRequest* req, HttpResponse *resp) { try { kind = stringFromJson(document, "kind"); - } catch (const JsonException&) { - throw ApiException("kind is not specified or not a string"); + } + catch (const JsonException&) { + throw ApiException("kind is not specified or not a string"); } if (!isValidMetadataKind(kind, false)) { @@ -1005,8 +1014,7 @@ static void apiZoneMetadataPOST(HttpRequest* req, HttpResponse *resp) { vector vecMetadata; if (!B.getDomainMetadata(zonename, kind, vecMetadata)) { - throw ApiException("Could not retrieve metadata entries for domain '" + - zonename.toString() + "'"); + throw ApiException("Could not retrieve metadata entries for domain '" + zonename.toString() + "'"); } const auto& metadata = document["metadata"]; @@ -1019,15 +1027,15 @@ static void apiZoneMetadataPOST(HttpRequest* req, HttpResponse *resp) { throw ApiException("metadata must be strings"); } if (std::find(vecMetadata.cbegin(), - vecMetadata.cend(), - value.string_value()) == vecMetadata.cend()) { + vecMetadata.cend(), + value.string_value()) + == vecMetadata.cend()) { vecMetadata.push_back(value.string_value()); } } if (!B.setDomainMetadata(zonename, kind, vecMetadata)) { - throw ApiException("Could not update metadata entries for domain '" + - zonename.toString() + "'"); + throw ApiException("Could not update metadata entries for domain '" + zonename.toString() + "'"); } DNSSECKeeper::clearMetaCache(zonename); @@ -1037,17 +1045,17 @@ static void apiZoneMetadataPOST(HttpRequest* req, HttpResponse *resp) { respMetadata.push_back(value); } - Json::object key { - { "type", "Metadata" }, - { "kind", document["kind"] }, - { "metadata", respMetadata } - }; + Json::object key{ + {"type", "Metadata"}, + {"kind", document["kind"]}, + {"metadata", respMetadata}}; resp->status = 201; resp->setJsonBody(key); } -static void apiZoneMetadataKindGET(HttpRequest* req, HttpResponse* resp) { +static void apiZoneMetadataKindGET(HttpRequest* req, HttpResponse* resp) +{ zoneFromId(req); string kind = req->parameters["kind"]; @@ -1074,7 +1082,8 @@ static void apiZoneMetadataKindGET(HttpRequest* req, HttpResponse* resp) { resp->setJsonBody(document); } -static void apiZoneMetadataKindPUT(HttpRequest* req, HttpResponse* resp) { +static void apiZoneMetadataKindPUT(HttpRequest* req, HttpResponse* resp) +{ zoneFromId(req); string kind = req->parameters["kind"]; @@ -1103,16 +1112,16 @@ static void apiZoneMetadataKindPUT(HttpRequest* req, HttpResponse* resp) { DNSSECKeeper::clearMetaCache(zonename); - Json::object key { - { "type", "Metadata" }, - { "kind", kind }, - { "metadata", metadata } - }; + Json::object key{ + {"type", "Metadata"}, + {"kind", kind}, + {"metadata", metadata}}; resp->setJsonBody(key); } -static void apiZoneMetadataKindDELETE(HttpRequest* req, HttpResponse* resp) { +static void apiZoneMetadataKindDELETE(HttpRequest* req, HttpResponse* resp) +{ zoneFromId(req); const string& kind = req->parameters["kind"]; @@ -1120,7 +1129,7 @@ static void apiZoneMetadataKindDELETE(HttpRequest* req, HttpResponse* resp) { throw ApiException("Unsupported metadata kind '" + kind + "'"); } - vector metadata; // an empty vector will do it + vector metadata; // an empty vector will do it if (!B.setDomainMetadata(zonename, kind, metadata)) { throw ApiException("Could not delete metadata for domain '" + zonename.toString() + "' (" + kind + ")"); } @@ -1130,11 +1139,12 @@ static void apiZoneMetadataKindDELETE(HttpRequest* req, HttpResponse* resp) { } // Throws 404 if the key with inquireKeyId does not exist -static void apiZoneCryptoKeysCheckKeyExists(const DNSName& zonename, int inquireKeyId, DNSSECKeeper *dk) { - DNSSECKeeper::keyset_t keyset=dk->getKeys(zonename, false); +static void apiZoneCryptoKeysCheckKeyExists(const DNSName& zonename, int inquireKeyId, DNSSECKeeper* dk) +{ + DNSSECKeeper::keyset_t keyset = dk->getKeys(zonename, false); bool found = false; - for(const auto& value : keyset) { - if (value.second.id == (unsigned) inquireKeyId) { + for (const auto& value : keyset) { + if (value.second.id == (unsigned)inquireKeyId) { found = true; break; } @@ -1144,7 +1154,8 @@ static void apiZoneCryptoKeysCheckKeyExists(const DNSName& zonename, int inquire } } -static inline int getInquireKeyId(HttpRequest *req, const DNSName& zonename, DNSSECKeeper *dnsseckeeper) { +static inline int getInquireKeyId(HttpRequest* req, const DNSName& zonename, DNSSECKeeper* dnsseckeeper) +{ int inquireKeyId = -1; if (req->parameters.count("key_id") == 1) { inquireKeyId = std::stoi(req->parameters["key_id"]); @@ -1153,35 +1164,41 @@ static inline int getInquireKeyId(HttpRequest *req, const DNSName& zonename, DNS return inquireKeyId; } -static void apiZoneCryptokeysExport(const DNSName& zonename, int64_t inquireKeyId, HttpResponse *resp, DNSSECKeeper *dnssec_dk) { - DNSSECKeeper::keyset_t keyset=dnssec_dk->getKeys(zonename, false); +static void apiZoneCryptokeysExport(const DNSName& zonename, int64_t inquireKeyId, HttpResponse* resp, DNSSECKeeper* dnssec_dk) +{ + DNSSECKeeper::keyset_t keyset = dnssec_dk->getKeys(zonename, false); bool inquireSingleKey = inquireKeyId >= 0; Json::array doc; - for(const auto& value : keyset) { + for (const auto& value : keyset) { if (inquireSingleKey && (unsigned)inquireKeyId != value.second.id) { continue; } string keyType; switch (value.second.keyType) { - case DNSSECKeeper::KSK: keyType="ksk"; break; - case DNSSECKeeper::ZSK: keyType="zsk"; break; - case DNSSECKeeper::CSK: keyType="csk"; break; - } - - Json::object key { - { "type", "Cryptokey" }, - { "id", static_cast(value.second.id) }, - { "active", value.second.active }, - { "published", value.second.published }, - { "keytype", keyType }, - { "flags", static_cast(value.first.getFlags()) }, - { "dnskey", value.first.getDNSKEY().getZoneRepresentation() }, - { "algorithm", DNSSECKeeper::algorithm2name(value.first.getAlgorithm()) }, - { "bits", value.first.getKey()->getBits() } - }; + case DNSSECKeeper::KSK: + keyType = "ksk"; + break; + case DNSSECKeeper::ZSK: + keyType = "zsk"; + break; + case DNSSECKeeper::CSK: + keyType = "csk"; + break; + } + + Json::object key{ + {"type", "Cryptokey"}, + {"id", static_cast(value.second.id)}, + {"active", value.second.active}, + {"published", value.second.published}, + {"keytype", keyType}, + {"flags", static_cast(value.first.getFlags())}, + {"dnskey", value.first.getDNSKEY().getZoneRepresentation()}, + {"algorithm", DNSSECKeeper::algorithm2name(value.first.getAlgorithm())}, + {"bits", value.first.getKey()->getBits()}}; string publishCDS; dnssec_dk->getPublishCDS(zonename, publishCDS); @@ -1190,21 +1207,25 @@ static void apiZoneCryptokeysExport(const DNSName& zonename, int64_t inquireKeyI stringtok(digestAlgos, publishCDS, ", "); std::set CDSalgos; - for(auto const &digestAlgo : digestAlgos) { + for (auto const& digestAlgo : digestAlgos) { CDSalgos.insert(pdns::checked_stoi(digestAlgo)); } if (value.second.keyType == DNSSECKeeper::KSK || value.second.keyType == DNSSECKeeper::CSK) { Json::array cdses; Json::array dses; - for(const uint8_t keyid : { DNSSECKeeper::DIGEST_SHA1, DNSSECKeeper::DIGEST_SHA256, DNSSECKeeper::DIGEST_GOST, DNSSECKeeper::DIGEST_SHA384 }) + for (const uint8_t keyid : {DNSSECKeeper::DIGEST_SHA1, DNSSECKeeper::DIGEST_SHA256, DNSSECKeeper::DIGEST_GOST, DNSSECKeeper::DIGEST_SHA384}) try { string ds = makeDSFromDNSKey(zonename, value.first.getDNSKEY(), keyid).getZoneRepresentation(); dses.push_back(ds); - if (CDSalgos.count(keyid)) { cdses.push_back(ds); } - } catch (...) {} + if (CDSalgos.count(keyid)) { + cdses.push_back(ds); + } + } + catch (...) { + } key["ds"] = dses; @@ -1228,7 +1249,8 @@ static void apiZoneCryptokeysExport(const DNSName& zonename, int64_t inquireKeyI resp->setJsonBody(doc); } -static void apiZoneCryptokeysGET(HttpRequest *req, HttpResponse *resp) { +static void apiZoneCryptokeysGET(HttpRequest* req, HttpResponse* resp) +{ zoneFromId(req); const auto inquireKeyId = getInquireKeyId(req, zonename, &dk); @@ -1246,18 +1268,20 @@ static void apiZoneCryptokeysGET(HttpRequest *req, HttpResponse *resp) { * Case 3: the key or zone does not exist. * The server returns 404 Not Found * */ -static void apiZoneCryptokeysDELETE(HttpRequest *req, HttpResponse *resp) { +static void apiZoneCryptokeysDELETE(HttpRequest* req, HttpResponse* resp) +{ zoneFromId(req); const auto inquireKeyId = getInquireKeyId(req, zonename, &dk); if (inquireKeyId == -1) { - throw HttpBadRequestException(); + throw HttpBadRequestException(); } if (dk.removeKey(zonename, inquireKeyId)) { resp->body = ""; resp->status = 204; - } else { + } + else { resp->setErrorResult("Could not DELETE " + req->parameters["key_id"], 422); } } @@ -1298,7 +1322,8 @@ static void apiZoneCryptokeysDELETE(HttpRequest *req, HttpResponse *resp) { * The server returns 201 Created and all public data about the added cryptokey */ -static void apiZoneCryptokeysPOST(HttpRequest *req, HttpResponse *resp) { +static void apiZoneCryptokeysPOST(HttpRequest* req, HttpResponse* resp) +{ zoneFromId(req); const auto& document = req->json(); @@ -1315,9 +1340,11 @@ static void apiZoneCryptokeysPOST(HttpRequest *req, HttpResponse *resp) { if (stringFromJson(document, "keytype") == "ksk" || stringFromJson(document, "keytype") == "csk") { keyOrZone = true; - } else if (stringFromJson(document, "keytype") == "zsk") { + } + else if (stringFromJson(document, "keytype") == "zsk") { keyOrZone = false; - } else { + } + else { throw ApiException("Invalid keytype " + stringFromJson(document, "keytype")); } @@ -1329,7 +1356,8 @@ static void apiZoneCryptokeysPOST(HttpRequest *req, HttpResponse *resp) { if (!docbits.is_null()) { if (!docbits.is_number() || (fmod(docbits.number_value(), 1.0) != 0) || docbits.int_value() < 0) { throw ApiException("'bits' must be a positive integer value"); - } else { + } + else { bits = docbits.int_value(); } } @@ -1340,9 +1368,11 @@ static void apiZoneCryptokeysPOST(HttpRequest *req, HttpResponse *resp) { if (algorithm == -1) { throw ApiException("Unknown algorithm: " + providedAlgo.string_value()); } - } else if (providedAlgo.is_number()) { + } + else if (providedAlgo.is_number()) { algorithm = providedAlgo.int_value(); - } else if (!providedAlgo.is_null()) { + } + else if (!providedAlgo.is_null()) { throw ApiException("Unknown algorithm: " + providedAlgo.string_value()); } @@ -1350,12 +1380,14 @@ static void apiZoneCryptokeysPOST(HttpRequest *req, HttpResponse *resp) { if (!dk.addKey(zonename, keyOrZone, algorithm, insertedId, bits, active, published)) { throw ApiException("Adding key failed, perhaps DNSSEC not enabled in configuration?"); } - } catch (std::runtime_error& error) { + } + catch (std::runtime_error& error) { throw ApiException(error.what()); } if (insertedId < 0) throw ApiException("Adding key failed, perhaps DNSSEC not enabled in configuration?"); - } else if (document["bits"].is_null() && document["algorithm"].is_null()) { + } + else if (document["bits"].is_null() && document["algorithm"].is_null()) { const auto& keyData = stringFromJson(document, privatekey_fieldname); DNSKEYRecordContent dkrc; DNSSECPrivateKey dpk; @@ -1378,17 +1410,20 @@ static void apiZoneCryptokeysPOST(HttpRequest *req, HttpResponse *resp) { } catch (std::runtime_error& error) { throw ApiException("Key could not be parsed. Make sure your key format is correct."); - } try { + } + try { if (!dk.addKey(zonename, dpk, insertedId, active, published)) { throw ApiException("Adding key failed, perhaps DNSSEC not enabled in configuration?"); } - } catch (std::runtime_error& error) { + } + catch (std::runtime_error& error) { throw ApiException(error.what()); } if (insertedId < 0) { throw ApiException("Adding key failed, perhaps DNSSEC not enabled in configuration?"); } - } else { + } + else { throw ApiException("Either you submit just the 'privatekey' field or you leave 'privatekey' empty and submit the other fields."); } apiZoneCryptokeysExport(zonename, insertedId, resp, &dk); @@ -1406,16 +1441,17 @@ static void apiZoneCryptokeysPOST(HttpRequest *req, HttpResponse *resp) { * Case 3: the backend returns false on de/activation. An error occurred. * The sever returns 422 Unprocessable Entity with message "Could not de/activate Key: :cryptokey_id in Zone: :zone_name" * */ -static void apiZoneCryptokeysPUT(HttpRequest *req, HttpResponse *resp) { +static void apiZoneCryptokeysPUT(HttpRequest* req, HttpResponse* resp) +{ zoneFromId(req); const auto inquireKeyId = getInquireKeyId(req, zonename, &dk); if (inquireKeyId == -1) { throw HttpBadRequestException(); } - //throws an exception if the Body is empty + // throws an exception if the Body is empty const auto& document = req->json(); - //throws an exception if the key does not exist or is not a bool + // throws an exception if the key does not exist or is not a bool bool active = boolFromJson(document, "active"); bool published = boolFromJson(document, "published", true); if (active) { @@ -1423,7 +1459,8 @@ static void apiZoneCryptokeysPUT(HttpRequest *req, HttpResponse *resp) { resp->setErrorResult("Could not activate Key: " + req->parameters["key_id"] + " in Zone: " + zonename.toString(), 422); return; } - } else { + } + else { if (!dk.deactivateKey(zonename, inquireKeyId)) { resp->setErrorResult("Could not deactivate Key: " + req->parameters["key_id"] + " in Zone: " + zonename.toString(), 422); return; @@ -1435,7 +1472,8 @@ static void apiZoneCryptokeysPUT(HttpRequest *req, HttpResponse *resp) { resp->setErrorResult("Could not publish Key: " + req->parameters["key_id"] + " in Zone: " + zonename.toString(), 422); return; } - } else { + } + else { if (!dk.unpublishKey(zonename, inquireKeyId)) { resp->setErrorResult("Could not unpublish Key: " + req->parameters["key_id"] + " in Zone: " + zonename.toString(), 422); return; @@ -1447,7 +1485,8 @@ static void apiZoneCryptokeysPUT(HttpRequest *req, HttpResponse *resp) { return; } -static void gatherRecordsFromZone(const std::string& zonestring, vector& new_records, const DNSName& zonename) { +static void gatherRecordsFromZone(const std::string& zonestring, vector& new_records, const DNSName& zonename) +{ DNSResourceRecord rr; vector zonedata; stringtok(zonedata, zonestring, "\r\n"); @@ -1456,23 +1495,23 @@ static void gatherRecordsFromZone(const std::string& zonestring, vector& records, const DNSName& zone) { sort(records.begin(), records.end(), - [](const DNSResourceRecord& rec_a, const DNSResourceRecord& rec_b) -> bool { - /* we need _strict_ weak ordering */ - return std::tie(rec_a.qname, rec_a.qtype, rec_a.content) < std::tie(rec_b.qname, rec_b.qtype, rec_b.content); - } - ); + [](const DNSResourceRecord& rec_a, const DNSResourceRecord& rec_b) -> bool { + /* we need _strict_ weak ordering */ + return std::tie(rec_a.qname, rec_a.qtype, rec_a.content) < std::tie(rec_b.qname, rec_b.qtype, rec_b.content); + }); DNSResourceRecord previous; - for(const auto& rec : records) { + for (const auto& rec : records) { if (previous.qname == rec.qname) { if (previous.qtype == rec.qtype) { if (onlyOneEntryTypes.count(rec.qtype.getCode()) != 0) { - throw ApiException("RRset "+rec.qname.toString()+" IN "+rec.qtype.toString()+" has more than one record"); + throw ApiException("RRset " + rec.qname.toString() + " IN " + rec.qtype.toString() + " has more than one record"); } if (previous.content == rec.content) { throw ApiException("Duplicate record in RRset " + rec.qname.toString() + " IN " + rec.qtype.toString() + " with content \"" + rec.content + "\""); } - } else if (exclusiveEntryTypes.count(rec.qtype.getCode()) != 0 || exclusiveEntryTypes.count(previous.qtype.getCode()) != 0) { - throw ApiException("RRset "+rec.qname.toString()+" IN "+rec.qtype.toString()+": Conflicts with another RRset"); + } + else if (exclusiveEntryTypes.count(rec.qtype.getCode()) != 0 || exclusiveEntryTypes.count(previous.qtype.getCode()) != 0) { + throw ApiException("RRset " + rec.qname.toString() + " IN " + rec.qtype.toString() + ": Conflicts with another RRset"); } } @@ -1520,19 +1559,21 @@ static void checkNewRecords(vector& records, const DNSName& z // Check if the DNSNames that should be hostnames, are hostnames try { checkHostnameCorrectness(rec); - } catch (const std::exception& e) { - throw ApiException("RRset "+rec.qname.toString()+" IN "+rec.qtype.toString() + ": " + e.what()); + } + catch (const std::exception& e) { + throw ApiException("RRset " + rec.qname.toString() + " IN " + rec.qtype.toString() + ": " + e.what()); } previous = rec; } } -static void checkTSIGKey(UeberBackend& B, const DNSName& keyname, const DNSName& algo, const string& content) { +static void checkTSIGKey(UeberBackend& B, const DNSName& keyname, const DNSName& algo, const string& content) +{ DNSName algoFromDB; string contentFromDB; if (B.getTSIGKey(keyname, algoFromDB, contentFromDB)) { - throw HttpConflictException("A TSIG key with the name '"+keyname.toLogString()+"' already exists"); + throw HttpConflictException("A TSIG key with the name '" + keyname.toLogString() + "' already exists"); } TSIGHashEnum the; @@ -1546,22 +1587,24 @@ static void checkTSIGKey(UeberBackend& B, const DNSName& keyname, const DNSName& } } -static Json::object makeJSONTSIGKey(const DNSName& keyname, const DNSName& algo, const string& content) { +static Json::object makeJSONTSIGKey(const DNSName& keyname, const DNSName& algo, const string& content) +{ Json::object tsigkey = { - { "name", keyname.toStringNoDot() }, - { "id", apiZoneNameToId(keyname) }, - { "algorithm", algo.toStringNoDot() }, - { "key", content }, - { "type", "TSIGKey" } - }; + {"name", keyname.toStringNoDot()}, + {"id", apiZoneNameToId(keyname)}, + {"algorithm", algo.toStringNoDot()}, + {"key", content}, + {"type", "TSIGKey"}}; return tsigkey; } -static Json::object makeJSONTSIGKey(const struct TSIGKey& key, bool doContent=true) { +static Json::object makeJSONTSIGKey(const struct TSIGKey& key, bool doContent = true) +{ return makeJSONTSIGKey(key.name, key.algorithm, doContent ? key.key : ""); } -static void apiServerTSIGKeysGET(HttpRequest* /* req */, HttpResponse* resp) { +static void apiServerTSIGKeysGET(HttpRequest* /* req */, HttpResponse* resp) +{ UeberBackend B; // NOLINT(readability-identifier-length) vector keys; @@ -1571,13 +1614,14 @@ static void apiServerTSIGKeysGET(HttpRequest* /* req */, HttpResponse* resp) { Json::array doc; - for(const auto &key : keys) { + for (const auto& key : keys) { doc.push_back(makeJSONTSIGKey(key, false)); } resp->setJsonBody(doc); } -static void apiServerTSIGKeysPOST(HttpRequest* req, HttpResponse* resp) { +static void apiServerTSIGKeysPOST(HttpRequest* req, HttpResponse* resp) +{ UeberBackend B; // NOLINT(readability-identifier-length) const auto& document = req->json(); DNSName keyname(stringFromJson(document, "name")); @@ -1587,7 +1631,8 @@ static void apiServerTSIGKeysPOST(HttpRequest* req, HttpResponse* resp) { if (content.empty()) { try { content = makeTSIGKey(algo); - } catch (const PDNSException& exc) { + } + catch (const PDNSException& exc) { throw HttpBadRequestException(exc.reason); } } @@ -1595,7 +1640,7 @@ static void apiServerTSIGKeysPOST(HttpRequest* req, HttpResponse* resp) { // Will throw an ApiException or HttpConflictException on error checkTSIGKey(B, keyname, algo, content); - if(!B.setTSIGKey(keyname, algo, content)) { + if (!B.setTSIGKey(keyname, algo, content)) { throw HttpInternalServerErrorException("Unable to add TSIG key"); } @@ -1604,31 +1649,34 @@ static void apiServerTSIGKeysPOST(HttpRequest* req, HttpResponse* resp) { } // NOLINTBEGIN(cppcoreguidelines-macro-usage, readability-identifier-length) -#define TSIGKeyFromId(req) \ - UeberBackend B; \ - DNSName keyname = apiZoneIdToName((req)->parameters["id"]); \ - DNSName algo; \ - string content; \ - try { \ - if (!B.getTSIGKey(keyname, algo, content)) { \ - throw HttpNotFoundException("TSIG key with name '"+keyname.toLogString()+"' not found"); \ - } \ - } catch(const PDNSException &e) { \ - throw HttpInternalServerErrorException("Could not retrieve Domain Info: " + e.reason); \ - } \ - struct TSIGKey tsk; \ - tsk.name = keyname; \ - tsk.algorithm = algo; \ +#define TSIGKeyFromId(req) \ + UeberBackend B; \ + DNSName keyname = apiZoneIdToName((req)->parameters["id"]); \ + DNSName algo; \ + string content; \ + try { \ + if (!B.getTSIGKey(keyname, algo, content)) { \ + throw HttpNotFoundException("TSIG key with name '" + keyname.toLogString() + "' not found"); \ + } \ + } \ + catch (const PDNSException& e) { \ + throw HttpInternalServerErrorException("Could not retrieve Domain Info: " + e.reason); \ + } \ + struct TSIGKey tsk; \ + tsk.name = keyname; \ + tsk.algorithm = algo; \ tsk.key = std::move(content); // NOLINTEND(cppcoreguidelines-macro-usage, readability-identifier-length) -static void apiServerTSIGKeyDetailGET(HttpRequest* req, HttpResponse* resp) { +static void apiServerTSIGKeyDetailGET(HttpRequest* req, HttpResponse* resp) +{ TSIGKeyFromId(req); resp->setJsonBody(makeJSONTSIGKey(tsk)); } -static void apiServerTSIGKeyDetailPUT(HttpRequest* req, HttpResponse* resp) { +static void apiServerTSIGKeyDetailPUT(HttpRequest* req, HttpResponse* resp) +{ TSIGKeyFromId(req); const auto& document = req->json(); @@ -1664,7 +1712,8 @@ static void apiServerTSIGKeyDetailPUT(HttpRequest* req, HttpResponse* resp) { resp->setJsonBody(makeJSONTSIGKey(tsk)); } -static void apiServerTSIGKeyDetailDELETE(HttpRequest* req, HttpResponse* resp) { +static void apiServerTSIGKeyDetailDELETE(HttpRequest* req, HttpResponse* resp) +{ TSIGKeyFromId(req); if (!B.deleteTSIGKey(keyname)) { throw HttpInternalServerErrorException("Unable to remove TSIG key '" + keyname.toStringNoDot() + "'"); @@ -1673,17 +1722,19 @@ static void apiServerTSIGKeyDetailDELETE(HttpRequest* req, HttpResponse* resp) { resp->status = 204; } -static void apiServerAutoprimaryDetailDELETE(HttpRequest* req, HttpResponse* resp) { +static void apiServerAutoprimaryDetailDELETE(HttpRequest* req, HttpResponse* resp) +{ UeberBackend B; // NOLINT(readability-identifier-length) const AutoPrimary& primary{req->parameters["ip"], req->parameters["nameserver"], ""}; if (!B.autoPrimaryRemove(primary)) { - throw HttpInternalServerErrorException("Cannot find backend with autoprimary feature"); + throw HttpInternalServerErrorException("Cannot find backend with autoprimary feature"); } resp->body = ""; resp->status = 204; } -static void apiServerAutoprimariesGET(HttpRequest* /* req */, HttpResponse* resp) { +static void apiServerAutoprimariesGET(HttpRequest* /* req */, HttpResponse* resp) +{ UeberBackend B; // NOLINT(readability-identifier-length) std::vector primaries; @@ -1691,18 +1742,18 @@ static void apiServerAutoprimariesGET(HttpRequest* /* req */, HttpResponse* resp throw HttpInternalServerErrorException("Unable to retrieve autoprimaries"); } Json::array doc; - for (const auto& primary: primaries) { + for (const auto& primary : primaries) { const Json::object obj = { - { "ip", primary.ip }, - { "nameserver", primary.nameserver }, - { "account", primary.account } - }; + {"ip", primary.ip}, + {"nameserver", primary.nameserver}, + {"account", primary.account}}; doc.push_back(obj); } resp->setJsonBody(doc); } -static void apiServerAutoprimariesPOST(HttpRequest* req, HttpResponse* resp) { +static void apiServerAutoprimariesPOST(HttpRequest* req, HttpResponse* resp) +{ UeberBackend B; // NOLINT(readability-identifier-length) const auto& document = req->json(); @@ -1724,7 +1775,8 @@ static void apiServerAutoprimariesPOST(HttpRequest* req, HttpResponse* resp) { } // create new zone -static void apiServerZonesPOST(HttpRequest* req, HttpResponse* resp) { +static void apiServerZonesPOST(HttpRequest* req, HttpResponse* resp) +{ UeberBackend B; // NOLINT(readability-identifier-length) DNSSECKeeper dk(&B); // NOLINT(readability-identifier-length) DomainInfo di; // NOLINT(readability-identifier-length) @@ -1775,7 +1827,7 @@ static void apiServerZonesPOST(HttpRequest* req, HttpResponse* resp) { QType qtype; qtype = stringFromJson(rrset, "type"); if (qtype.getCode() == 0) { - throw ApiException("RRset "+qname.toString()+" IN "+stringFromJson(rrset, "type")+": unknown type given"); + throw ApiException("RRset " + qname.toString() + " IN " + stringFromJson(rrset, "type") + ": unknown type given"); } if (rrset["records"].is_array()) { uint32_t ttl = uintFromJson(rrset, "ttl"); @@ -1785,7 +1837,8 @@ static void apiServerZonesPOST(HttpRequest* req, HttpResponse* resp) { gatherComments(rrset, qname, qtype, new_comments); } } - } else if (!zonestring.empty()) { + } + else if (!zonestring.empty()) { gatherRecordsFromZone(zonestring, new_records, zonename); } } @@ -1797,10 +1850,10 @@ static void apiServerZonesPOST(HttpRequest* req, HttpResponse* resp) { throw ApiException("Zone data MUST NOT be given for Consumer zones"); } - for(auto& rr : new_records) { // NOLINT(readability-identifier-length) + for (auto& rr : new_records) { // NOLINT(readability-identifier-length) rr.qname.makeUsLowerCase(); if (!rr.qname.isPartOf(zonename) && rr.qname != zonename) { - throw ApiException("RRset "+rr.qname.toString()+" IN "+rr.qtype.toString()+": Name is out of zone"); + throw ApiException("RRset " + rr.qname.toString() + " IN " + rr.qtype.toString() + ": Name is out of zone"); } apiCheckQNameAllowedCharacters(rr.qname.toString()); @@ -1825,7 +1878,7 @@ static void apiServerZonesPOST(HttpRequest* req, HttpResponse* resp) { boost::replace_all(soa, "@", zonename.toStringNoDot()); SOAData sd; // NOLINT(readability-identifier-length) fillSOAData(soa, sd); - sd.serial=document["serial"].int_value(); + sd.serial = document["serial"].int_value(); autorr.qtype = QType::SOA; autorr.content = makeSOAContent(sd)->getZoneRepresentation(true); // updateDomainSettingsFromDocument will apply SOA-EDIT-API as needed @@ -1847,7 +1900,8 @@ static void apiServerZonesPOST(HttpRequest* req, HttpResponse* resp) { try { // ensure the name parses autorr.content = DNSName(nameserver).toStringRootDot(); - } catch (...) { + } + catch (...) { throw ApiException("Unable to parse DNS Name for NS '" + nameserver + "'"); } autorr.qtype = QType::NS; @@ -1862,22 +1916,22 @@ static void apiServerZonesPOST(HttpRequest* req, HttpResponse* resp) { if (boolFromJson(document, "dnssec", false)) { checkDefaultDNSSECAlgos(); - if(document["nsec3param"].string_value().length() > 0) { + if (document["nsec3param"].string_value().length() > 0) { NSEC3PARAMRecordContent ns3pr(document["nsec3param"].string_value()); string error_msg; if (!dk.checkNSEC3PARAM(ns3pr, error_msg)) { - throw ApiException("NSEC3PARAMs provided for zone '"+zonename.toString()+"' are invalid. " + error_msg); + throw ApiException("NSEC3PARAMs provided for zone '" + zonename.toString() + "' are invalid. " + error_msg); } } } // no going back after this if (!B.createDomain(zonename, kind.get_value_or(DomainInfo::Native), primaries.get_value_or(vector()), account.get_value_or(""))) { - throw ApiException("Creating domain '"+zonename.toString()+"' failed: backend refused"); + throw ApiException("Creating domain '" + zonename.toString() + "' failed: backend refused"); } - if(!B.getDomainInfo(zonename, di)) { - throw ApiException("Creating domain '"+zonename.toString()+"' failed: lookup of domain ID failed"); + if (!B.getDomainInfo(zonename, di)) { + throw ApiException("Creating domain '" + zonename.toString() + "' failed: lookup of domain ID failed"); } di.backend->startTransaction(zonename, static_cast(di.id)); @@ -1885,11 +1939,11 @@ static void apiServerZonesPOST(HttpRequest* req, HttpResponse* resp) { // will be overridden by updateDomainSettingsFromDocument, if given in document. di.backend->setDomainMetadataOne(zonename, "SOA-EDIT-API", "DEFAULT"); - for(auto& rr : new_records) { // NOLINT(readability-identifier-length) + for (auto& rr : new_records) { // NOLINT(readability-identifier-length) rr.domain_id = static_cast(di.id); di.backend->feedRecord(rr, DNSName()); } - for(Comment& comment : new_comments) { + for (Comment& comment : new_comments) { comment.domain_id = static_cast(di.id); if (!di.backend->feedComment(comment)) { throw ApiException("Hosting backend does not support editing comments."); @@ -1914,7 +1968,8 @@ static void apiServerZonesPOST(HttpRequest* req, HttpResponse* resp) { } // list known zones -static void apiServerZonesGET(HttpRequest* req, HttpResponse* resp) { +static void apiServerZonesGET(HttpRequest* req, HttpResponse* resp) +{ UeberBackend B; // NOLINT(readability-identifier-length) DNSSECKeeper dk(&B); // NOLINT(readability-identifier-length) vector domains; @@ -1928,10 +1983,12 @@ static void apiServerZonesGET(HttpRequest* req, HttpResponse* resp) { if (B.getDomainInfo(zonename, di)) { domains.push_back(di); } - } else { + } + else { try { B.getAllDomains(&domains, true, true); // incl. serial and disabled - } catch(const PDNSException &e) { // NOLINT(readability-identifier-length) + } + catch (const PDNSException& e) { // NOLINT(readability-identifier-length) throw HttpInternalServerErrorException("Could not retrieve all domain information: " + e.reason); } } @@ -1947,13 +2004,14 @@ static void apiServerZonesGET(HttpRequest* req, HttpResponse* resp) { Json::array doc; doc.reserve(domains.size()); - for(const DomainInfo& di : domains) { + for (const DomainInfo& di : domains) { doc.push_back(getZoneInfo(di, with_dnssec ? &dk : nullptr)); } resp->setJsonBody(doc); } -static void apiServerZoneDetailPUT(HttpRequest* req, HttpResponse* resp) { +static void apiServerZoneDetailPUT(HttpRequest* req, HttpResponse* resp) +{ zoneFromId(req); // update domain contents and/or settings @@ -1985,7 +2043,7 @@ static void apiServerZoneDetailPUT(HttpRequest* req, HttpResponse* resp) { QType qtype; qtype = stringFromJson(rrset, "type"); if (qtype.getCode() == 0) { - throw ApiException("RRset "+qname.toString()+" IN "+stringFromJson(rrset, "type")+": unknown type given"); + throw ApiException("RRset " + qname.toString() + " IN " + stringFromJson(rrset, "type") + ": unknown type given"); } if (rrset["records"].is_array()) { uint32_t ttl = uintFromJson(rrset, "ttl"); @@ -2000,10 +2058,10 @@ static void apiServerZoneDetailPUT(HttpRequest* req, HttpResponse* resp) { throw ApiException("New RRsets are invalid: " + string(exc.what())); } - for(auto& rr : new_records) { // NOLINT(readability-identifier-length) + for (auto& rr : new_records) { // NOLINT(readability-identifier-length) rr.qname.makeUsLowerCase(); if (!rr.qname.isPartOf(zonename) && rr.qname != zonename) { - throw ApiException("RRset "+rr.qname.toString()+" IN "+rr.qtype.toString()+": Name is out of zone"); + throw ApiException("RRset " + rr.qname.toString() + " IN " + rr.qtype.toString() + ": Name is out of zone"); } apiCheckQNameAllowedCharacters(rr.qname.toString()); @@ -2024,11 +2082,11 @@ static void apiServerZoneDetailPUT(HttpRequest* req, HttpResponse* resp) { checkNewRecords(new_records, zonename); di.backend->startTransaction(zonename, static_cast(di.id)); - for(auto& rr : new_records) { // NOLINT(readability-identifier-length) + for (auto& rr : new_records) { // NOLINT(readability-identifier-length) rr.domain_id = static_cast(di.id); di.backend->feedRecord(rr, DNSName()); } - for(Comment& comment : new_comments) { + for (Comment& comment : new_comments) { comment.domain_id = static_cast(di.id); di.backend->feedComment(comment); } @@ -2036,7 +2094,8 @@ static void apiServerZoneDetailPUT(HttpRequest* req, HttpResponse* resp) { if (!haveSoa && (newKind == DomainInfo::Secondary || newKind == DomainInfo::Consumer)) { di.backend->setStale(di.id); } - } else { + } + else { // avoid deleting current zone contents di.backend->startTransaction(zonename, -1); } @@ -2051,21 +2110,23 @@ static void apiServerZoneDetailPUT(HttpRequest* req, HttpResponse* resp) { resp->status = 204; // No Content, but indicate success } -static void apiServerZoneDetailDELETE(HttpRequest* req, HttpResponse* resp) { +static void apiServerZoneDetailDELETE(HttpRequest* req, HttpResponse* resp) +{ zoneFromId(req); // delete domain di.backend->startTransaction(zonename, -1); try { - if(!di.backend->deleteDomain(zonename)) { - throw ApiException("Deleting domain '"+zonename.toString()+"' failed: backend delete failed/unsupported"); + if (!di.backend->deleteDomain(zonename)) { + throw ApiException("Deleting domain '" + zonename.toString() + "' failed: backend delete failed/unsupported"); } di.backend->commitTransaction(); g_zoneCache.remove(zonename); - } catch (...) { + } + catch (...) { di.backend->abortTransaction(); throw; } @@ -2079,17 +2140,20 @@ static void apiServerZoneDetailDELETE(HttpRequest* req, HttpResponse* resp) { resp->status = 204; // No Content: declare that the zone is gone now } -static void apiServerZoneDetailPATCH(HttpRequest* req, HttpResponse* resp) { +static void apiServerZoneDetailPATCH(HttpRequest* req, HttpResponse* resp) +{ zoneFromId(req); patchZone(B, zonename, di, req, resp); } -static void apiServerZoneDetailGET(HttpRequest* req, HttpResponse* resp) { +static void apiServerZoneDetailGET(HttpRequest* req, HttpResponse* resp) +{ zoneFromId(req); fillZone(B, zonename, resp, req); } -static void apiServerZoneExport(HttpRequest* req, HttpResponse* resp) { +static void apiServerZoneExport(HttpRequest* req, HttpResponse* resp) +{ zoneFromId(req); ostringstream ss; @@ -2097,28 +2161,26 @@ static void apiServerZoneExport(HttpRequest* req, HttpResponse* resp) { DNSResourceRecord rr; SOAData sd; di.backend->list(zonename, di.id); - while(di.backend->get(rr)) { + while (di.backend->get(rr)) { if (!rr.qtype.getCode()) continue; // skip empty non-terminals - ss << - rr.qname.toString() << "\t" << - rr.ttl << "\t" << - "IN" << "\t" << - rr.qtype.toString() << "\t" << - makeApiRecordContent(rr.qtype, rr.content) << - endl; + ss << rr.qname.toString() << "\t" << rr.ttl << "\t" + << "IN" + << "\t" << rr.qtype.toString() << "\t" << makeApiRecordContent(rr.qtype, rr.content) << endl; } if (req->accept_json) { - resp->setJsonBody(Json::object { { "zone", ss.str() } }); - } else { + resp->setJsonBody(Json::object{{"zone", ss.str()}}); + } + else { resp->headers["Content-Type"] = "text/plain; charset=us-ascii"; resp->body = ss.str(); } } -static void apiServerZoneAxfrRetrieve(HttpRequest* req, HttpResponse* resp) { +static void apiServerZoneAxfrRetrieve(HttpRequest* req, HttpResponse* resp) +{ zoneFromId(req); if (di.primaries.empty()) @@ -2129,16 +2191,18 @@ static void apiServerZoneAxfrRetrieve(HttpRequest* req, HttpResponse* resp) { resp->setSuccessResult("Added retrieval request for '" + zonename.toString() + "' from primary " + di.primaries.front().toLogString()); } -static void apiServerZoneNotify(HttpRequest* req, HttpResponse* resp) { +static void apiServerZoneNotify(HttpRequest* req, HttpResponse* resp) +{ zoneFromId(req); - if(!Communicator.notifyDomain(zonename, &B)) + if (!Communicator.notifyDomain(zonename, &B)) throw ApiException("Failed to add to the queue - see server log"); resp->setSuccessResult("Notification queued"); } -static void apiServerZoneRectify(HttpRequest* req, HttpResponse* resp) { +static void apiServerZoneRectify(HttpRequest* req, HttpResponse* resp) +{ zoneFromId(req); if (dk.isPresigned(zonename)) @@ -2185,12 +2249,11 @@ static void patchZone(UeberBackend& B, const DNSName& zonename, DomainInfo& di, QType qtype; qtype = stringFromJson(rrset, "type"); if (qtype.getCode() == 0) { - throw ApiException("RRset "+qname.toString()+" IN "+stringFromJson(rrset, "type")+": unknown type given"); + throw ApiException("RRset " + qname.toString() + " IN " + stringFromJson(rrset, "type") + ": unknown type given"); } - if(seen.count({qname, qtype, changetype})) - { - throw ApiException("Duplicate RRset "+qname.toString()+" IN "+qtype.toString()+" with changetype: "+changetype); + if (seen.count({qname, qtype, changetype})) { + throw ApiException("Duplicate RRset " + qname.toString() + " IN " + qtype.toString() + " with changetype: " + changetype); } seen.insert({qname, qtype, changetype}); @@ -2203,7 +2266,7 @@ static void patchZone(UeberBackend& B, const DNSName& zonename, DomainInfo& di, else if (changetype == "REPLACE") { // we only validate for REPLACE, as DELETE can be used to "fix" out of zone records. if (!qname.isPartOf(zonename) && qname != zonename) - throw ApiException("RRset "+qname.toString()+" IN "+qtype.toString()+": Name is out of zone"); + throw ApiException("RRset " + qname.toString() + " IN " + qtype.toString() + ": Name is out of zone"); bool replace_records = rrset["records"].is_array(); bool replace_comments = rrset["comments"].is_array(); @@ -2221,7 +2284,7 @@ static void patchZone(UeberBackend& B, const DNSName& zonename, DomainInfo& di, uint32_t ttl = uintFromJson(rrset, "ttl"); gatherRecords(rrset, qname, qtype, ttl, new_records); - for(DNSResourceRecord& rr : new_records) { + for (DNSResourceRecord& rr : new_records) { rr.domain_id = static_cast(di.id); if (rr.qtype.getCode() == QType::SOA && rr.qname == zonename) { soa_edit_done = increaseSOARecord(rr, soa_edit_api_kind, soa_edit_kind); @@ -2233,7 +2296,7 @@ static void patchZone(UeberBackend& B, const DNSName& zonename, DomainInfo& di, if (replace_comments) { gatherComments(rrset, qname, qtype, new_comments); - for(Comment& c : new_comments) { + for (Comment& c : new_comments) { c.domain_id = static_cast(di.id); } } @@ -2259,19 +2322,19 @@ static void patchZone(UeberBackend& B, const DNSName& zonename, DomainInfo& di, if (qtype == QType::NS || rr.qtype == QType::NS) ns_seen = true; if (qtype.getCode() != rr.qtype.getCode() - && (exclusiveEntryTypes.count(qtype.getCode()) != 0 - || exclusiveEntryTypes.count(rr.qtype.getCode()) != 0)) { + && (exclusiveEntryTypes.count(qtype.getCode()) != 0 + || exclusiveEntryTypes.count(rr.qtype.getCode()) != 0)) { // leave database handle in a consistent state while (di.backend->get(rr)) ; - throw ApiException("RRset "+qname.toString()+" IN "+qtype.toString()+": Conflicts with pre-existing RRset"); + throw ApiException("RRset " + qname.toString() + " IN " + qtype.toString() + ": Conflicts with pre-existing RRset"); } } if (dname_seen && ns_seen && qname != zonename) { - throw ApiException("RRset "+qname.toString()+" IN "+qtype.toString()+": Cannot have both NS and DNAME except in zone apex"); + throw ApiException("RRset " + qname.toString() + " IN " + qtype.toString() + ": Cannot have both NS and DNAME except in zone apex"); } if (!new_records.empty() && di.kind == DomainInfo::Consumer) { // Allow deleting all RRsets, just not modifying them. @@ -2313,8 +2376,8 @@ static void patchZone(UeberBackend& B, const DNSName& zonename, DomainInfo& di, fillSOAData(rr.content, sd); resp->headers["X-PDNS-New-Serial"] = std::to_string(sd.serial); } - - } catch(...) { + } + catch (...) { di.backend->abortTransaction(); throw; } @@ -2339,7 +2402,8 @@ static void patchZone(UeberBackend& B, const DNSName& zonename, DomainInfo& di, return; } -static void apiServerSearchData(HttpRequest* req, HttpResponse* resp) { +static void apiServerSearchData(HttpRequest* req, HttpResponse* resp) +{ string q = req->getvars["q"]; string sMax = req->getvars["max"]; string sObjectType = req->getvars["object_type"]; @@ -2376,45 +2440,40 @@ static void apiServerSearchData(HttpRequest* req, HttpResponse* resp) { else throw ApiException("object_type must be one of the following options: all, zone, record, comment"); - SimpleMatch sm(q,true); + SimpleMatch sm(q, true); UeberBackend B; vector domains; vector result_rr; vector result_c; - map zoneIdZone; - map::iterator val; + map zoneIdZone; + map::iterator val; Json::array doc; B.getAllDomains(&domains, false, true); - for(const DomainInfo& di: domains) - { + for (const DomainInfo& di : domains) { if ((objectType == ObjectType::ALL || objectType == ObjectType::ZONE) && ents < maxEnts && sm.match(di.zone)) { - doc.push_back(Json::object { - { "object_type", "zone" }, - { "zone_id", apiZoneNameToId(di.zone) }, - { "name", di.zone.toString() } - }); + doc.push_back(Json::object{ + {"object_type", "zone"}, + {"zone_id", apiZoneNameToId(di.zone)}, + {"name", di.zone.toString()}}); ents++; } zoneIdZone[di.id] = di; // populate cache } - if ((objectType == ObjectType::ALL || objectType == ObjectType::RECORD) && B.searchRecords(q, maxEnts, result_rr)) - { - for(const DNSResourceRecord& rr: result_rr) - { + if ((objectType == ObjectType::ALL || objectType == ObjectType::RECORD) && B.searchRecords(q, maxEnts, result_rr)) { + for (const DNSResourceRecord& rr : result_rr) { if (!rr.qtype.getCode()) continue; // skip empty non-terminals - auto object = Json::object { - { "object_type", "record" }, - { "name", rr.qname.toString() }, - { "type", rr.qtype.toString() }, - { "ttl", (double)rr.ttl }, - { "disabled", rr.disabled }, - { "content", makeApiRecordContent(rr.qtype, rr.content) } - }; + auto object = Json::object{ + {"object_type", "record"}, + {"name", rr.qname.toString()}, + {"type", rr.qtype.toString()}, + {"ttl", (double)rr.ttl}, + {"disabled", rr.disabled}, + {"content", makeApiRecordContent(rr.qtype, rr.content)}}; if ((val = zoneIdZone.find(rr.domain_id)) != zoneIdZone.end()) { object["zone_id"] = apiZoneNameToId(val->second.zone); object["zone"] = val->second.zone.toString(); @@ -2423,16 +2482,13 @@ static void apiServerSearchData(HttpRequest* req, HttpResponse* resp) { } } - if ((objectType == ObjectType::ALL || objectType == ObjectType::COMMENT) && B.searchComments(q, maxEnts, result_c)) - { - for(const Comment &c: result_c) - { - auto object = Json::object { - { "object_type", "comment" }, - { "name", c.qname.toString() }, - { "type", c.qtype.toString() }, - { "content", c.content } - }; + if ((objectType == ObjectType::ALL || objectType == ObjectType::COMMENT) && B.searchComments(q, maxEnts, result_c)) { + for (const Comment& c : result_c) { + auto object = Json::object{ + {"object_type", "comment"}, + {"name", c.qname.toString()}, + {"type", c.qtype.toString()}, + {"content", c.content}}; if ((val = zoneIdZone.find(c.domain_id)) != zoneIdZone.end()) { object["zone_id"] = apiZoneNameToId(val->second.zone); object["zone"] = val->second.zone.toString(); @@ -2444,7 +2500,8 @@ static void apiServerSearchData(HttpRequest* req, HttpResponse* resp) { resp->setJsonBody(doc); } -static void apiServerCacheFlush(HttpRequest* req, HttpResponse* resp) { +static void apiServerCacheFlush(HttpRequest* req, HttpResponse* resp) +{ DNSName canon = apiNameToDNSName(req->getvars["domain"]); if (g_zoneCache.isEnabled()) { @@ -2463,25 +2520,26 @@ static void apiServerCacheFlush(HttpRequest* req, HttpResponse* resp) { DNSSECKeeper::clearCaches(canon); // purge entire zone from cache, not just zone-level records. uint64_t count = purgeAuthCaches(canon.toString() + "$"); - resp->setJsonBody(Json::object { - { "count", (int) count }, - { "result", "Flushed cache." } - }); + resp->setJsonBody(Json::object{ + {"count", (int)count}, + {"result", "Flushed cache."}}); } static std::ostream& operator<<(std::ostream& os, StatType statType) { - switch (statType) - { - case StatType::counter: return os << "counter"; - case StatType::gauge: return os << "gauge"; + switch (statType) { + case StatType::counter: + return os << "counter"; + case StatType::gauge: + return os << "gauge"; }; return os << static_cast(statType); } -static void prometheusMetrics(HttpRequest* /* req */, HttpResponse* resp) { +static void prometheusMetrics(HttpRequest* /* req */, HttpResponse* resp) +{ std::ostringstream output; - for (const auto &metricName : S.getEntries()) { + for (const auto& metricName : S.getEntries()) { // Prometheus suggest using '_' instead of '-' std::string prometheusMetricName = "pdns_auth_" + boost::replace_all_copy(metricName, "-", "_"); @@ -2490,9 +2548,15 @@ static void prometheusMetrics(HttpRequest* /* req */, HttpResponse* resp) { output << prometheusMetricName << " " << S.read(metricName) << "\n"; } - output << "# HELP pdns_auth_info " << "Info from PowerDNS, value is always 1" << "\n"; - output << "# TYPE pdns_auth_info " << "gauge" << "\n"; - output << "pdns_auth_info{version=\"" << VERSION << "\"} " << "1" << "\n"; + output << "# HELP pdns_auth_info " + << "Info from PowerDNS, value is always 1" + << "\n"; + output << "# TYPE pdns_auth_info " + << "gauge" + << "\n"; + output << "pdns_auth_info{version=\"" << VERSION << "\"} " + << "1" + << "\n"; resp->body = output.str(); resp->headers["Content-Type"] = "text/plain"; @@ -2505,32 +2569,32 @@ void AuthWebServer::cssfunction(HttpRequest* /* req */, HttpResponse* resp) resp->headers["Content-Type"] = "text/css"; ostringstream ret; - ret<<"* { box-sizing: border-box; margin: 0; padding: 0; }"<body = ret.str(); resp->status = 200; } @@ -2539,7 +2603,7 @@ void AuthWebServer::webThread() { try { setThreadName("pdns/webserver"); - if(::arg().mustDo("api")) { + if (::arg().mustDo("api")) { d_ws->registerApiHandler("/api/v1/servers/localhost/cache/flush", apiServerCacheFlush, "PUT"); d_ws->registerApiHandler("/api/v1/servers/localhost/config", apiServerConfig, "GET"); d_ws->registerApiHandler("/api/v1/servers/localhost/search-data", apiServerSearchData, "GET"); @@ -2580,14 +2644,16 @@ void AuthWebServer::webThread() d_ws->registerApiHandler("/api", apiDiscovery, "GET"); } if (::arg().mustDo("webserver")) { - d_ws->registerWebHandler("/style.css", [this](HttpRequest *req, HttpResponse *resp){cssfunction(req, resp);}, "GET"); - d_ws->registerWebHandler("/", [this](HttpRequest *req, HttpResponse *resp){indexfunction(req, resp);}, "GET"); + d_ws->registerWebHandler( + "/style.css", [this](HttpRequest* req, HttpResponse* resp) { cssfunction(req, resp); }, "GET"); + d_ws->registerWebHandler( + "/", [this](HttpRequest* req, HttpResponse* resp) { indexfunction(req, resp); }, "GET"); d_ws->registerWebHandler("/metrics", prometheusMetrics, "GET"); } d_ws->go(); } - catch(...) { - g_log<