Commit 9f19367f authored by Mark Andrews's avatar Mark Andrews

initial code to support returning thematching rule from the ssu table and the...

initial code to support returning thematching rule from the ssu table and the start of support for add-new rule
parent 5826c85a
......@@ -42,9 +42,10 @@ typedef enum {
dns_ssumatchtype_local = 13,
dns_ssumatchtype_selfsubms = 14,
dns_ssumatchtype_selfsubkrb5 = 15,
dns_ssumatchtype_max = 15, /* max value */
dns_ssumatchtype_addnew = 16,
dns_ssumatchtype_max = 16, /* max value */
dns_ssumatchtype_dlz = 16 /* intentionally higher than _max */
dns_ssumatchtype_dlz = 17 /* intentionally higher than _max */
} dns_ssumatchtype_t;
isc_result_t
......@@ -136,7 +137,7 @@ bool
dns_ssutable_checkrules(dns_ssutable_t *table, const dns_name_t *signer,
const dns_name_t *name, const isc_netaddr_t *addr,
bool tcp, const dns_aclenv_t *env, dns_rdatatype_t type,
const dst_key_t *key);
const dst_key_t *key, const dns_ssurule_t **rulep);
/*%<
* Checks that the attempted update of (name, type) is allowed according
* to the rules specified in the simple-secure-update rule table. If
......
......@@ -284,7 +284,7 @@ bool
dns_ssutable_checkrules(dns_ssutable_t *table, const dns_name_t *signer,
const dns_name_t *name, const isc_netaddr_t *addr,
bool tcp, const dns_aclenv_t *env, dns_rdatatype_t type,
const dst_key_t *key) {
const dst_key_t *key, const dns_ssurule_t **rulep) {
dns_ssurule_t *rule;
unsigned int i;
dns_fixedname_t fixed;
......@@ -298,10 +298,7 @@ dns_ssutable_checkrules(dns_ssutable_t *table, const dns_name_t *signer,
REQUIRE(signer == NULL || dns_name_isabsolute(signer));
REQUIRE(dns_name_isabsolute(name));
REQUIRE(addr == NULL || env != NULL);
if (signer == NULL && addr == NULL) {
return (false);
}
REQUIRE(rulep == NULL || *rulep == NULL);
for (rule = ISC_LIST_HEAD(table->rules); rule != NULL;
rule = ISC_LIST_NEXT(rule, link))
......@@ -346,6 +343,7 @@ dns_ssutable_checkrules(dns_ssutable_t *table, const dns_name_t *signer,
break;
case dns_ssumatchtype_external:
case dns_ssumatchtype_dlz:
case dns_ssumatchtype_addnew:
break;
}
......@@ -499,6 +497,19 @@ dns_ssutable_checkrules(dns_ssutable_t *table, const dns_name_t *signer,
continue;
}
break;
case dns_ssumatchtype_addnew: {
dns_name_t suffix;
unsigned int labels = dns_name_countlabels(name);
if (signer != NULL || labels < 2)
continue;
dns_name_init(&suffix, NULL);
dns_name_getlabelsequence(name, 1, labels - 1, &suffix);
if (!dns_name_equal(rule->identity, &suffix))
continue;
break;
}
}
if (rule->ntypes == 0) {
......@@ -522,6 +533,9 @@ dns_ssutable_checkrules(dns_ssutable_t *table, const dns_name_t *signer,
continue;
}
}
if (rule->grant && rulep != NULL) {
*rulep = rule;
}
return (rule->grant);
}
......@@ -646,6 +660,8 @@ dns_ssu_mtypefromstring(const char *str, dns_ssumatchtype_t *mtype) {
*mtype = dns_ssumatchtype_6to4self;
} else if (strcasecmp(str, "zonesub") == 0) {
*mtype = dns_ssumatchtype_subdomain;
} else if (strcasecmp(str, "add-new") == 0) {
*mtype = dns_ssumatchtype_addnew;
} else if (strcasecmp(str, "external") == 0) {
*mtype = dns_ssumatchtype_external;
} else {
......
......@@ -301,23 +301,14 @@ doc_matchname(cfg_printer_t *pctx, const cfg_type_t *type) {
cfg_print_cstr(pctx, " ]");
}
static const char *matchtype_enums[] = { "6to4-self",
"external",
"krb5-self",
"krb5-selfsub",
"krb5-subdomain",
"ms-self",
"ms-selfsub",
"ms-subdomain",
"name",
"self",
"selfsub",
"selfwild",
"subdomain",
"tcp-self",
"wildcard",
"zonesub",
NULL };
static const char *matchtype_enums[] = {
"6to4-self", "add-new", "external",
"krb5-self", "krb5-selfsub", "krb5-subdomain",
"ms-self", "ms-selfsub", "ms-subdomain",
"name", "self", "selfsub",
"selfwild", "subdomain", "tcp-self",
"wildcard", "zonesub", NULL
};
static cfg_type_t cfg_type_matchtype = { "matchtype", parse_matchtype,
cfg_print_ustring, cfg_doc_enum,
......
......@@ -200,6 +200,9 @@
goto failure; \
} while (0)
#define IS_ADD_NEW(rule) \
(rule != NULL && dns_ssurule_matchtype(rule) == dns_ssumatchtype_addnew)
/*
* Return TRUE if NS_CLIENTATTR_TCP is set in the attributes other FALSE.
*/
......@@ -900,6 +903,7 @@ typedef struct {
static isc_result_t
ssu_checkrule(void *data, dns_rdataset_t *rrset) {
ssu_check_t *ssuinfo = data;
const dns_ssurule_t *rule = NULL;
bool result;
/*
......@@ -910,9 +914,13 @@ ssu_checkrule(void *data, dns_rdataset_t *rrset) {
rrset->type == dns_rdatatype_nsec) {
return (ISC_R_SUCCESS);
}
result = dns_ssutable_checkrules(
ssuinfo->table, ssuinfo->signer, ssuinfo->name, ssuinfo->addr,
ssuinfo->tcp, ssuinfo->aclenv, rrset->type, ssuinfo->key);
result = dns_ssutable_checkrules(ssuinfo->table, ssuinfo->signer,
ssuinfo->name, ssuinfo->addr,
ssuinfo->tcp, ssuinfo->aclenv,
rrset->type, ssuinfo->key, &rule);
if (IS_ADD_NEW(rule)) {
return (ISC_R_FAILURE);
}
return (result == true ? ISC_R_SUCCESS : ISC_R_FAILURE);
}
......@@ -2565,6 +2573,9 @@ update_action(isc_task_t *task, isc_event_t *event) {
uint64_t records;
dns_aclenv_t *env =
ns_interfacemgr_getaclenv(client->manager->interface->mgr);
size_t ruleslen = 0;
size_t rule;
const dns_ssurule_t **rules = NULL;
INSIST(event->ev_type == DNS_EVENT_UPDATE);
......@@ -2739,15 +2750,24 @@ update_action(isc_task_t *task, isc_event_t *event) {
/*
* Perform the Update Section Prescan.
*/
if (ssutable != NULL) {
ruleslen = request->counts[DNS_SECTION_UPDATE];
rules = isc_mem_get(mctx, sizeof(*rules) * ruleslen);
memset(rules, 0, sizeof(*rules) * ruleslen);
}
for (result = dns_message_firstname(request, DNS_SECTION_UPDATE);
for (rule = 0,
result = dns_message_firstname(request, DNS_SECTION_UPDATE);
result == ISC_R_SUCCESS;
result = dns_message_nextname(request, DNS_SECTION_UPDATE))
rule++, result = dns_message_nextname(request, DNS_SECTION_UPDATE))
{
dns_name_t *name = NULL;
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_ttl_t ttl;
dns_rdataclass_t update_class;
INSIST(rule < ruleslen);
get_current_rr(request, DNS_SECTION_UPDATE, zoneclass, &name,
&rdata, &covers, &ttl, &update_class);
......@@ -2820,11 +2840,17 @@ update_action(isc_task_t *task, isc_event_t *event) {
if (!dns_ssutable_checkrules(
ssutable, client->signer, name,
&netaddr, TCPCLIENT(client), env,
rdata.type, tsigkey))
rdata.type, tsigkey, &rules[rule]))
{
FAILC(DNS_R_REFUSED, "rejected by "
"secure update");
}
/* add-new is addition only */
if (update_class == dns_rdataclass_none &&
IS_ADD_NEW(rules[rule])) {
FAILC(DNS_R_REFUSED,
"rejected by secure update");
}
} else {
if (!ssu_checkall(db, ver, name, ssutable,
client->signer, &netaddr, env,
......@@ -2847,9 +2873,10 @@ update_action(isc_task_t *task, isc_event_t *event) {
*/
options = dns_zone_getoptions(zone);
for (result = dns_message_firstname(request, DNS_SECTION_UPDATE);
for (rule = 0,
result = dns_message_firstname(request, DNS_SECTION_UPDATE);
result == ISC_R_SUCCESS;
result = dns_message_nextname(request, DNS_SECTION_UPDATE))
rule++, result = dns_message_nextname(request, DNS_SECTION_UPDATE))
{
dns_name_t *name = NULL;
dns_rdata_t rdata = DNS_RDATA_INIT;
......@@ -2857,10 +2884,30 @@ update_action(isc_task_t *task, isc_event_t *event) {
dns_rdataclass_t update_class;
bool flag;
INSIST(rule < ruleslen);
get_current_rr(request, DNS_SECTION_UPDATE, zoneclass, &name,
&rdata, &covers, &ttl, &update_class);
if (update_class == zoneclass) {
/*
* There must be no records at the name except the
* the record to be added.
*/
if (IS_ADD_NEW(rules[rule])) {
result = foreach_rr(db, ver, name, rdata.type,
covers, rrset_exists_action,
NULL);
if (result == ISC_R_EXISTS)
continue;
CHECK(result);
CHECK(name_exists(db, ver, name, &flag));
if (flag) {
FAILC(DNS_R_REFUSED,
"rejected by secure update");
}
}
/*
* RFC1123 doesn't allow MF and MD in master zones.
*/
......@@ -3420,6 +3467,10 @@ common:
dns_db_detach(&db);
}
if (rules != NULL) {
isc_mem_put(mctx, rules, sizeof(*rules) * ruleslen);
}
if (ssutable != NULL) {
dns_ssutable_detach(&ssutable);
}
......
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