update-check-ksk boolean;
update-policy ( local | { ( deny | grant ) string (
6to4-self | external | krb5-self | krb5-selfsub |
- krb5-subdomain | ms-self | ms-selfsub | ms-subdomain |
+ krb5-subdomain | krb5-subdomain-self-rhs | ms-self |
+ ms-selfsub | ms-subdomain | ms-subdomain-self-rhs |
name | self | selfsub | selfwild | subdomain | tcp-self
| wildcard | zonesub ) [ string ] rrtypelist; ... };
use-alt-transfer-source boolean;
stub );
update-check-ksk boolean;
update-policy ( local | { ( deny | grant ) string ( 6to4-self |
- external | krb5-self | krb5-selfsub | krb5-subdomain | ms-self
- | ms-selfsub | ms-subdomain | name | self | selfsub | selfwild
- | subdomain | tcp-self | wildcard | zonesub ) [ string ]
+ external | krb5-self | krb5-selfsub | krb5-subdomain |
+ krb5-subdomain-self-rhs | ms-self | ms-selfsub | ms-subdomain |
+ ms-subdomain-self-rhs | name | self | selfsub | selfwild |
+ subdomain | tcp-self | wildcard | zonesub ) [ string ]
rrtypelist; ... };
use-alt-transfer-source boolean;
zero-no-soa-ttl boolean;
update\-check\-ksk boolean;
update\-policy ( local | { ( deny | grant ) string (
6to4\-self | external | krb5\-self | krb5\-selfsub |
- krb5\-subdomain | ms\-self | ms\-selfsub | ms\-subdomain |
+ krb5\-subdomain | krb5\-subdomain\-self\-rhs | ms\-self |
+ ms\-selfsub | ms\-subdomain | ms\-subdomain\-self\-rhs |
name | self | selfsub | selfwild | subdomain | tcp\-self
| wildcard | zonesub ) [ string ] rrtypelist; ... };
use\-alt\-transfer\-source boolean;
stub );
update\-check\-ksk boolean;
update\-policy ( local | { ( deny | grant ) string ( 6to4\-self |
- external | krb5\-self | krb5\-selfsub | krb5\-subdomain | ms\-self
- | ms\-selfsub | ms\-subdomain | name | self | selfsub | selfwild
- | subdomain | tcp\-self | wildcard | zonesub ) [ string ]
+ external | krb5\-self | krb5\-selfsub | krb5\-subdomain |
+ krb5\-subdomain\-self\-rhs | ms\-self | ms\-selfsub | ms\-subdomain |
+ ms\-subdomain\-self\-rhs | name | self | selfsub | selfwild |
+ subdomain | tcp\-self | wildcard | zonesub ) [ string ]
rrtypelist; ... };
use\-alt\-transfer\-source boolean;
zero\-no\-soa\-ttl boolean;
sig-signing-type <integer>;
sig-validity-interval <integer> [ <integer> ];
update-check-ksk <boolean>;
- update-policy ( local | { ( deny | grant ) <string> ( 6to4-self | external | krb5-self | krb5-selfsub | krb5-subdomain | ms-self | ms-selfsub | ms-subdomain | name | self | selfsub | selfwild | subdomain | tcp-self | wildcard | zonesub ) [ <string> ] <rrtypelist>; ... };
+ update-policy ( local | { ( deny | grant ) <string> ( 6to4-self | external | krb5-self | krb5-selfsub | krb5-subdomain | krb5-subdomain-self-rhs | ms-self | ms-selfsub | ms-subdomain | ms-subdomain-self-rhs | name | self | selfsub | selfwild | subdomain | tcp-self | wildcard | zonesub ) [ <string> ] <rrtypelist>; ... };
zero-no-soa-ttl <boolean>;
zone-statistics ( full | terse | none | <boolean> );
};
sig-signing-type <integer>;
sig-validity-interval <integer> [ <integer> ];
update-check-ksk <boolean>;
- update-policy ( local | { ( deny | grant ) <string> ( 6to4-self | external | krb5-self | krb5-selfsub | krb5-subdomain | ms-self | ms-selfsub | ms-subdomain | name | self | selfsub | selfwild | subdomain | tcp-self | wildcard | zonesub ) [ <string> ] <rrtypelist>; ... };
+ update-policy ( local | { ( deny | grant ) <string> ( 6to4-self | external | krb5-self | krb5-selfsub | krb5-subdomain | krb5-subdomain-self-rhs | ms-self | ms-selfsub | ms-subdomain | ms-subdomain-self-rhs | name | self | selfsub | selfwild | subdomain | tcp-self | wildcard | zonesub ) [ <string> ] <rrtypelist>; ... };
zero-no-soa-ttl <boolean>;
zone-statistics ( full | terse | none | <boolean> );
};
update-check-ksk <boolean>;
update-policy ( local | { ( deny | grant ) <string> (
6to4-self | external | krb5-self | krb5-selfsub |
- krb5-subdomain | ms-self | ms-selfsub | ms-subdomain |
+ krb5-subdomain | krb5-subdomain-self-rhs | ms-self |
+ ms-selfsub | ms-subdomain | ms-subdomain-self-rhs |
name | self | selfsub | selfwild | subdomain | tcp-self
| wildcard | zonesub ) [ <string> ] <rrtypelist>; ... };
use-alt-transfer-source <boolean>;
stub );
update-check-ksk <boolean>;
update-policy ( local | { ( deny | grant ) <string> ( 6to4-self |
- external | krb5-self | krb5-selfsub | krb5-subdomain | ms-self
- | ms-selfsub | ms-subdomain | name | self | selfsub | selfwild
- | subdomain | tcp-self | wildcard | zonesub ) [ <string> ]
+ external | krb5-self | krb5-selfsub | krb5-subdomain |
+ krb5-subdomain-self-rhs | ms-self | ms-selfsub | ms-subdomain |
+ ms-subdomain-self-rhs | name | self | selfsub | selfwild |
+ subdomain | tcp-self | wildcard | zonesub ) [ <string> ]
<rrtypelist>; ... };
use-alt-transfer-source <boolean>;
zero-no-soa-ttl <boolean>;
update-check-ksk <boolean>;
update-policy ( local | { ( deny | grant ) <string> (
6to4-self | external | krb5-self | krb5-selfsub |
- krb5-subdomain | ms-self | ms-selfsub | ms-subdomain |
+ krb5-subdomain | krb5-subdomain-self-rhs | ms-self |
+ ms-selfsub | ms-subdomain | ms-subdomain-self-rhs |
name | self | selfsub | selfwild | subdomain | tcp-self
| wildcard | zonesub ) [ <string> ] <rrtypelist>; ... };
use-alt-transfer-source <boolean>;
stub );
update-check-ksk <boolean>;
update-policy ( local | { ( deny | grant ) <string> ( 6to4-self |
- external | krb5-self | krb5-selfsub | krb5-subdomain | ms-self
- | ms-selfsub | ms-subdomain | name | self | selfsub | selfwild
- | subdomain | tcp-self | wildcard | zonesub ) [ <string> ]
+ external | krb5-self | krb5-selfsub | krb5-subdomain |
+ krb5-subdomain-self-rhs | ms-self | ms-selfsub | ms-subdomain |
+ ms-subdomain-self-rhs | name | self | selfsub | selfwild |
+ subdomain | tcp-self | wildcard | zonesub ) [ <string> ]
<rrtypelist>; ... };
use-alt-transfer-source <boolean>;
zero-no-soa-ttl <boolean>;
case dns_ssumatchtype_name:
case dns_ssumatchtype_subdomain: /* also zonesub */
case dns_ssumatchtype_subdomainms:
+ case dns_ssumatchtype_subdomainselfmsrhs:
case dns_ssumatchtype_subdomainkrb5:
+ case dns_ssumatchtype_subdomainselfkrb5rhs:
case dns_ssumatchtype_wildcard:
case dns_ssumatchtype_external:
case dns_ssumatchtype_local:
dns_ssumatchtype_local = 13,
dns_ssumatchtype_selfsubms = 14,
dns_ssumatchtype_selfsubkrb5 = 15,
- dns_ssumatchtype_max = 15, /* max value */
+ dns_ssumatchtype_subdomainselfkrb5rhs = 16,
+ dns_ssumatchtype_subdomainselfmsrhs = 17,
+ dns_ssumatchtype_max = 17, /* max value */
- dns_ssumatchtype_dlz = 16 /* intentionally higher than _max */
+ dns_ssumatchtype_dlz = 18 /* intentionally higher than _max */
} dns_ssumatchtype_t;
typedef struct dns_ssuruletype {
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 dns_ssurule_t **rulep);
+ const dns_name_t *target, 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
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 dns_ssurule_t **rulep) {
+ const dns_name_t *target, const dst_key_t *key,
+ const dns_ssurule_t **rulep) {
dns_fixedname_t fixed;
dns_name_t *stfself;
dns_name_t *tcpself;
dns_name_t *wildcard;
dns_ssurule_t *rule;
+ const dns_name_t *tname;
int match;
isc_result_t result;
unsigned int i;
rule = ISC_LIST_NEXT(rule, link))
{
switch (rule->matchtype) {
- case dns_ssumatchtype_name:
case dns_ssumatchtype_local:
- case dns_ssumatchtype_subdomain:
- case dns_ssumatchtype_wildcard:
+ case dns_ssumatchtype_name:
case dns_ssumatchtype_self:
case dns_ssumatchtype_selfsub:
case dns_ssumatchtype_selfwild:
+ case dns_ssumatchtype_subdomain:
+ case dns_ssumatchtype_wildcard:
if (signer == NULL) {
continue;
}
case dns_ssumatchtype_selfsubms:
case dns_ssumatchtype_subdomainkrb5:
case dns_ssumatchtype_subdomainms:
+ case dns_ssumatchtype_subdomainselfkrb5rhs:
+ case dns_ssumatchtype_subdomainselfmsrhs:
if (signer == NULL) {
continue;
}
}
continue;
case dns_ssumatchtype_subdomainkrb5:
+ case dns_ssumatchtype_subdomainselfkrb5rhs:
if (!dns_name_issubdomain(name, rule->name)) {
continue;
}
+ tname = NULL;
+ switch (rule->matchtype) {
+ case dns_ssumatchtype_subdomainselfkrb5rhs:
+ if (type == dns_rdatatype_ptr) {
+ tname = target;
+ }
+ if (type == dns_rdatatype_srv) {
+ tname = target;
+ }
+ break;
+ default:
+ break;
+ }
if (dst_gssapi_identitymatchesrealmkrb5(
- signer, NULL, rule->identity, false)) {
+ signer, tname, rule->identity, false)) {
break;
}
continue;
case dns_ssumatchtype_subdomainms:
+ case dns_ssumatchtype_subdomainselfmsrhs:
if (!dns_name_issubdomain(name, rule->name)) {
continue;
}
+ tname = NULL;
+ switch (rule->matchtype) {
+ case dns_ssumatchtype_subdomainselfmsrhs:
+ if (type == dns_rdatatype_ptr) {
+ tname = target;
+ }
+ if (type == dns_rdatatype_srv) {
+ tname = target;
+ }
+ break;
+ default:
+ break;
+ }
if (dst_gssapi_identitymatchesrealmms(
- signer, NULL, rule->identity, false)) {
+ signer, tname, rule->identity, false)) {
break;
}
continue;
if (rule->ntypes == 0) {
/*
* If this is a DLZ rule, then the DLZ ssu
- * checks will have already checked
- * the type.
+ * checks will have already checked the type.
*/
if (rule->matchtype != dns_ssumatchtype_dlz &&
!isusertype(type)) {
*mtype = dns_ssumatchtype_selfsubkrb5;
} else if (strcasecmp(str, "ms-subdomain") == 0) {
*mtype = dns_ssumatchtype_subdomainms;
+ } else if (strcasecmp(str, "ms-subdomain-self-rhs") == 0) {
+ *mtype = dns_ssumatchtype_subdomainselfmsrhs;
} else if (strcasecmp(str, "krb5-subdomain") == 0) {
*mtype = dns_ssumatchtype_subdomainkrb5;
+ } else if (strcasecmp(str, "krb5-subdomain-self-rhs") == 0) {
+ *mtype = dns_ssumatchtype_subdomainselfkrb5rhs;
} else if (strcasecmp(str, "tcp-self") == 0) {
*mtype = dns_ssumatchtype_tcpself;
} else if (strcasecmp(str, "6to4-self") == 0) {
"krb5-self",
"krb5-selfsub",
"krb5-subdomain",
+ "krb5-subdomain-self-rhs",
"ms-self",
"ms-selfsub",
"ms-subdomain",
+ "ms-subdomain-self-rhs",
"name",
"self",
"selfsub",
static isc_result_t
ssu_checkrule(void *data, dns_rdataset_t *rrset) {
- const dns_ssurule_t *rule = NULL;
ssu_check_t *ssuinfo = data;
- bool rule_ok;
+ bool rule_ok = false;
/*
* If we're deleting all records, it's ok to delete RRSIG and NSEC even
return (ISC_R_SUCCESS);
}
- rule_ok = dns_ssutable_checkrules(ssuinfo->table, ssuinfo->signer,
- ssuinfo->name, ssuinfo->addr,
- ssuinfo->tcp, ssuinfo->aclenv,
- rrset->type, ssuinfo->key, &rule);
+ /*
+ * krb5-subdomain-self-rhs and ms-subdomain-self-rhs need
+ * to check the PTR and SRV target names so extract them
+ * from the resource records.
+ */
+ if (rrset->rdclass == dns_rdataclass_in &&
+ (rrset->type == dns_rdatatype_srv ||
+ rrset->type == dns_rdatatype_ptr))
+ {
+ dns_name_t *target = NULL;
+ dns_rdata_ptr_t ptr;
+ dns_rdata_in_srv_t srv;
+ dns_rdataset_t rdataset;
+ isc_result_t result;
+
+ dns_rdataset_init(&rdataset);
+ dns_rdataset_clone(rrset, &rdataset);
+
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset))
+ {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_current(&rdataset, &rdata);
+ if (rrset->type == dns_rdatatype_ptr) {
+ result = dns_rdata_tostruct(&rdata, &ptr, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ target = &ptr.ptr;
+ }
+ if (rrset->type == dns_rdatatype_srv) {
+ result = dns_rdata_tostruct(&rdata, &srv, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ target = &srv.target;
+ }
+ rule_ok = dns_ssutable_checkrules(
+ ssuinfo->table, ssuinfo->signer, ssuinfo->name,
+ ssuinfo->addr, ssuinfo->tcp, ssuinfo->aclenv,
+ rrset->type, target, ssuinfo->key, NULL);
+ if (!rule_ok) {
+ break;
+ }
+ }
+ if (result != ISC_R_NOMORE) {
+ rule_ok = false;
+ }
+ dns_rdataset_disassociate(&rdataset);
+ } else {
+ rule_ok = dns_ssutable_checkrules(
+ ssuinfo->table, ssuinfo->signer, ssuinfo->name,
+ ssuinfo->addr, ssuinfo->tcp, ssuinfo->aclenv,
+ rrset->type, NULL, ssuinfo->key, NULL);
+ }
return (rule_ok ? ISC_R_SUCCESS : ISC_R_FAILURE);
}
return (result == ISC_R_SUCCESS);
}
+static isc_result_t
+ssu_checkrr(void *data, rr_t *rr) {
+ isc_result_t result;
+ ssu_check_t *ssuinfo = data;
+ dns_name_t *target = NULL;
+ dns_rdata_ptr_t ptr;
+ dns_rdata_in_srv_t srv;
+ bool answer;
+
+ if (rr->rdata.type == dns_rdatatype_ptr) {
+ result = dns_rdata_tostruct(&rr->rdata, &ptr, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ target = &ptr.ptr;
+ }
+ if (rr->rdata.type == dns_rdatatype_srv) {
+ result = dns_rdata_tostruct(&rr->rdata, &srv, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ target = &srv.target;
+ }
+
+ answer = dns_ssutable_checkrules(
+ ssuinfo->table, ssuinfo->signer, ssuinfo->name, ssuinfo->addr,
+ ssuinfo->tcp, ssuinfo->aclenv, rr->rdata.type, target,
+ ssuinfo->key, NULL);
+ return (answer ? ISC_R_SUCCESS : ISC_R_FAILURE);
+}
+
/**************************************************************************/
/*
* Checking of "RRset exists (value dependent)" prerequisites.
if (ssutable != NULL) {
isc_netaddr_t netaddr;
+ dns_name_t *target = NULL;
dst_key_t *tsigkey = NULL;
+ dns_rdata_ptr_t ptr;
+ dns_rdata_in_srv_t srv;
+
isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
if (client->message->tsigkey != NULL) {
tsigkey = client->message->tsigkey->key;
}
- if (rdata.type != dns_rdatatype_any) {
+ if ((update_class == dns_rdataclass_in ||
+ update_class == dns_rdataclass_none) &&
+ rdata.type == dns_rdatatype_ptr)
+ {
+ result = dns_rdata_tostruct(&rdata, &ptr, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ target = &ptr.ptr;
+ }
+
+ if ((update_class == dns_rdataclass_in ||
+ update_class == dns_rdataclass_none) &&
+ rdata.type == dns_rdatatype_srv)
+ {
+ result = dns_rdata_tostruct(&rdata, &srv, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ target = &srv.target;
+ }
+
+ if (update_class == dns_rdataclass_any &&
+ zoneclass == dns_rdataclass_in &&
+ (rdata.type == dns_rdatatype_ptr ||
+ rdata.type == dns_rdatatype_srv))
+ {
+ ssu_check_t ssuinfo;
+
+ ssuinfo.name = name;
+ ssuinfo.table = ssutable;
+ ssuinfo.signer = client->signer;
+ ssuinfo.addr = &netaddr;
+ ssuinfo.aclenv = env;
+ ssuinfo.tcp = TCPCLIENT(client);
+ ssuinfo.key = tsigkey;
+
+ result = foreach_rr(db, ver, name, rdata.type,
+ dns_rdatatype_none,
+ ssu_checkrr, &ssuinfo);
+ if (result != ISC_R_SUCCESS) {
+ FAILC(DNS_R_REFUSED,
+ "rejected by secure update");
+ }
+ } else if (target != NULL &&
+ update_class == dns_rdataclass_none) {
+ bool flag;
+ CHECK(rr_exists(db, ver, name, &rdata, &flag));
+ if (flag &&
+ !dns_ssutable_checkrules(
+ ssutable, client->signer, name,
+ &netaddr, TCPCLIENT(client), env,
+ rdata.type, target, tsigkey,
+ &rules[rule]))
+ {
+ FAILC(DNS_R_REFUSED,
+ "rejected by secure update");
+ }
+ } else if (rdata.type != dns_rdatatype_any) {
if (!dns_ssutable_checkrules(
ssutable, client->signer, name,
&netaddr, TCPCLIENT(client), env,
- rdata.type, tsigkey, &rules[rule]))
+ rdata.type, target, tsigkey,
+ &rules[rule]))
{
FAILC(DNS_R_REFUSED, "rejected by "
"secure update");