From b2ffe56fc5c53efcd4db58902ca0da1dee64ad2d Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Thu, 30 Aug 2018 18:31:17 +1000 Subject: [PATCH] add krb5-selfsub and ms-selfsub (cherry picked from commit fbeefd4990a53daabcbbc2130b39f0e7e1e6dd50) --- doc/arm/Bv9ARM-book.xml | 31 ++++++++++++- lib/bind9/check.c | 2 + lib/dns/gssapictx.c | 84 ++++++++++++++++++++---------------- lib/dns/include/dns/ssu.h | 6 ++- lib/dns/include/dst/gssapi.h | 12 ++++-- lib/dns/ssu.c | 80 +++++++++++++++++++++++----------- lib/isccfg/namedconf.c | 7 +-- 7 files changed, 150 insertions(+), 72 deletions(-) diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml index 4c4dd14b5e4..baff8d36443 100644 --- a/doc/arm/Bv9ARM-book.xml +++ b/doc/arm/Bv9ARM-book.xml @@ -12573,12 +12573,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, @@ -12737,6 +12738,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. + + + @@ -12808,6 +12823,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 d74b0380ffe..d32a5a17f15 100644 --- a/lib/bind9/check.c +++ b/lib/bind9/check.c @@ -1731,6 +1731,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 cac049867c9..8bd99af343c 100644 --- a/lib/dns/gssapictx.c +++ b/lib/dns/gssapictx.c @@ -345,12 +345,13 @@ cleanup: } bool -dst_gssapi_identitymatchesrealmkrb5(dns_name_t *signer, dns_name_t *name, - dns_name_t *realm) +dst_gssapi_identitymatchesrealmkrb5(const dns_name_t *signer, + const dns_name_t *name, + 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; @@ -365,8 +366,6 @@ dst_gssapi_identitymatchesrealmkrb5(dns_name_t *signer, dns_name_t *name, 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)); /* @@ -380,6 +379,10 @@ dst_gssapi_identitymatchesrealmkrb5(dns_name_t *signer, dns_name_t *name, *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 @@ -397,36 +400,44 @@ dst_gssapi_identitymatchesrealmkrb5(dns_name_t *signer, dns_name_t *name, return (false); /* - * 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); - } else { - if (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); + } + 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 } bool -dst_gssapi_identitymatchesrealmms(dns_name_t *signer, dns_name_t *name, - dns_name_t *realm) +dst_gssapi_identitymatchesrealmms(const dns_name_t *signer, + const dns_name_t *name, + 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; @@ -439,8 +450,6 @@ dst_gssapi_identitymatchesrealmms(dns_name_t *signer, dns_name_t *name, 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)); /* @@ -474,36 +483,35 @@ dst_gssapi_identitymatchesrealmms(dns_name_t *signer, dns_name_t *name, *sname = '\0'; sname = sbuf; - /* - * 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. - */ - if (name != NULL) { - nname = strchr(nbuf, '.'); - if (nname == NULL) - return (false); - *nname++ = '\0'; + if (strcmp(rname, rbuf) != 0) { + return (false); } /* - * Now, we do a simple comparison between the name and the realm. + * Now, we check that the realm matches (case sensitive) and that + * 'name' matches against 'machinename' qualified with '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); - } + 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); + } + 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 } diff --git a/lib/dns/include/dns/ssu.h b/lib/dns/include/dns/ssu.h index da6e3432bd8..402583c7d00 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; #define DNS_SSUMATCHTYPE_NAME dns_ssumatchtype_name diff --git a/lib/dns/include/dst/gssapi.h b/lib/dns/include/dst/gssapi.h index 40257d47961..17a9f548a2e 100644 --- a/lib/dns/include/dst/gssapi.h +++ b/lib/dns/include/dst/gssapi.h @@ -187,8 +187,10 @@ gss_error_tostring(uint32_t major, uint32_t minor, */ bool -dst_gssapi_identitymatchesrealmkrb5(dns_name_t *signer, dns_name_t *name, - dns_name_t *realm); +dst_gssapi_identitymatchesrealmkrb5(const dns_name_t *signer, + const dns_name_t *name, + 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 @@ -197,8 +199,10 @@ dst_gssapi_identitymatchesrealmkrb5(dns_name_t *signer, dns_name_t *name, */ bool -dst_gssapi_identitymatchesrealmms(dns_name_t *signer, dns_name_t *name, - dns_name_t *realm); +dst_gssapi_identitymatchesrealmms(const dns_name_t *signer, + const dns_name_t *name, + 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 8aec053db6b..71ded66bbc0 100644 --- a/lib/dns/ssu.c +++ b/lib/dns/ssu.c @@ -395,10 +395,12 @@ dns_ssutable_checkrules2(dns_ssutable_t *table, dns_name_t *signer, continue; } break; - case DNS_SSUMATCHTYPE_SELFKRB5: - case DNS_SSUMATCHTYPE_SELFMS: - case DNS_SSUMATCHTYPE_SUBDOMAINKRB5: - case DNS_SSUMATCHTYPE_SUBDOMAINMS: + 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) continue; break; @@ -462,30 +464,56 @@ dns_ssutable_checkrules2(dns_ssutable_t *table, dns_name_t *signer, if (!dns_name_matcheswildcard(name, wildcard)) continue; break; - case DNS_SSUMATCHTYPE_SELFKRB5: - if (!dst_gssapi_identitymatchesrealmkrb5(signer, name, - rule->identity)) - continue; - break; - case DNS_SSUMATCHTYPE_SELFMS: - if (!dst_gssapi_identitymatchesrealmms(signer, name, - rule->identity)) - continue; - break; - case DNS_SSUMATCHTYPE_SUBDOMAINKRB5: + case dns_ssumatchtype_selfkrb5: + if (dst_gssapi_identitymatchesrealmkrb5(signer, name, + rule->identity, + false)) + { + break; + } + continue; + case dns_ssumatchtype_selfms: + 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; - case DNS_SSUMATCHTYPE_SUBDOMAINMS: + 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); @@ -658,8 +686,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 0a658c942b9..cd797a6b411 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -320,9 +320,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 = { -- 2.47.3