Only one variant per zone may appear in a view; setting a new zone variant will
replace the previous one in the view.
+View names are case-sensitive and may be composed of letters, digits, spaces,
+as well as `-` (dash), `.` (dot) and `_` (underscore). They are not allowed to
+start with a dot or a space.
+
Resolution Algorithm
--------------------
src_dir / 'bindparserclasses.hh',
src_dir / 'burtle.hh',
src_dir / 'cachecleaner.hh',
+ src_dir / 'check-zone.cc',
+ src_dir / 'check-zone.hh',
src_dir / 'circular_buffer.hh',
src_dir / 'comment.hh',
src_dir / 'communicator.cc',
bindparser.cc \
burtle.hh \
cachecleaner.hh \
+ check-zone.cc check-zone.hh \
circular_buffer.hh \
comment.hh \
communicator.cc communicator.hh \
bindlexer.l \
bindparser.yy \
cachecleaner.hh \
+ check-zone.cc check-zone.hh \
circular_buffer.hh \
credentials.cc credentials.hh \
dbdnsseckeeper.cc \
--- /dev/null
+/*
+ * This file is part of PowerDNS or dnsdist.
+ * Copyright -- PowerDNS.COM B.V. and its contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * In addition, for the avoidance of any doubt, permission is granted to
+ * link this program with OpenSSL and to (re)distribute the binaries
+ * produced as the result of such linking.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "dns.hh"
+#include "dnsrecords.hh"
+
+#include "check-zone.hh"
+
+namespace Check
+{
+
+bool validateViewName(std::string_view name, std::string& error)
+{
+ if (name.empty()) {
+ error = "Empty view names are not allowed";
+ return false;
+ }
+
+ if (auto pos = name.find_first_not_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 _-."); pos != std::string_view::npos) {
+ error = std::string("View name contains forbidden character '") + name[pos] + "' at position " + std::to_string(pos);
+ return false;
+ }
+
+ if (name[0] == '.') {
+ error = "View names are not allowed to start with a dot";
+ return false;
+ }
+
+ if (name[0] == ' ') {
+ error = "View names are not allowed to start with a space";
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace Check
--- /dev/null
+/*
+ * This file is part of PowerDNS or dnsdist.
+ * Copyright -- PowerDNS.COM B.V. and its contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * In addition, for the avoidance of any doubt, permission is granted to
+ * link this program with OpenSSL and to (re)distribute the binaries
+ * produced as the result of such linking.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+// These validation/verification routines are used by both pdnsutil and
+// the pdns_server REST API.
+// They build error messages, if any, into an object provided by the caller
+// (preferrably a container if it makes sense to report multiple errors);
+// it's up to each caller to decide how to report such errors.
+
+namespace Check
+{
+
+// Validate a view name. Although view names never appear on the wire, we
+// restrict them to [a-zA-Z0-9-_. ], with empty names or names with leading
+// whitespace or a leading dot forbidden.
+bool validateViewName(std::string_view name, std::string& error);
+
+} // namespace Check
#include <csignal>
#include <sys/wait.h>
+#include "check-zone.hh"
#include "credentials.hh"
#include "dnsseckeeper.hh"
#include "dnssecinfra.hh"
UtilBackend B("default"); //NOLINT(readability-identifier-length)
+ if ((B.getCapabilities() & DNSBackend::CAP_VIEWS) == 0) {
+ cerr << "None of the configured backends support views." << endl;
+ return 1;
+ }
+
vector<ZoneName> ret;
B.viewListZones(cmds.at(0), ret);
UtilBackend B("default"); //NOLINT(readability-identifier-length)
+ if ((B.getCapabilities() & DNSBackend::CAP_VIEWS) == 0) {
+ // Don't complain about the lack of view support in this case, but
+ // don't list anything either.
+ return 0;
+ }
+
vector<string> ret;
B.viewList(ret);
UtilBackend B("default"); //NOLINT(readability-identifier-length)
+ if ((B.getCapabilities() & DNSBackend::CAP_VIEWS) == 0) {
+ cerr << "None of the configured backends support views." << endl;
+ return 1;
+ }
+
string view{cmds.at(0)};
+ string error;
+ if (!Check::validateViewName(view, error)) {
+ cerr << error << "." << endl;
+ return 1;
+ }
ZoneName zone{cmds.at(1)};
if (!B.viewAddZone(view, zone)) {
cerr<<"Operation failed."<<endl;
UtilBackend B("default"); //NOLINT(readability-identifier-length)
+ if ((B.getCapabilities() & DNSBackend::CAP_VIEWS) == 0) {
+ cerr << "None of the configured backends support views." << endl;
+ return 1;
+ }
+
string view{cmds.at(0)};
+ string error;
+ if (!Check::validateViewName(view, error)) {
+ cerr << error << "." << endl;
+ return 1;
+ }
ZoneName zone{cmds.at(1)};
if (!B.viewDelZone(view, zone)) {
cerr<<"Operation failed."<<endl;
UtilBackend B("default"); //NOLINT(readability-identifier-length)
+ if ((B.getCapabilities() & DNSBackend::CAP_VIEWS) == 0) {
+ cerr << "None of the configured backends support views." << endl;
+ return 1;
+ }
+
vector<pair<Netmask, string> > ret;
B.networkList(ret);
UtilBackend B("default"); //NOLINT(readability-identifier-length)
+ if ((B.getCapabilities() & DNSBackend::CAP_VIEWS) == 0) {
+ cerr << "None of the configured backends support views." << endl;
+ return 1;
+ }
+
Netmask net{cmds.at(0)};
string view{};
if (cmds.size() > 1) {
#include "auth-zonecache.hh"
#include "threadname.hh"
#include "tsigutils.hh"
+#include "check-zone.hh"
using json11::Json;
throw ApiException("Zone " + zonename.toString() + " does not exist");
}
std::string view{req->parameters["view"]};
+ std::string error;
+ if (!Check::validateViewName(view, error)) {
+ throw ApiException(error);
+ }
if (!domainInfo.backend->viewAddZone(view, zonename)) {
throw ApiException("Failed to add " + zonename.toString() + " to view " + view);
{
ZoneData zoneData{req};
std::string view{req->parameters["view"]};
+ std::string error;
+ if (!Check::validateViewName(view, error)) {
+ throw ApiException(error);
+ }
if (!zoneData.domainInfo.backend->viewDelZone(view, zoneData.zoneName)) {
throw ApiException("Failed to remove " + zoneData.zoneName.toString() + " from view " + view);
-Operation failed.
+None of the configured backends support views.