Commit 54185d2e authored by Jan Kadlec's avatar Jan Kadlec

Issue warning and ignore semanticaly wrong RRs during AXFR.

parent 3f53306b
......@@ -120,19 +120,27 @@ static char *error_messages[(-ZC_ERR_UNKNOWN) + 1] = {
"GLUE: Record with glue address missing!",
};
err_handler_t *handler_new(int log_cname, int log_glue, int log_rrsigs,
int log_nsec, int log_nsec3)
void err_handler_init(err_handler_t *h)
{
err_handler_t *handler = xmalloc(sizeof(err_handler_t));
memset(h, 0, sizeof(err_handler_t));
memset(h->errors, 0, sizeof(uint) * (-ZC_ERR_UNKNOWN + 1));
h->options.log_cname = 0;
h->options.log_glue = 0;
h->options.log_rrsigs = 0;
h->options.log_nsec = 0;
h->options.log_nsec3 = 0;
}
memset(handler->errors, 0, sizeof(uint) * (-ZC_ERR_UNKNOWN + 1));
handler->error_count = 0;
handler->options.log_cname = log_cname;
handler->options.log_glue = log_glue;
handler->options.log_rrsigs = log_rrsigs;
handler->options.log_nsec = log_nsec;
handler->options.log_nsec3 = log_nsec3;
err_handler_t *err_handler_new()
{
err_handler_t *handler= xmalloc(sizeof(err_handler_t));
err_handler_init(handler);
handler->options.log_cname = 1;
handler->options.log_glue = 1;
handler->options.log_rrsigs = 1;
handler->options.log_nsec = 1;
handler->options.log_nsec3 = 1;
return handler;
}
......@@ -755,8 +763,8 @@ static int zone_is_secure(const knot_zone_contents_t *z)
return (soa_rr && soa_rr->rrsigs ? 1 : 0);
}
static int sem_check_node_mandatory(knot_zone_contents_t *zone,
knot_node_t *node, int level,
static int sem_check_node_mandatory(const knot_zone_contents_t *zone,
const knot_node_t *node, int level,
err_handler_t *handler, int *fatal_error)
{
const knot_rrset_t *cname_rrset =
......@@ -790,7 +798,7 @@ static int sem_check_node_mandatory(knot_zone_contents_t *zone,
const knot_rrset_t *dname_rrset =
knot_node_rrset(node, KNOT_RRTYPE_DNAME);
if (dname_rrset != NULL) {
if (knot_node_rrset(node, KNOT_RRTYPE_CNAME)) {
if (cname_rrset) {
*fatal_error = 1;
err_handler_handle_error(handler, node,
ZC_ERR_CNAME_EXTRA_RECORDS,
......@@ -807,7 +815,8 @@ static int sem_check_node_mandatory(knot_zone_contents_t *zone,
struct sem_check_param param;
param.node_count = 0;
int ret_apply =
knot_zone_contents_nsec3_apply_inorder(zone,
knot_zone_contents_nsec3_apply_inorder(
(knot_zone_contents_t *)zone,
count_nodes_in_tree,
&param);
if (ret_apply != KNOT_EOK || param.node_count != 1) {
......@@ -834,8 +843,9 @@ static int sem_check_node_mandatory(knot_zone_contents_t *zone,
return KNOT_EOK;
}
static int sem_check_node_optional(knot_zone_contents_t *zone,
knot_node_t *node, err_handler_t *handler)
static int sem_check_node_optional(const knot_zone_contents_t *zone,
const knot_node_t *node,
err_handler_t *handler)
{
if (knot_node_is_deleg_point(node) || knot_zone_contents_apex(zone) ==
node) {
......@@ -847,7 +857,6 @@ static int sem_check_node_optional(knot_zone_contents_t *zone,
NULL);
return KNOT_EOK;
}
//FIXME this should be an error as well ! (i guess)
/* TODO How about multiple RRs? */
knot_dname_t *ns_dname =
......@@ -915,8 +924,8 @@ static int sem_check_node_optional(knot_zone_contents_t *zone,
*
* \return Appropriate error code if error was found.
*/
int sem_check_node_plain(knot_zone_contents_t *zone,
knot_node_t *node,
int sem_check_node_plain(const knot_zone_contents_t *zone,
const knot_node_t *node,
int do_checks,
err_handler_t *handler,
int only_mandatory,
......
......@@ -134,18 +134,18 @@ struct err_handler {
typedef struct err_handler err_handler_t;
/*!
* \brief Creates new semantic error handler.
* \brief Inits semantic error handler. No optional events will be logged.
*
* \param log_cname If true, log all CNAME related events.
* \param log_glue If true, log all Glue related events.
* \param log_rrsigs If true, log all RRSIGs related events.
* \param log_nsec If true, log all NSEC related events.
* \param log_nsec3 If true, log all NSEC3 related events.
* \param handler Variable to be initialized.
*/
void err_handler_init(err_handler_t *err_handler);
/*!
* \brief Creates new semantic error handler.
*
* \return err_handler_t * Created error handler.
*/
err_handler_t *handler_new(int log_cname, int log_glue, int log_rrsigs,
int log_nsec, int log_nsec3);
err_handler_t *err_handler_new();
/*!
* \brief Called when error has been encountered in node. Will either log error
......@@ -200,8 +200,8 @@ int zone_do_sem_checks(knot_zone_contents_t *zone, int check_level,
err_handler_t *handler, knot_node_t *first_nsec3_node,
knot_node_t *last_nsec3_node);
int sem_check_node_plain(knot_zone_contents_t *zone,
knot_node_t *node,
int sem_check_node_plain(const knot_zone_contents_t *zone,
const knot_node_t *node,
int do_checks,
err_handler_t *handler,
int only_mandatory,
......
......@@ -546,8 +546,7 @@ int knot_zload_open(zloader_t **dst, const char *source, const char *origin,
zl->semantic_checks = semantic_checks;
*dst = zl;
/* Log all information for now - possibly more config options. */
zl->err_handler = handler_new(1, 1, 1, 1, 1);
zl->err_handler = err_handler_new();
if (zl->err_handler == NULL) {
/* Not a reason to stop. */
log_zone_warning("Could not create semantic checks handler. "
......
......@@ -34,6 +34,7 @@
#include "libknot/updates/changesets.h"
#include "libknot/tsig.h"
#include "libknot/tsig-op.h"
#include "knot/zone/semantic-check.h"
#include "common/lists.h"
#include "common/descriptor.h"
#include "libknot/rdata.h"
......@@ -293,25 +294,29 @@ static int xfrin_process_orphan_rrsigs(knot_zone_contents_t *zone,
/*----------------------------------------------------------------------------*/
static void xfrin_log_error(const knot_dname_t *zone_owner,
const knot_dname_t *rr_owner,
const knot_rrset_t *rr,
int ret)
{
char *zonename = knot_dname_to_str(zone_owner);
char *rrname = knot_dname_to_str(rr->owner);
if (ret == KNOT_EOUTOFZONE) {
// Out-of-zone data, ignore
char *rrname = knot_dname_to_str(rr_owner);
log_zone_warning("Zone %s: Ignoring "
"out-of-zone RR owned by %s\n",
zonename, rrname);
free(zonename);
free(rrname);
} if (ret == KNOT_EMALF) {
// Semantic error
char rrstr[16];
knot_rrtype_to_string(rr->type, rrstr, 16);
log_zone_warning("Zone %s: Ignoring RR owned by %s, type %s, due"
"to semantic error.\n", zonename, rrname, rrstr);
} else {
log_zone_error("Zone %s: Failed to process "
"incoming RR, transfer "
"is probably malformed. (Reason: %s)\n",
"incoming RR, Transfer failed (Reason: %s)\n",
zonename, knot_strerror(ret));
free(zonename);
}
free(rrname);
free(zonename);
}
void xfrin_free_orphan_rrsigs(xfrin_orphan_rrsig_t **rrsigs)
......@@ -433,6 +438,40 @@ static int xfrin_check_tsig(knot_packet_t *packet, knot_ns_xfr_t *xfr,
/*----------------------------------------------------------------------------*/
static int rr_semantic_check(const knot_zone_contents_t *z,
err_handler_t *err_handler,
const knot_node_t *node, const knot_rrset_t *rr,
bool *usable)
{
if (!node) {
// New RR
return true;
}
// Make a copy of node and check if the node passes semantic checks
knot_node_t *node_copy = NULL;
int ret = knot_node_shallow_copy(node, &node_copy);
if (ret != KNOT_EOK) {
return KNOT_ENOMEM;
}
const int check_level_auto = -1;
ret = knot_node_add_rrset(node_copy, (knot_rrset_t *)rr);
if (ret != KNOT_EOK) {
knot_node_free(&node_copy);
}
int fatal = 0;
ret = sem_check_node_plain(z, node, check_level_auto,
err_handler, 1, &fatal);
knot_node_free(&node_copy);
if (ret != KNOT_EOK) {
return ret;
}
*usable = !fatal;
return KNOT_EOK;
}
int xfrin_process_axfr_packet(knot_ns_xfr_t *xfr)
{
const uint8_t *pkt = xfr->wire;
......@@ -444,6 +483,10 @@ int xfrin_process_axfr_packet(knot_ns_xfr_t *xfr)
return KNOT_EINVAL;
}
/* Init semantic error handler - used for CNAME/DNAME checks. */
err_handler_t err_handler;
err_handler_init(&err_handler);
dbg_xfrin_verb("Processing AXFR packet of size %zu.\n", size);
// check if the response is OK
......@@ -615,12 +658,12 @@ dbg_xfrin_exec(
if (!knot_dname_is_sub(rr->owner, xfr->zone->name) &&
!knot_dname_is_equal(rr->owner, xfr->zone->name)) {
// Out-of-zone data
xfrin_log_error(xfr->zone->name, rr->owner,
xfrin_log_error(xfr->zone->name, rr,
KNOT_EOUTOFZONE);
knot_rrset_deep_free(&rr, 1);
ret = knot_packet_parse_next_rr_answer(packet, &rr);
continue;
}
}
dbg_rrset_detail("\nNext RR:\n\n");
knot_rrset_dump(rr);
......@@ -754,7 +797,7 @@ dbg_xfrin_exec_verb(
knot_rrset_deep_free(&rr, 1);
return KNOT_EMALF;
}
knot_node_t *(*get_node)(const knot_zone_contents_t *,
const knot_dname_t *) = NULL;
int (*add_node)(knot_zone_contents_t *, knot_node_t *, int,
......@@ -815,6 +858,21 @@ dbg_xfrin_exec_verb(
in_zone = 1;
} else {
assert(in_zone);
bool rr_usable = false;
ret = rr_semantic_check(zone, &err_handler, node, rr,
&rr_usable);
if (ret != KNOT_EOK) {
knot_packet_free(&packet);
return ret;
}
if (!rr_usable) {
xfrin_log_error(xfr->zone->name, rr, KNOT_EMALF);
knot_rrset_deep_free(&rr, true);
ret = knot_packet_parse_next_rr_answer(packet,
&rr);
continue;
}
ret = knot_zone_contents_add_rrset(zone, rr, &node,
KNOT_RRSET_DUPL_MERGE);
......@@ -1105,14 +1163,13 @@ dbg_xfrin_exec_verb(
if (!knot_dname_is_sub(rr->owner, xfr->zone->name) &&
!knot_dname_is_equal(rr->owner, xfr->zone->name)) {
// out-of-zone domain
xfrin_log_error(xfr->zone->name, rr->owner,
KNOT_EOUTOFZONE);
xfrin_log_error(xfr->zone->name, rr, KNOT_EOUTOFZONE);
knot_rrset_deep_free(&rr, 1);
// Skip this rr
ret = knot_packet_parse_next_rr_answer(packet, &rr);
continue;
}
switch (state) {
case -1:
// a SOA is expected
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment