diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml
index 453b7a43bd..af15b64982 100644
--- a/doc/arm/Bv9ARM-book.xml
+++ b/doc/arm/Bv9ARM-book.xml
@@ -12719,12 +12719,13 @@ example.com. NS ns2.example.net.
the rules are checked for each existing record type.
- The ruletype field has 13
+ The ruletype field has 16
values:
name, subdomain,
wildcard, self,
selfsub, selfwild,
krb5-self, ms-self,
+ krb5-selfsub, ms-selfsub,
krb5-subdomain,
ms-subdomain,
tcp-self, 6to4-self,
@@ -12883,6 +12884,20 @@ example.com. NS ns2.example.net.
+
+
+
+ ms-selfsub
+
+
+
+ This is similar to ms-self
+ except it also allows updates to any subdomain of
+ the name specified in the Windows machine
+ principal, not just to the name itself.
+
+
+
@@ -12954,6 +12969,20 @@ example.com. NS ns2.example.net.
+
+
+
+ krb5-selfsub
+
+
+
+ This is similar to krb5-self
+ except it also allows updates to any subdomain of
+ the name specified in the 'machine' part of the
+ Kerberos principal, not just to the name itself.
+
+
+
diff --git a/lib/bind9/check.c b/lib/bind9/check.c
index 2e5de8e1e9..451bfbeeac 100644
--- a/lib/bind9/check.c
+++ b/lib/bind9/check.c
@@ -1830,6 +1830,8 @@ check_update_policy(const cfg_obj_t *policy, isc_log_t *logctx) {
break;
case dns_ssumatchtype_selfkrb5:
case dns_ssumatchtype_selfms:
+ case dns_ssumatchtype_selfsubkrb5:
+ case dns_ssumatchtype_selfsubms:
case dns_ssumatchtype_tcpself:
case dns_ssumatchtype_6to4self:
if (tresult == ISC_R_SUCCESS &&
diff --git a/lib/dns/gssapictx.c b/lib/dns/gssapictx.c
index bca9d3646b..6a6b2e3ab5 100644
--- a/lib/dns/gssapictx.c
+++ b/lib/dns/gssapictx.c
@@ -347,11 +347,11 @@ cleanup:
bool
dst_gssapi_identitymatchesrealmkrb5(const dns_name_t *signer,
const dns_name_t *name,
- const dns_name_t *realm)
+ const dns_name_t *realm,
+ bool subdomain)
{
#ifdef GSSAPI
char sbuf[DNS_NAME_FORMATSIZE];
- char nbuf[DNS_NAME_FORMATSIZE];
char rbuf[DNS_NAME_FORMATSIZE];
char *sname;
char *rname;
@@ -366,8 +366,6 @@ dst_gssapi_identitymatchesrealmkrb5(const dns_name_t *signer,
result = dns_name_toprincipal(signer, &buffer);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
isc_buffer_putuint8(&buffer, 0);
- if (name != NULL)
- dns_name_format(name, nbuf, sizeof(nbuf));
dns_name_format(realm, rbuf, sizeof(rbuf));
/*
@@ -382,6 +380,10 @@ dst_gssapi_identitymatchesrealmkrb5(const dns_name_t *signer,
*rname = '\0';
rname++;
+ if (strcmp(rname, rbuf) != 0) {
+ return (false);
+ }
+
/*
* Find the host portion of the signer's name. We do this by
* searching for the first / character. We then check to make
@@ -401,24 +403,30 @@ dst_gssapi_identitymatchesrealmkrb5(const dns_name_t *signer,
}
/*
- * Now, we do a simple comparison between the name and the realm.
+ * If name is non NULL check that it matches against the
+ * machine name as expected.
*/
if (name != NULL) {
- if ((strcasecmp(sname, nbuf) == 0)
- && (strcmp(rname, rbuf) == 0)) {
- return (true);
+ dns_fixedname_t fixed;
+ dns_name_t *machine;
+
+ machine = dns_fixedname_initname(&fixed);
+ result = dns_name_fromstring(machine, sname, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ return (false);
}
- } else {
- if (strcmp(rname, rbuf) == 0) {
- return (true);
+ if (subdomain) {
+ return (dns_name_issubdomain(name, machine));
}
+ return (dns_name_equal(name, machine));
}
- return (false);
+ return (true);
#else
UNUSED(signer);
UNUSED(name);
UNUSED(realm);
+ UNUSED(subdomain);
return (false);
#endif
}
@@ -426,14 +434,13 @@ dst_gssapi_identitymatchesrealmkrb5(const dns_name_t *signer,
bool
dst_gssapi_identitymatchesrealmms(const dns_name_t *signer,
const dns_name_t *name,
- const dns_name_t *realm)
+ const dns_name_t *realm,
+ bool subdomain)
{
#ifdef GSSAPI
char sbuf[DNS_NAME_FORMATSIZE];
- char nbuf[DNS_NAME_FORMATSIZE];
char rbuf[DNS_NAME_FORMATSIZE];
char *sname;
- char *nname;
char *rname;
isc_buffer_t buffer;
isc_result_t result;
@@ -446,8 +453,6 @@ dst_gssapi_identitymatchesrealmms(const dns_name_t *signer,
result = dns_name_toprincipal(signer, &buffer);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
isc_buffer_putuint8(&buffer, 0);
- if (name != NULL)
- dns_name_format(name, nbuf, sizeof(nbuf));
dns_name_format(realm, rbuf, sizeof(rbuf));
/*
@@ -484,39 +489,35 @@ dst_gssapi_identitymatchesrealmms(const dns_name_t *signer,
*sname = '\0';
sname = sbuf;
+ if (strcmp(rname, rbuf) != 0) {
+ return (false);
+ }
+
/*
- * Find the first . in the target name, and make it the end of
- * the string. The rest of the name has to match the realm.
+ * Now, we check that the realm matches (case sensitive) and that
+ * 'name' matches against 'machinename' qualified with 'realm'.
*/
if (name != NULL) {
- nname = strchr(nbuf, '.');
- if (nname == NULL) {
+ dns_fixedname_t fixed;
+ dns_name_t *machine;
+
+ machine = dns_fixedname_initname(&fixed);
+ result = dns_name_fromstring2(machine, sbuf, realm, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
return (false);
}
- *nname++ = '\0';
+ if (subdomain) {
+ return (dns_name_issubdomain(name, machine));
+ }
+ return (dns_name_equal(name, machine));
}
- /*
- * Now, we do a simple comparison between the name and the realm.
- */
- if (name != NULL) {
- if ((strcasecmp(sname, nbuf) == 0)
- && (strcmp(rname, rbuf) == 0)
- && (strcasecmp(nname, rbuf) == 0)) {
- return (true);
- }
- } else {
- if (strcmp(rname, rbuf) == 0) {
- return (true);
- }
- }
-
-
- return (false);
+ return (true);
#else
UNUSED(signer);
UNUSED(name);
UNUSED(realm);
+ UNUSED(subdomain);
return (false);
#endif
}
diff --git a/lib/dns/include/dns/ssu.h b/lib/dns/include/dns/ssu.h
index 6bb15ede0f..a4167c0900 100644
--- a/lib/dns/include/dns/ssu.h
+++ b/lib/dns/include/dns/ssu.h
@@ -39,9 +39,11 @@ typedef enum {
dns_ssumatchtype_6to4self = 11,
dns_ssumatchtype_external = 12,
dns_ssumatchtype_local = 13,
- dns_ssumatchtype_max = 13, /* max value */
+ dns_ssumatchtype_selfsubms = 14,
+ dns_ssumatchtype_selfsubkrb5 = 15,
+ dns_ssumatchtype_max = 15, /* max value */
- dns_ssumatchtype_dlz = 14 /* intentionally higher than _max */
+ dns_ssumatchtype_dlz = 16 /* intentionally higher than _max */
} dns_ssumatchtype_t;
isc_result_t
diff --git a/lib/dns/include/dst/gssapi.h b/lib/dns/include/dst/gssapi.h
index e08dee2801..8ce6c30459 100644
--- a/lib/dns/include/dst/gssapi.h
+++ b/lib/dns/include/dst/gssapi.h
@@ -189,7 +189,8 @@ gss_error_tostring(uint32_t major, uint32_t minor,
bool
dst_gssapi_identitymatchesrealmkrb5(const dns_name_t *signer,
const dns_name_t *name,
- const dns_name_t *realm);
+ const dns_name_t *realm,
+ bool subdomain);
/*
* Compare a "signer" (in the format of a Kerberos-format Kerberos5
* principal: host/example.com@EXAMPLE.COM) to the realm name stored
@@ -200,7 +201,8 @@ dst_gssapi_identitymatchesrealmkrb5(const dns_name_t *signer,
bool
dst_gssapi_identitymatchesrealmms(const dns_name_t *signer,
const dns_name_t *name,
- const dns_name_t *realm);
+ const dns_name_t *realm,
+ bool subdomain);
/*
* Compare a "signer" (in the format of a Kerberos-format Kerberos5
* principal: host/example.com@EXAMPLE.COM) to the realm name stored
diff --git a/lib/dns/ssu.c b/lib/dns/ssu.c
index 7cd664c75e..8767e0ab1a 100644
--- a/lib/dns/ssu.c
+++ b/lib/dns/ssu.c
@@ -388,6 +388,8 @@ dns_ssutable_checkrules(dns_ssutable_t *table, const dns_name_t *signer,
break;
case dns_ssumatchtype_selfkrb5:
case dns_ssumatchtype_selfms:
+ case dns_ssumatchtype_selfsubkrb5:
+ case dns_ssumatchtype_selfsubms:
case dns_ssumatchtype_subdomainkrb5:
case dns_ssumatchtype_subdomainms:
if (signer == NULL)
@@ -457,29 +459,55 @@ dns_ssutable_checkrules(dns_ssutable_t *table, const dns_name_t *signer,
continue;
break;
case dns_ssumatchtype_selfkrb5:
- if (!dst_gssapi_identitymatchesrealmkrb5(signer, name,
- rule->identity))
- continue;
- break;
+ if (dst_gssapi_identitymatchesrealmkrb5(signer, name,
+ rule->identity,
+ false))
+ {
+ break;
+ }
+ continue;
case dns_ssumatchtype_selfms:
- if (!dst_gssapi_identitymatchesrealmms(signer, name,
- rule->identity))
- continue;
- break;
+ if (dst_gssapi_identitymatchesrealmms(signer, name,
+ rule->identity,
+ false))
+ {
+ break;
+ }
+ continue;
+ case dns_ssumatchtype_selfsubkrb5:
+ if (dst_gssapi_identitymatchesrealmkrb5(signer, name,
+ rule->identity,
+ true))
+ {
+ break;
+ }
+ continue;
+ case dns_ssumatchtype_selfsubms:
+ if (dst_gssapi_identitymatchesrealmms(signer, name,
+ rule->identity,
+ true))
+ break;
+ continue;
case dns_ssumatchtype_subdomainkrb5:
if (!dns_name_issubdomain(name, rule->name))
continue;
- if (!dst_gssapi_identitymatchesrealmkrb5(signer, NULL,
- rule->identity))
- continue;
- break;
+ if (dst_gssapi_identitymatchesrealmkrb5(signer, NULL,
+ rule->identity,
+ false))
+ {
+ break;
+ }
+ continue;
case dns_ssumatchtype_subdomainms:
if (!dns_name_issubdomain(name, rule->name))
continue;
- if (!dst_gssapi_identitymatchesrealmms(signer, NULL,
- rule->identity))
- continue;
- break;
+ if (dst_gssapi_identitymatchesrealmms(signer, NULL,
+ rule->identity,
+ false))
+ {
+ break;
+ }
+ continue;
case dns_ssumatchtype_tcpself:
tcpself = dns_fixedname_initname(&fixed);
reverse_from_address(tcpself, addr);
@@ -652,8 +680,12 @@ dns_ssu_mtypefromstring(const char *str, dns_ssumatchtype_t *mtype) {
*mtype = dns_ssumatchtype_selfwild;
} else if (strcasecmp(str, "ms-self") == 0) {
*mtype = dns_ssumatchtype_selfms;
+ } else if (strcasecmp(str, "ms-selfsub") == 0) {
+ *mtype = dns_ssumatchtype_selfsubms;
} else if (strcasecmp(str, "krb5-self") == 0) {
*mtype = dns_ssumatchtype_selfkrb5;
+ } else if (strcasecmp(str, "krb5-selfsub") == 0) {
+ *mtype = dns_ssumatchtype_selfsubkrb5;
} else if (strcasecmp(str, "ms-subdomain") == 0) {
*mtype = dns_ssumatchtype_subdomainms;
} else if (strcasecmp(str, "krb5-subdomain") == 0) {
diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c
index 3f6336d898..c6b1072d88 100644
--- a/lib/isccfg/namedconf.c
+++ b/lib/isccfg/namedconf.c
@@ -323,9 +323,10 @@ doc_matchname(cfg_printer_t *pctx, const cfg_type_t *type) {
}
static const char *matchtype_enums[] = {
- "6to4-self", "external", "krb5-self", "krb5-subdomain", "ms-self",
- "ms-subdomain", "name", "self", "selfsub", "selfwild", "subdomain",
- "tcp-self", "wildcard", "zonesub", NULL
+ "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 cfg_type_t cfg_type_matchtype = {