mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-11 07:40:00 -04:00
fix: dev: Fix a bug with template filename reuse
When a zone filename is defined in `named.conf` which will be
written to by the server - i.e., for secondary or dynamically updated
zones - there is a test at configuration time to ensure that the
filename is non-unique.
This test is run before the zone is actually created, so a zone
configured using a template may not have had its filename expanded
yet. This can cause a configuration to fail because, for example,
multiple zones appear to using the filename `$name.db`.
This has been fixed by adding a new function `dns_zone_expandzonefile()`
and calling it during the uniqueness check.
Merge branch 'each-template-file' into 'main'
See merge request isc-projects/bind9!11769
This commit is contained in:
commit
cf11b88e0e
8 changed files with 304 additions and 182 deletions
15
bin/tests/system/checkconf/bad-template-file-reuse.conf
Normal file
15
bin/tests/system/checkconf/bad-template-file-reuse.conf
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
template a {
|
||||
type secondary;
|
||||
primaries { 192.0.0.2; };
|
||||
file "$name.db";
|
||||
};
|
||||
|
||||
zone example {
|
||||
template a;
|
||||
};
|
||||
|
||||
zone other {
|
||||
type secondary;
|
||||
primaries { 192.0.0.2; };
|
||||
file "example.db";
|
||||
};
|
||||
17
bin/tests/system/checkconf/good-template-file-reuse.conf
Normal file
17
bin/tests/system/checkconf/good-template-file-reuse.conf
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
template a {
|
||||
type secondary;
|
||||
primaries { 192.0.0.2; };
|
||||
file "$name.db";
|
||||
};
|
||||
|
||||
zone one {
|
||||
template a;
|
||||
};
|
||||
|
||||
zone two {
|
||||
template a;
|
||||
};
|
||||
|
||||
zone three {
|
||||
template a;
|
||||
};
|
||||
|
|
@ -50,3 +50,17 @@ zone "present" {
|
|||
file "present.db";
|
||||
initial-file "example.db";
|
||||
};
|
||||
|
||||
template secondary {
|
||||
type secondary;
|
||||
primaries { 10.53.0.1; };
|
||||
file "$name.db";
|
||||
};
|
||||
|
||||
zone "extra1" {
|
||||
template secondary;
|
||||
};
|
||||
|
||||
zone "extra2" {
|
||||
template secondary;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -18,7 +18,13 @@ import pytest
|
|||
import isctest
|
||||
|
||||
pytestmark = pytest.mark.extra_artifacts(
|
||||
["ns2/copied.db", "ns2/present.db", "ns2/alternate.db"]
|
||||
[
|
||||
"ns2/copied.db",
|
||||
"ns2/present.db",
|
||||
"ns2/alternate.db",
|
||||
"ns2/extra1.db",
|
||||
"ns2/extra2.db",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1557,3 +1557,36 @@ dns_zone_getkeystores(dns_zone_t *zone);
|
|||
* Get the keystores pointer, it should never be NULL once the server is
|
||||
* initialized.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_zone_expandzonefile(isc_buffer_t *b, const char *filename,
|
||||
const dns_name_t *zonename, const char *viewname,
|
||||
const char *typename);
|
||||
/*%<
|
||||
* Expands the zone file name ('filename') using the inputs
|
||||
* 'zonename', 'viewname' and 'typename'. The expanded file name
|
||||
* is stored in the buffer 'b'. The follow expansions are available:
|
||||
*
|
||||
* - $name or "%s" to the zone name, in lowercase
|
||||
* - $type or "%t" to the zone type
|
||||
* - $view or "%v" to the view name
|
||||
* - $char1 or "%1" to the first character of the zone name
|
||||
* - $char2 or "%2" to the second character of the zone name (or a dot if
|
||||
* there is no second character)
|
||||
* - $char3 or "%3" to the third character of the zone name (or a dot if
|
||||
* there is no third character)
|
||||
* - $label1 or "%z" to the toplevel domain of the zone (or a dot if it is
|
||||
* the TLD)
|
||||
* - $label2 or "%y" to the next label under the toplevel domain (or a dot if
|
||||
* there is no next label)
|
||||
* - $label2 or "%x" to the next-next label under the toplevel domain (or a
|
||||
* dot if there is no next-next label)
|
||||
*
|
||||
* If 'viewname' is NULL, it is treated as an empty string.
|
||||
*
|
||||
* Requires:
|
||||
* \li 'b' to be non NULL.
|
||||
* \li 'filename' to be non NULL.
|
||||
* \li 'zonename' to be a valid name.
|
||||
* \li 'typename' to be non NULL.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -273,15 +273,23 @@ setstring(dns_zone_t *zone, char **field, const char *value) {
|
|||
}
|
||||
|
||||
typedef struct foundtoken foundtoken_t;
|
||||
typedef isc_result_t (*tokenparse_t)(const dns_zone_t *zone,
|
||||
typedef struct token_names token_names_t;
|
||||
typedef isc_result_t (*tokenparse_t)(const token_names_t *names,
|
||||
const foundtoken_t *token,
|
||||
isc_buffer_t *b);
|
||||
|
||||
struct foundtoken {
|
||||
const char *pos;
|
||||
size_t len;
|
||||
tokenparse_t parse;
|
||||
};
|
||||
|
||||
struct token_names {
|
||||
dns_name_t *zonename;
|
||||
const char *viewname;
|
||||
const char *typename;
|
||||
};
|
||||
|
||||
static int
|
||||
foundtoken_order(const void *a, const void *b) {
|
||||
/* sort char pointers in order of which occurs first in memory */
|
||||
|
|
@ -301,80 +309,62 @@ putmem(isc_buffer_t *b, const char *base, size_t length) {
|
|||
}
|
||||
|
||||
static isc_result_t
|
||||
tokenparse_type(const dns_zone_t *zone, const foundtoken_t *token,
|
||||
isc_buffer_t *b) {
|
||||
const char *typename = dns_zonetype_name(zone->type);
|
||||
|
||||
UNUSED(token);
|
||||
|
||||
return putmem(b, typename, strlen(typename));
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
tokenparse_name(const dns_zone_t *zone, const foundtoken_t *token,
|
||||
isc_buffer_t *b) {
|
||||
isc_result_t result;
|
||||
char buf[DNS_NAME_FORMATSIZE];
|
||||
dns_fixedname_t fn;
|
||||
dns_name_t *name = dns_fixedname_initname(&fn);
|
||||
|
||||
UNUSED(token);
|
||||
|
||||
result = dns_name_downcase(&zone->origin, name);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
dns_name_format(name, buf, sizeof(buf));
|
||||
result = putmem(b, buf, strlen(buf));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
tokenparse_view(const dns_zone_t *zone, const foundtoken_t *token,
|
||||
tokenparse_type(const token_names_t *names, const foundtoken_t *token,
|
||||
isc_buffer_t *b) {
|
||||
UNUSED(token);
|
||||
|
||||
return putmem(b, zone->view->name, strlen(zone->view->name));
|
||||
return putmem(b, names->typename, strlen(names->typename));
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
tokenparse_char(const dns_zone_t *zone, const foundtoken_t *token,
|
||||
tokenparse_name(const token_names_t *names,
|
||||
const foundtoken_t *token ISC_ATTR_UNUSED, isc_buffer_t *b) {
|
||||
char name[DNS_NAME_FORMATSIZE];
|
||||
|
||||
dns_name_format(names->zonename, name, sizeof(name));
|
||||
return putmem(b, name, strlen(name));
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
tokenparse_view(const token_names_t *names, const foundtoken_t *token,
|
||||
isc_buffer_t *b) {
|
||||
isc_result_t result;
|
||||
char buf[DNS_NAME_FORMATSIZE];
|
||||
dns_fixedname_t fn;
|
||||
dns_name_t *name = dns_fixedname_initname(&fn);
|
||||
UNUSED(token);
|
||||
|
||||
return putmem(b, names->viewname, strlen(names->viewname));
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
tokenparse_char(const token_names_t *names, const foundtoken_t *token,
|
||||
isc_buffer_t *b) {
|
||||
char name[DNS_NAME_FORMATSIZE];
|
||||
size_t chartokidx;
|
||||
char c;
|
||||
|
||||
result = dns_name_downcase(&zone->origin, name);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
dns_name_format(name, buf, sizeof(buf));
|
||||
dns_name_format(names->zonename, name, sizeof(name));
|
||||
|
||||
chartokidx = token->pos[token->len - 1] - '1';
|
||||
INSIST(chartokidx <= 2);
|
||||
if (chartokidx < strlen(buf)) {
|
||||
c = buf[chartokidx];
|
||||
if (chartokidx < strlen(name)) {
|
||||
c = name[chartokidx];
|
||||
} else {
|
||||
c = '.';
|
||||
}
|
||||
result = putmem(b, &c, 1);
|
||||
|
||||
return result;
|
||||
return putmem(b, &c, 1);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
tokenparse_label(const dns_zone_t *zone, const foundtoken_t *token,
|
||||
tokenparse_label(const token_names_t *names, const foundtoken_t *token,
|
||||
isc_buffer_t *b) {
|
||||
isc_result_t result;
|
||||
char buf[DNS_NAME_FORMATSIZE];
|
||||
dns_fixedname_t fn;
|
||||
dns_name_t *name = dns_fixedname_initname(&fn);
|
||||
unsigned int labels = dns_name_countlabels(&zone->origin);
|
||||
dns_fixedname_t ft;
|
||||
dns_name_t *target = dns_fixedname_initname(&ft);
|
||||
unsigned int labels;
|
||||
char labeltokidx;
|
||||
int ilabel = -1;
|
||||
|
||||
result = dns_name_fromstring(name, ".", NULL, 0, NULL);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
dns_name_copy(dns_rootname, target);
|
||||
labels = dns_name_countlabels(names->zonename);
|
||||
|
||||
labeltokidx = token->pos[token->len - 1];
|
||||
if (token->len == 2) {
|
||||
|
|
@ -389,23 +379,18 @@ tokenparse_label(const dns_zone_t *zone, const foundtoken_t *token,
|
|||
INSIST(labeltokidx >= '1' && labeltokidx <= '3');
|
||||
}
|
||||
|
||||
/*
|
||||
* Even if implicit, the root label counts as one label.
|
||||
*/
|
||||
if (labeltokidx == '1' || labeltokidx == 'z') {
|
||||
ilabel = labels - 2;
|
||||
ilabel = labels - 1;
|
||||
} else if (labeltokidx == '2' || labeltokidx == 'y') {
|
||||
ilabel = labels - 3;
|
||||
ilabel = labels - 2;
|
||||
} else if (labeltokidx == '3' || labeltokidx == 'x') {
|
||||
ilabel = labels - 4;
|
||||
ilabel = labels - 3;
|
||||
}
|
||||
|
||||
if (ilabel >= 0) {
|
||||
dns_name_getlabelsequence(&zone->origin, ilabel, 1, name);
|
||||
result = dns_name_downcase(name, name);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
dns_name_getlabelsequence(names->zonename, ilabel, 1, target);
|
||||
}
|
||||
dns_name_format(name, buf, sizeof(buf));
|
||||
dns_name_format(target, buf, sizeof(buf));
|
||||
result = putmem(b, buf, strlen(buf));
|
||||
|
||||
return result;
|
||||
|
|
@ -447,22 +432,33 @@ static const token_t tokens[] = {
|
|||
*
|
||||
* Cap the length at PATH_MAX.
|
||||
*/
|
||||
static void
|
||||
setfilename(dns_zone_t *zone, char **field, const char *value) {
|
||||
void
|
||||
dns_zone_expandzonefile(isc_buffer_t *b, const char *filename,
|
||||
const dns_name_t *zonename, const char *viewname,
|
||||
const char *typename) {
|
||||
isc_result_t result;
|
||||
foundtoken_t founds[ARRAY_SIZE(tokens)];
|
||||
char filename[PATH_MAX];
|
||||
isc_buffer_t b;
|
||||
dns_fixedname_t fz;
|
||||
size_t tags = 0;
|
||||
token_names_t names = { .zonename = dns_fixedname_initname(&fz),
|
||||
.viewname = viewname,
|
||||
.typename = typename };
|
||||
|
||||
if (value == NULL) {
|
||||
*field = NULL;
|
||||
return;
|
||||
REQUIRE(zonename != NULL);
|
||||
REQUIRE(filename != NULL);
|
||||
REQUIRE(typename != NULL);
|
||||
|
||||
if (viewname == NULL) {
|
||||
names.viewname = "";
|
||||
}
|
||||
|
||||
/* Normalize the name by converting to lower case */
|
||||
result = dns_name_downcase(zonename, names.zonename);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(tokens); i++) {
|
||||
const token_t *token = &tokens[i];
|
||||
const char *p = strcasestr(value, token->name);
|
||||
const char *p = strcasestr(filename, token->name);
|
||||
|
||||
if (p != NULL) {
|
||||
founds[tags++] =
|
||||
|
|
@ -473,34 +469,48 @@ setfilename(dns_zone_t *zone, char **field, const char *value) {
|
|||
}
|
||||
|
||||
if (tags == 0) {
|
||||
setstring(zone, field, value);
|
||||
return;
|
||||
putmem(b, filename, strlen(filename));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
isc_buffer_init(&b, filename, sizeof(filename));
|
||||
|
||||
/* sort the tag offsets in order of occurrence */
|
||||
qsort(founds, tags, sizeof(foundtoken_t), foundtoken_order);
|
||||
|
||||
const char *p = value;
|
||||
const char *p = filename;
|
||||
for (size_t i = 0; i < tags; i++) {
|
||||
foundtoken_t *token = &founds[i];
|
||||
|
||||
CHECK(putmem(&b, p, token->pos - p));
|
||||
CHECK(putmem(b, p, token->pos - p));
|
||||
|
||||
p = token->pos;
|
||||
INSIST(p != NULL);
|
||||
CHECK(token->parse(zone, token, &b));
|
||||
CHECK(token->parse(&names, token, b));
|
||||
|
||||
/* Advance the input pointer past the token */
|
||||
p += founds[i].len;
|
||||
}
|
||||
|
||||
const char *end = value + strlen(value);
|
||||
putmem(&b, p, end - p);
|
||||
const char *end = filename + strlen(filename);
|
||||
putmem(b, p, end - p);
|
||||
|
||||
cleanup:
|
||||
isc_buffer_putuint8(&b, 0);
|
||||
isc_buffer_putuint8(b, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
setfilename(dns_zone_t *zone, char **field, const char *value) {
|
||||
char filename[PATH_MAX];
|
||||
isc_buffer_t b;
|
||||
|
||||
if (value == NULL) {
|
||||
*field = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
isc_buffer_init(&b, filename, sizeof(filename));
|
||||
dns_zone_expandzonefile(&b, value, &zone->origin,
|
||||
zone->view != NULL ? zone->view->name : NULL,
|
||||
dns_zonetype_name(zone->type));
|
||||
setstring(zone, field, filename);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@
|
|||
#include <dns/rrl.h>
|
||||
#include <dns/secalg.h>
|
||||
#include <dns/ssu.h>
|
||||
#include <dns/zoneproperties.h>
|
||||
|
||||
#include <dst/dst.h>
|
||||
|
||||
|
|
@ -74,7 +75,9 @@
|
|||
static in_port_t dnsport = 53;
|
||||
|
||||
static isc_result_t
|
||||
fileexist(const cfg_obj_t *obj, isc_symtab_t *symtab, bool writeable);
|
||||
fileexist(const cfg_obj_t *obj, const dns_name_t *zonename,
|
||||
const char *viewname, const char *typename, isc_symtab_t *symtab,
|
||||
bool writeable, isc_mem_t *mctx);
|
||||
|
||||
static isc_result_t
|
||||
keydirexist(const cfg_obj_t *zcgf, const char *optname, dns_name_t *zname,
|
||||
|
|
@ -4186,7 +4189,9 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
|||
ztype == CFG_ZONE_MIRROR || ddns ||
|
||||
has_dnssecpolicy))
|
||||
{
|
||||
tresult = fileexist(fileobj, files, true);
|
||||
tresult = fileexist(fileobj, zname, viewname,
|
||||
dns_zonetype_name(ztype), files,
|
||||
true, mctx);
|
||||
if (tresult != ISC_R_SUCCESS && result == ISC_R_SUCCESS)
|
||||
{
|
||||
result = tresult;
|
||||
|
|
@ -4195,7 +4200,9 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
|||
(ztype == CFG_ZONE_PRIMARY ||
|
||||
ztype == CFG_ZONE_HINT))
|
||||
{
|
||||
tresult = fileexist(fileobj, files, false);
|
||||
tresult = fileexist(fileobj, zname, viewname,
|
||||
dns_zonetype_name(ztype), files,
|
||||
false, mctx);
|
||||
if (tresult != ISC_R_SUCCESS && result == ISC_R_SUCCESS)
|
||||
{
|
||||
result = tresult;
|
||||
|
|
@ -4396,20 +4403,33 @@ typedef enum symtab_file_type {
|
|||
} symtab_file_type_t;
|
||||
|
||||
static isc_result_t
|
||||
fileexist(const cfg_obj_t *obj, isc_symtab_t *symtab, bool writeable) {
|
||||
fileexist(const cfg_obj_t *obj, const dns_name_t *zonename,
|
||||
const char *viewname, const char *typename, isc_symtab_t *symtab,
|
||||
bool writeable, isc_mem_t *mctx) {
|
||||
isc_result_t result_ro, result_w;
|
||||
isc_symvalue_t symvalue_ro, symvalue_w;
|
||||
unsigned int line;
|
||||
const char *file;
|
||||
const char *filename = cfg_obj_asstring(obj);
|
||||
char buf[PATH_MAX];
|
||||
|
||||
/*
|
||||
* If the filename contains '$' or "%' characters, it's probably
|
||||
* a template file and should not be tested for uniqueness.
|
||||
*/
|
||||
if (strpbrk(filename, "%$") != NULL) {
|
||||
isc_buffer_t b;
|
||||
isc_buffer_init(&b, buf, sizeof(buf));
|
||||
dns_zone_expandzonefile(&b, filename, zonename, viewname,
|
||||
typename);
|
||||
filename = buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* Since symtab doesn't let us query the file type, we need to query
|
||||
* twice. Once per type.
|
||||
*/
|
||||
result_ro = isc_symtab_lookup(symtab, cfg_obj_asstring(obj), READ_ONLY,
|
||||
result_ro = isc_symtab_lookup(symtab, filename, READ_ONLY,
|
||||
&symvalue_ro);
|
||||
result_w = isc_symtab_lookup(symtab, cfg_obj_asstring(obj), WRITEABLE,
|
||||
&symvalue_w);
|
||||
result_w = isc_symtab_lookup(symtab, filename, WRITEABLE, &symvalue_w);
|
||||
|
||||
bool found_read_only = result_ro == ISC_R_SUCCESS;
|
||||
bool found_writable = result_w == ISC_R_SUCCESS;
|
||||
|
|
@ -4423,8 +4443,8 @@ fileexist(const cfg_obj_t *obj, isc_symtab_t *symtab, bool writeable) {
|
|||
? symvalue_ro
|
||||
: symvalue_w;
|
||||
|
||||
file = cfg_obj_file(symvalue.as_cpointer);
|
||||
line = cfg_obj_line(symvalue.as_cpointer);
|
||||
const char *file = cfg_obj_file(symvalue.as_cpointer);
|
||||
unsigned int line = cfg_obj_line(symvalue.as_cpointer);
|
||||
cfg_obj_log(obj, ISC_LOG_ERROR,
|
||||
"writeable file '%s': already in use: "
|
||||
"%s:%u",
|
||||
|
|
@ -4439,9 +4459,12 @@ fileexist(const cfg_obj_t *obj, isc_symtab_t *symtab, bool writeable) {
|
|||
isc_symvalue_t symvalue =
|
||||
(isc_symvalue_t){ .as_cpointer = obj };
|
||||
symtab_file_type_t type = writeable ? WRITEABLE : READ_ONLY;
|
||||
isc_result_t result =
|
||||
isc_symtab_define(symtab, cfg_obj_asstring(obj), type,
|
||||
symvalue, isc_symexists_reject);
|
||||
char *key = isc_mem_strdup(mctx, filename);
|
||||
isc_result_t result = isc_symtab_define(
|
||||
symtab, key, type, symvalue, isc_symexists_reject);
|
||||
if (result == ISC_R_EXISTS) {
|
||||
isc_mem_free(mctx, key);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -6205,7 +6228,7 @@ isccfg_check_namedconf(const cfg_obj_t *config, unsigned int flags,
|
|||
* case sensitive. This will prevent people using FOO.DB and foo.db
|
||||
* on case sensitive file systems but that shouldn't be a major issue.
|
||||
*/
|
||||
isc_symtab_create(mctx, NULL, NULL, false, &files);
|
||||
isc_symtab_create(mctx, freekey, mctx, false, &files);
|
||||
isc_symtab_create(mctx, freekey, mctx, false, &keydirs);
|
||||
isc_symtab_create(mctx, freekey, mctx, true, &inview);
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
#include <tests/dns.h>
|
||||
|
||||
typedef struct {
|
||||
const char *name, *input, *expected;
|
||||
const char *name, *view, *type, *input, *expected;
|
||||
} zonefile_test_params_t;
|
||||
|
||||
static int
|
||||
|
|
@ -50,103 +50,106 @@ teardown_test(void **state) {
|
|||
}
|
||||
|
||||
ISC_LOOP_TEST_IMPL(filename) {
|
||||
isc_result_t result;
|
||||
dns_zone_t *zone = NULL;
|
||||
isc_buffer_t b;
|
||||
dns_fixedname_t of;
|
||||
dns_name_t *origin = dns_fixedname_initname(&of);
|
||||
char buf[PATH_MAX];
|
||||
const zonefile_test_params_t tests[] = {
|
||||
{ "example.COM", "$name", "example.com" },
|
||||
{ "example.COM", "$name.db", "example.com.db" },
|
||||
{ "example.COM", "./dir/$name.db", "./dir/example.com.db" },
|
||||
{ "example.COM", "%s", "example.com" },
|
||||
{ "example.COM", "%s.db", "example.com.db" },
|
||||
{ "example.COM", "./dir/%s.db", "./dir/example.com.db" },
|
||||
{ "example.COM", "$type", "primary" },
|
||||
{ "example.COM", "$type-file", "primary-file" },
|
||||
{ "example.COM", "./dir/$type", "./dir/primary" },
|
||||
{ "example.COM", "./$type/$name.db",
|
||||
{ "example.COM", "local", "primary", "$name", "example.com" },
|
||||
{ "example.COM", "local", "primary", "$name.db",
|
||||
"example.com.db" },
|
||||
{ "example.COM", "local", "primary", "./dir/$name.db",
|
||||
"./dir/example.com.db" },
|
||||
{ "example.COM", "local", "primary", "%s", "example.com" },
|
||||
{ "example.COM", "local", "primary", "%s.db",
|
||||
"example.com.db" },
|
||||
{ "example.COM", "local", "primary", "./dir/%s.db",
|
||||
"./dir/example.com.db" },
|
||||
{ "example.COM", "local", "primary", "$type", "primary" },
|
||||
{ "example.COM", "local", "primary", "$type-file",
|
||||
"primary-file" },
|
||||
{ "example.COM", "local", "primary", "./dir/$type",
|
||||
"./dir/primary" },
|
||||
{ "example.COM", "local", "secondary", "./dir/$type",
|
||||
"./dir/secondary" },
|
||||
{ "example.COM", "local", "primary", "./$type/$name.db",
|
||||
"./primary/example.com.db" },
|
||||
{ "example.COM", "%t", "primary" },
|
||||
{ "example.COM", "%t-file", "primary-file" },
|
||||
{ "example.COM", "./dir/%t", "./dir/primary" },
|
||||
{ "example.COM", "./%t/%s.db", "./primary/example.com.db" },
|
||||
{ "example.COM", "./$TyPe/$NAmE.db",
|
||||
{ "example.COM", "local", "primary", "%t", "primary" },
|
||||
{ "example.COM", "local", "primary", "%t-file",
|
||||
"primary-file" },
|
||||
{ "example.COM", "local", "primary", "./dir/%t",
|
||||
"./dir/primary" },
|
||||
{ "example.COM", "local", "primary", "./%t/%s.db",
|
||||
"./primary/example.com.db" },
|
||||
{ "example.COM", "./$name/$type", "./example.com/primary" },
|
||||
{ "example.COM", "$name.$type", "example.com.primary" },
|
||||
{ "example.COM", "$type$name", "primaryexample.com" },
|
||||
{ "example.COM", "$type$type", "primary$type" },
|
||||
{ "example.COM", "$name$name", "example.com$name" },
|
||||
{ "example.COM", "typename", "typename" },
|
||||
{ "example.COM", "$view", "local" },
|
||||
{ "example.COM", "%v", "local" },
|
||||
{ "example.COM", "./$type/$view-$name.db",
|
||||
{ "example.COM", "local", "secondary", "./%t/%s.db",
|
||||
"./secondary/example.com.db" },
|
||||
{ "example.COM", "local", "primary", "./$TyPe/$NAmE.db",
|
||||
"./primary/example.com.db" },
|
||||
{ "example.COM", "local", "primary", "./$name/$type",
|
||||
"./example.com/primary" },
|
||||
{ "example.COM", "local", "primary", "$name.$type",
|
||||
"example.com.primary" },
|
||||
{ "example.COM", "local", "primary", "$type$name",
|
||||
"primaryexample.com" },
|
||||
{ "example.COM", "local", "primary", "$type$type",
|
||||
"primary$type" },
|
||||
{ "example.COM", "local", "primary", "$name$name",
|
||||
"example.com$name" },
|
||||
{ "example.COM", "local", "primary", "typename", "typename" },
|
||||
{ "example.COM", "local", "primary", "$view", "local" },
|
||||
{ "example.COM", NULL, "primary", "$view", "" },
|
||||
{ "example.COM", "local", "primary", "%v", "local" },
|
||||
{ "example.COM", "local", "primary", "./$type/$view-$name.db",
|
||||
"./primary/local-example.com.db" },
|
||||
{ "example.COM", "./$view/$type-$name.db",
|
||||
{ "example.COM", "local", "primary", "./$view/$type-$name.db",
|
||||
"./local/primary-example.com.db" },
|
||||
{ "example.COM", "./$name/$view-$type.db",
|
||||
{ "example.COM", "local", "primary", "./$name/$view-$type.db",
|
||||
"./example.com/local-primary.db" },
|
||||
{ "example.COM", "./%s/%v-%t.db",
|
||||
{ "example.COM", "local", "primary", "./%s/%v-%t.db",
|
||||
"./example.com/local-primary.db" },
|
||||
{ "example.COM", "", "" },
|
||||
{ "example.COM", "$char1", "e" },
|
||||
{ "example.COM", "$char2", "x" },
|
||||
{ "example.COM", "$char3", "a" },
|
||||
{ "example.COM", "%1", "e" },
|
||||
{ "example.COM", "%2", "x" },
|
||||
{ "example.COM", "%3", "a" },
|
||||
{ "example.COM", "$label1", "com" },
|
||||
{ "example.COM", "$label2", "example" },
|
||||
{ "example.COM", "$label3", "." },
|
||||
{ "example.COM", "%z", "com" },
|
||||
{ "example.COM", "%y", "example" },
|
||||
{ "example.COM", "%x", "." },
|
||||
{ "example", "$label1", "example" },
|
||||
{ "example", "$label2", "." },
|
||||
{ "example", "$label3", "." },
|
||||
{ "a.b.c.d.e", "$label1", "e" },
|
||||
{ "a.b.c.d.e", "$label2", "d" },
|
||||
{ "a.b.c.d.e", "$label3", "c" },
|
||||
{ "a.b.c", "$char1", "a" },
|
||||
{ "a.b.c", "$char2", "." },
|
||||
{ "a.b.c", "$char3", "b" },
|
||||
{ "a.b.c", "%1", "a" },
|
||||
{ "a.b.c", "%2", "." },
|
||||
{ "a.b.c", "%3", "b" },
|
||||
{ "a", "%1", "a" },
|
||||
{ "a", "%2", "." },
|
||||
{ "a", "%3", "." },
|
||||
{ "a.b.c.d", "%1$char2%3$label1%x", "a.bdb" }
|
||||
{ "example.COM", "local", "primary", "", "" },
|
||||
{ "example.COM", "local", "primary", "$char1", "e" },
|
||||
{ "example.COM", "local", "primary", "$char2", "x" },
|
||||
{ "example.COM", "local", "primary", "$char3", "a" },
|
||||
{ "example.COM", "local", "primary", "%1", "e" },
|
||||
{ "example.COM", "local", "primary", "%2", "x" },
|
||||
{ "example.COM", "local", "primary", "%3", "a" },
|
||||
{ "example.COM", "local", "primary", "$label1", "com" },
|
||||
{ "example.COM", "local", "primary", "$label2", "example" },
|
||||
{ "example.COM", "local", "primary", "$label3", "." },
|
||||
{ "example.COM", "local", "primary", "%z", "com" },
|
||||
{ "example.COM", "local", "primary", "%y", "example" },
|
||||
{ "example.COM", "local", "primary", "%x", "." },
|
||||
{ "example", "local", "primary", "$label1", "example" },
|
||||
{ "example", "local", "primary", "$label2", "." },
|
||||
{ "example", "local", "primary", "$label3", "." },
|
||||
{ "a.b.c.d.e", "local", "primary", "$label1", "e" },
|
||||
{ "a.b.c.d.e", "local", "primary", "$label2", "d" },
|
||||
{ "a.b.c.d.e", "local", "primary", "$label3", "c" },
|
||||
{ "a.b.c", "local", "primary", "$char1", "a" },
|
||||
{ "a.b.c", "local", "primary", "$char2", "." },
|
||||
{ "a.b.c", "local", "primary", "$char3", "b" },
|
||||
{ "a.b.c", "local", "primary", "%1", "a" },
|
||||
{ "a.b.c", "local", "primary", "%2", "." },
|
||||
{ "a.b.c", "local", "primary", "%3", "b" },
|
||||
{ "a", "local", "primary", "%1", "a" },
|
||||
{ "a", "local", "primary", "%2", "." },
|
||||
{ "a", "local", "primary", "%3", "." },
|
||||
{ "a.b.c.d", "local", "primary", "%1$char2%3$label1%x",
|
||||
"a.bdb" }
|
||||
};
|
||||
|
||||
dns_view_t *view = NULL;
|
||||
result = dns_test_makeview("local", false, false, &view);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(tests); i++) {
|
||||
result = dns_test_makezone(tests[i].name, &zone, view, false);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
dns_zone_setview(zone, view);
|
||||
dns_zone_setfile(zone, tests[i].input, NULL,
|
||||
dns_masterformat_text,
|
||||
&dns_master_style_default);
|
||||
assert_string_equal(dns_zone_getfile(zone), tests[i].expected);
|
||||
|
||||
dns_zone_detach(&zone);
|
||||
isc_buffer_init(&b, buf, sizeof(buf));
|
||||
dns_test_namefromstring(tests[i].name, &of);
|
||||
dns_zone_expandzonefile(&b, tests[i].input, origin,
|
||||
tests[i].view, tests[i].type);
|
||||
assert_string_equal(buf, tests[i].expected);
|
||||
}
|
||||
|
||||
/* use .COM here to test that the name is correctly downcased */
|
||||
result = dns_test_makezone("example.COM", &zone, view, false);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
dns_zone_setview(zone, view);
|
||||
dns_view_detach(&view);
|
||||
|
||||
/* test PATH_MAX overrun */
|
||||
char longname[PATH_MAX] = { 0 };
|
||||
memset(longname, 'x', sizeof(longname) - 1);
|
||||
dns_zone_setfile(zone, longname, NULL, dns_masterformat_text,
|
||||
&dns_master_style_default);
|
||||
assert_string_equal(dns_zone_getfile(zone), longname);
|
||||
|
||||
/*
|
||||
* overwrite the beginning of the long name with $name. when
|
||||
|
|
@ -154,13 +157,14 @@ ISC_LOOP_TEST_IMPL(filename) {
|
|||
* still be capped at PATH_MAX characters.
|
||||
*/
|
||||
memmove(longname, "$name", 5);
|
||||
dns_zone_setfile(zone, longname, NULL, dns_masterformat_text,
|
||||
&dns_master_style_default);
|
||||
assert_int_equal(strlen(longname), PATH_MAX - 1);
|
||||
memmove(longname, "example.com", 11);
|
||||
assert_string_equal(dns_zone_getfile(zone), longname);
|
||||
|
||||
dns_zone_detach(&zone);
|
||||
isc_buffer_init(&b, buf, sizeof(buf));
|
||||
dns_test_namefromstring("example.COM", &of);
|
||||
dns_zone_expandzonefile(&b, longname, origin, "local", "primary");
|
||||
memmove(longname, "example.com", 11);
|
||||
assert_string_equal(buf, longname);
|
||||
|
||||
isc_loopmgr_shutdown();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue