instead of having sockaddr and netaddr members in the cfg_obj->value
union, we now just keep pointers, and allocate memory when parsing
these types. this reduces the size of cfg_obj_t from 112 to 80 bytes.
instead of using an opaque ns_cfgctx pointer to store the configuration
data to be used by addzone and modzone, there are now fields in the
dns_view object to store the view configuration and LMDB database
environment. the global configuration is now stored in the named_server
object, along with the ACL context.
In order to harden `cfg_obj_t` usage now the configuration tree is
manipulated in various ways (cloned, merged, etc.), this introduce the
VALID_CFGOBJ macro to check the validity of a `cfg_obj_t` node.
Since the builtin trust-anchors are now called `builtin-trust-anchors`,
delv needs specific handling in order to be able to parse those when
they are used.
Before, delv was simply parsing a single clause (either in the case of
an overriden trust-anchors value from bindkeys file or by simply reading
the builtin value). But since the name changed, the same code can't be
shared and the builtin version is expected to be in a map.
Since the effective configuration tree is a "merged" configuration tree
from the user and the default configurations, the effective configuration
provides a unique configuration tree used by apply_confiuration() to
configure the server.
However, there is one specific case where the configuration code needs
to differentiate whether the configuration originally came from the
default or the user configuration: the trust-anchors. This is because
the default trust-anchors _have_ to be those for the root zone, and the
one provided by the user can be for any zone. A check enforces this.
In order to keep this difference visible from the configuration code,
with a unique configuration tree, we now introduce a default-only
`builtin-trust-anchors` statement which holds the builtin root
trust-anchors. It can't be used from the user configuration (this would
raise an error), hence it is not documented.
There are multiple check-names options provided in the default
configuration, and they must "complete" those provided by the user.
This is now handled when building the effective tree.
The prefetch statement can be overriden by the user, but the user might
specify the prefetch without the trigger value, which needs to be
pulled from the default configuration. Handle this case by directly
getting the default value if needed from the default configuration when
building the effective configuration tree.
Also take care of keeping the values inside their bounds, and simplify
the server configuration code which then just have to read effective
configuration values.
Default dnssec-policies are not overridden by user-provided ones. Add
this specific case to make sure those are kept, and also ensure that the
default dnssec-policy is always in the first position (which is an
implicit requirement in the existing implementation).
Also simplify the server configuration code, as it only needs to build
the list of dnssec-policy based on the effective config list.
User specified views don't override default views. In particular, the
_bind/CH view is still active. However, the order is important: if the
user defines a foo/CH view, it must be able to override _bind/CH by
matching clients first (this is how the view is documented).
The server configuration code is now simpler; it only has to build the
views based on the effective view list, and only creates the _default
view if there are no explicit views created by the user.
Implement the specific rules of ACL inheritance when buiding the
effective configuration. As those rules are directly implemented in the
configuration tree, they are removed from `apply_configuation`.
Add the entry point of the logic to merge the user and the default
configuration, called cfg_effective_config(). This function takes a user
configuration and a default configuration. It internally clones the user
configuration tree, then walks through the clauses recursively applying
default values if they are missing.
The newly built configuration tree, called the effective configuration
tree, is then returned.
Currently this is just the basic mechanism which is implemented (i.e.
enable to walk from clause to clause, goes into a nested clause, and so
on). The next commits will introduce the implementation of
clause-specific merge functions in order to preserve the existing
named.conf semantics.
In order to handle specific cases when merging configurations (i.e.
some specific clauses which require specific handling, not just
overriding values for instance), the cfg_clausedef_t includes an
optional merge method.
The merge function is NULL by default. If it is defined for a given
clause, and this clause is defined in both the user and default
configurations, the merge function is then called with both the user and
default clause instances. It's up the the implementation of that function
do to anything needed to keep the correct named.conf semantic.
cfg_map_addclone() is a variant of cfg_map_add which internally clones
an object and adds it to a map. It ensures that the object is an
implicit list if the map clause has the CFG_CLAUSEFLAG_MULTI set
cfg_list_addclone() clones a list (internally cloning each individual
element) and appends or preprends it to an existing target list.
Both of these will be needed to merge the default configuration
with the user configuration.
In order to make upcoming configuration tree changes easier, the
cfg_map_firstclause() and _nextclause() functions have been changed
to return the clause itself rather than only the clause name.
"max-cache-size default;" is allowed, according to the documentation
and the parser, but when it's configured, named crashes due to an
INSIST that the only legal string value is "unlimited". this has
been fied.
the configuration has also been simplified. previously, we checked for
max-cache-size in view and options, then determined whether to look in
the global default options based on whether the view had recursion set.
the default value set there was only applicable to views with recursion.
now, the default is an explicit "default", which affects views with
and without recursion in different ways.
the cfg type for "max-cache-size" has been changed from
cfg_type_sizeorpercent to cfg_type_maxcachesize.
Introduce `cfg_obj_clone` which takes a `cfg_obj_t` node and clones it.
it allocates a new node, copies its scalar values and recursively
allocates child nodes, copying their scalar values as well and so on.
Internally, a new method `cfg_copyfunc_t` copy is added in `cfg_rep_t`,
which enables implementing a copy function specific for each
representation type a node can hold.
In cfg_parse_buffer and cfg_parse_file 'pctx' was being checked
for being non-NULL when it was guarenteed to be non-NULL. This
raised Coverity issues ID 637688 and ID 637689.
change_directory() now lives in libisccfg. when it was moved,
the logging behavior changed: previously it had been logged
by named only, in the general logging category, and without the
named.conf filename and line number. it was not logged by
named-checkconf. this behavior has now been restored.
Since the `file` property of cfg_obj_t can now be null (instead of
"none"), cfg_obj_t would take a fallback flow where the line was not
logged. This fixes it.
Also, add the log line when parser_complain is called and `file` is null
(which might happend when parsing buffer only) to also include the line
number.
- several functions that can no longer fail have been changed to
type void, and unnecessary 'cleanup' sections were removed
- renamed cfg_create_obj() to cfg_obj_create(), and cfg_create_tuple()
to cfg_tuple_create(), to match typical nomenclature.
- fixed a memory leak bug, in which an element could be removed
from a list in delete_zoneconf() without being freed. this has
been addressed by adding a cfg_list_unlink() function.
list elements are now allocated based on the list they will
be stored in, using the same mctx.
- the cfg_parser_create() and cfg_parser_destroy() calls are no
longer used outside parser.c, so they are now static functions
- cfg_parser_attach(), cfg_parser_reset(), and cfg_parser_setflags()
are no longer used at all, and have been removed.
- cfg_parser_mapadd() has been renamed for clarity to cfg_map_add().
Instead of (1) allocating a parser, (2) parsing a file/buffer then (3)
freeing the parser, the parser is now internally created/destroyed from
within the `cfg_parse_*` functions. This simplifies a lot the use cases,
especially around the error cases where the parser needs to be freed in
a cleanup goto.
The only trick was the parser callback mechanism, which would previously
have been set up between steps 1 and 2. Since it's never been used for
any purpose other than the "directory" option, the chdir call has now
been moved inside the parser and the generic callback mechanism has been
removed, replacing CFG_CLAUSEFLAG_CALLBACK with CFG_CLAUSEFLAG_CHDIR.
cfg_obj_t doesn't store a pointer to its a parser context anymore,
and does not depend on the parser's lifecycle. Instead, it stores a
reference to its own memory context (and in principle, each node
could have different memory context). This also slightly simplifies
the _destroy API as there is no need to pass a context through it
anymore.
In order to reduce the lifecycle dependency of a `cfg_obj_t` on its
parser, the `file` field needs its own reference count, so it isn't
deleted when the parser is. It is now stored as a subsidiary
`cfg_obj_t` object of type string.
When generating a new key, dnssec-keygen checks for possible
key ID collisions with existing keys. The dnssec.c:findmatchingkeys()
function, which is supposed to get the list of the existing keys,
fails to do that for the existing KEY rrtype keys (i.e. generated
using 'dnssec-keygen -T KEY') because it doesn't pass down to the
dst_key_fromnamedfile() -> dst_key_read_public() functions the type
of the keys it's interested in. Fix the issue by introducing a new
function parameter which tells in which type of keys the caller is
currently interested in.
Since the "tkey-gssapi-credential" statement has been previously
deprecated, mark it as ancient and remove all code related to it:
- The code processing the "tkey-gssapi-credential" statement in the
configuration is the only user of the dst_gssapi_acquirecred() and
dst_gssapi_releasecred() functions, so remove them along with their
static helper functions and a backup definition of the
GSS_KRB5_MECHANISM macro.
- When calling gss_accept_sec_context(), pass GSS_C_NO_CREDENTIAL
instead of the credential acquired by gss_acquire_cred().
(Previously, NULL was passed when "tkey-gssapi-credential" was not
specified. Kerberos headers define GSS_C_NO_CREDENTIAL as
(gss_cred_id_t) 0, so the logic was effectively the same, but using
the GSS_C_NO_CREDENTIAL macro is more appropriate.) This renders
the 'cred' parameter for dst_gssapi_acceptctx() redundant, so remove
it from the prototype of the latter. (Contrary to what the
documentation for dst_gssapi_acceptctx() claims,
dst_gssapi_releasecred() does not need to subsequently be called to
free the GSS-API context; a dst_gssapi_deletectx() call in
gssapi_destroy() takes care of that when the dynamically generated
TSIG key is destroyed.)
- Remove the 'gsscred' member from struct dns_tkeyctx, along with its
related dns_gss_cred_id_t typedef.
Update the relevant sections of the ARM and code comments accordingly.
This makes the "tkey-gssapi-keytab" statement the only way to set up
GSS-TSIG in named.
Remove redundant code from bin/named/tkeyconf.c while at it.
The type `ns_pluginregister_ctx_t` was initially added to pass plugin
contextual data when the plugin is registered, but this is also now
passed into `plugin_check`. Furthermore, those various data are not
specific to the registration in particular. Rename the type into
`ns_pluginctx_t` for clarity.
This commit introduces a new type, ns_pluginregister_ctx_t,
which is passed to plugin_check() and plugin_register() in place of the
'source' parameter. The source value is now just part of the structure,
which also holds a pointer to the zone origin if the plugin is loaded at
a zone level.
This provides more contextual information, enabling the plugin to make
specific configuration decisions based on the name of the zone for which
it is loaded.
It's also flexible if more contextual data are needed in the future:
add a new field to ns_pluginregister_ctx_t, and new plugins can use
it without affecting compatibility with existing plugins.
In named_config_parsefile(), when checking the validity of
named.conf, the checking of plugin correctness was deliberately
postponed until the plugin is loaded and registered. However,
when the plugin was registered, the checking was never actually
done: the plugin_register() implementation was called, but
plugin_check() was not.
This made it necessary to duplicate the correctness checking in both
functions, so that both named-checkconf and named could catch errors.
That should not be required.
ns_plugin_register() now calls the check function before the register
function, and aborts if either one fails. ns_plugin_check() calls only
the check function. ns_plugin_check() is used by named-checkconf, and
ns_plugin_register() is used by named. (Note: this design has a
side effect that a call to ns_plugin_register() will result in the
plugin parameters being parsed twice at registration time.)
ns_plugin_check() now takes an additional argument for the hook
source: zone or view.
ACL configuration context variables are inconsistently named as `actx`,
`ac`, or `aclconfctx`, which caused confusion during code reviews. This
commit renames all `cfg_aclconfctx_t` variables to `aclctx`, which is
short, consistent, and unambiguous.
The configuration should also take into account the built-in
DNSSEC policies when verifying the keys in the key-directory match the
given policy. Update the code accordingly and add some good and
failure test cases.
With named-checkconf -k you can check your configuration including
checking the dnssec-policy keys against the configured keystores. If
there is a mismatch in the key files versus the policy, named-checkconf
will fail. This is useful for running before migrating to dnssec-policy.
For logging purposes, introduce a function that writes the identifying
information about a policy key into a string.
Allow a dnssec key to be initialized outside the keymgr code.
Add 'log_errors' to 'cfg_kasp_fromconfig' to avoid duplicate error
logs.
`named_g_actconfctx` is a global variable holding the ACL configuration
context alive (in particular, to dynamically load zones). However, this
object is build once per configuration (early) and is used only inside
server.c `apply_configuration` flow. (Two exceptions: the shutdown flow,
still in server.c and plugin check flow, which doesn't need it, so it's
NULL in such case).
Instead of leaving this global publicly exposed, it is now part of the
`named_server_t` object. This allows us to clearly see that, when
reconfigureing the server, the new instance of the ACL context is known
only by the newly built object and not currently used by "production"
object; and will help to move move logic before the exclusive mode is
taken.
The other advantage is that the ACL configuration context can now be
built before the exclusive lock as well.
The "tkey-domain" statement has effectively been a no-op since commit
bd4576b3ce, which removed the only bit of
code using it: the logic implementing TKEY Mode 2 (Diffie-Hellman).
A subsequent cleanup commit, 885c132f4a,
also missed the opportunity to remove the "tkey-domain" statement
altogether.
Mark the "tkey-domain" statement as obsolete and remove all code and
documentation related to it.
The "tkey-gssapi-keytab" statement enables GSS-TSIG to be set up in a
simpler and more reliable way than using the "tkey-gssapi-credential"
statement and setting environment variables (e.g. KRB5_KTNAME).
Mark the "tkey-gssapi-credential" statement as deprecated to eventually
only have one method for setting up GSS-TSIG in named. Do not mention
"tkey-gssapi-credential" in the section of the ARM on dynamic updates.
By default, when named is started it may start answering to
queries before the response policy zones are completely loaded
and processed. This new feature gives an option to the users to
tell named that incoming requests should result in SERVFAIL anwser
until all the response policy zones are procesed and ready.
Add a new option 'manual-mode' to 'dnssec-policy'. The intended
use is that if it is enabled, it will not automatically move to the
next state transition (RUMOURED, UNRETENTIVE), only after manual
confirmation. The intended state transition should be logged.
> Put a space before opening parentheses only after control statement
> keywords (for/if/while...) except this option doesn’t apply to ForEach
> and If macros. This is useful in projects where ForEach/If macros are
> treated as function calls instead of control statements.
DNSKEY algorithms RSASHA1 and RSASHA-NSEC3-SHA1 and DS digest type
SHA1 are deprecated. Log when these are present in primary zone
files and when generating new DNSKEYs, DS and CDS records.
Use the existing RSASHA256 and RSASHA512 implementation to provide
working PRIVATEOID example implementations. We are using the OID
values normally associated with RSASHA256 (1.2.840.113549.1.1.11)
and RSASHA512 (1.2.840.113549.1.1.13).
DST algorithm and DNSSEC algorithm values are not necessarily the same
anymore: if the DNSSEC algorithm value is PRIVATEOID or PRIVATEDNS, then
the DST algorithm will be mapped to something else. The conversion is
now done correctly where necessary.
The algorithm values PRIVATEDNS and PRIVATEOID are placeholders,
signifying that the actual algorithm identifier is encoded into the
key data. Keys using this mechanism are now supported.
- The algorithm values PRIVATEDNS and PRIVATEOID cannot be used to
build a key file name; dst_key_buildfilename() will assert if
they are used.
- The DST key values for private algorithms are higher than 255.
Since DST_ALG_MAXALG now exceeds 256, algorithm arrays that were
previously hardcoded to size 256 have been resized.
- New mnemonic/text conversion functions have been added.
dst_algorithm_{fromtext,totext,format} can handle algorithm
identifiers encoded in PRIVATEDNS and PRIVATEOID keys, as well
as the traditional algorithm identifiers. (Note: The existing
dns_secalg_{fromtext,totext,format} functions are similar, but
do *not* support PRIVATEDNS and PRIVATEOID. In most cases, the
new functions have taken the place of the old ones, but in a few
cases the old version is still appropriate.)
- dns_private{oid,dns}_{fromtext,totext,format} converts between
DST algorithm values and the mnemonic strings for algorithms
implemented using PRIVATEDNS or PRIVATEOID. (E.g., "RSASHA256OID").
- dst_algorithm_tosecalg() returns the DNSSEC algorithm identifier
that applies for a given DST algorithm. For PRIVATEDNS- or
PRIVATEOID- based algorithms, the result will be PRIVATEDNS or
PRIVATEOID, respectively.
- dst_algorithm_fromprivatedns() and dst_algorithm_fromprivateoid()
return the DST algorithm identifier for an encoded algorithm in
wire format, represented as in DNS name or an object identifier,
respectively.
- dst_algorithm_fromdata() is a front-end for the above; it extracts
the private algorithm identifier encoded at the begining of a
block of key or signature data, and returns the matching DST
algorithm number.
- dst_key_fromdns() and dst_key_frombuffer() now work with keys
that have PRIVATEDNS and PRIVATEOID algorithm identifiers at the
beginning.
"type delegation-only" has been obsolete for some time
(see #3953) but the zone type flag for it was still defined
in libisccfg. It has now been removed.