if (req->method == "GET") {
apiZoneCryptokeysGET(zonename, inquireKeyId, resp, &dk);
- } else if (req->method == "DELETE") {
+ } else if (req->method == "DELETE" && !::arg().mustDo("api-readonly")) {
if (inquireKeyId == -1)
throw HttpBadRequestException();
apiZoneCryptokeysDELETE(zonename, inquireKeyId, req, resp, &dk);
- } else if (req->method == "POST") {
+ } else if (req->method == "POST" && !::arg().mustDo("api-readonly")) {
apiZoneCryptokeysPOST(zonename, req, resp, &dk);
- } else if (req->method == "PUT") {
+ } else if (req->method == "PUT" && !::arg().mustDo("api-readonly")) {
if (inquireKeyId == -1)
throw HttpBadRequestException();
apiZoneCryptokeysPUT(zonename, inquireKeyId, req, resp, &dk);
}
}
+ /** Throws ApiException if records with duplicate name/type/content are present.
+ * NOTE: sorts records in-place.
+ */
+ static void checkDuplicateRecords(vector<DNSResourceRecord>& records) {
+ sort(records.begin(), records.end(),
+ [](const DNSResourceRecord& rec_a, const DNSResourceRecord& rec_b) -> bool {
+ return rec_a.qname.toString() > rec_b.qname.toString() || \
+ rec_a.qtype.getCode() > rec_b.qtype.getCode() || \
+ rec_a.content < rec_b.content;
+ }
+ );
+ DNSResourceRecord previous;
+ for(const auto& rec : records) {
+ if (previous.qtype == rec.qtype && previous.qname == rec.qname && previous.content == rec.content) {
+ throw ApiException("Duplicate record in RRset " + rec.qname.toString() + " IN " + rec.qtype.getName() + " with content \"" + rec.content + "\"");
+ }
+ previous = rec;
+ }
+ }
+
static void apiServerZones(HttpRequest* req, HttpResponse* resp) {
UeberBackend B;
DNSSECKeeper dk(&B);
auto document = req->json();
DNSName zonename = apiNameToDNSName(stringFromJson(document, "name"));
apiCheckNameAllowedCharacters(zonename.toString());
+ zonename.makeUsLowerCase();
bool exists = B.getDomainInfo(zonename, di);
if(exists)
}
for(auto& rr : new_records) {
+ rr.qname.makeUsLowerCase();
if (!rr.qname.isPartOf(zonename) && rr.qname != zonename)
throw ApiException("RRset "+rr.qname.toString()+" IN "+rr.qtype.getName()+": Name is out of zone");
apiCheckQNameAllowedCharacters(rr.qname.toString());
}
}
+ checkDuplicateRecords(new_records);
+
// no going back after this
if(!B.createDomain(zonename))
throw ApiException("Creating domain '"+zonename.toString()+"' failed");
rr.content = makeBackendRecordContent(rr.qtype, rr.content);
}
}
+ checkDuplicateRecords(new_records);
}
if (replace_comments) {