Add 64-self to 48-self update policy rules

These rules are intended to allow ISP customers to add delegations
in the IPv6 reverse tree that correspond to the IPv6 prefix delegations
that they have recieved from the ISP.  This is similar to the
existing 6to4-self rule which but for the other nibble boundaries
in common use.
This commit is contained in:
Mark Andrews
2025-03-06 15:10:10 +11:00
parent b652d5327c
commit db4c5dfdbc
6 changed files with 137 additions and 24 deletions
+23 -3
View File
@@ -7349,7 +7349,7 @@ records are also written to the zone's filename.
Each rule grants or denies privileges. Rules are checked in the order in
which they are specified in the :any:`update-policy` statement. Once a
message has successfully matched a rule, the operation is immediately
granted or denied, and no further rules are examined. There are 16 types
granted or denied, and no further rules are examined. There are 23 types
of rules; the rule type is specified by the ``ruletype`` field, and the
interpretation of other fields varies depending on the rule type.
@@ -7405,11 +7405,12 @@ records are also written to the zone's filename.
send
EOF
The ruletype field has 18 values: ``name``, ``subdomain``, ``zonesub``,
The ruletype field has 23 values: ``name``, ``subdomain``, ``zonesub``,
``wildcard``, ``self``, ``selfsub``, ``selfwild``, ``ms-self``,
``ms-selfsub``, ``ms-subdomain``, ``ms-subdomain-self-rhs``, ``krb5-self``,
``krb5-selfsub``, ``krb5-subdomain``, ``krb5-subdomain-self-rhs``,
``tcp-self``, ``6to4-self``, and ``external``.
``tcp-self``, ``6to4-self``, ``64-self``, ``60-self``, ``56-self``,
``52-self``, ``48-self`` and ``external``.
``name``
With exact-match semantics, this rule matches when the name being updated is identical to the contents of the ``name`` field.
@@ -7496,6 +7497,25 @@ records are also written to the zone's filename.
.. note::
It is theoretically possible to spoof these TCP sessions.
``64-self``, ``60-self``, ``56-self``, ``52-self``, ``48-self``
These allow records at reverse IPv6 names at the specified
nibble boundary to be updated if a TCP request comes from
an IPv6 address in the matching prefix. These are intended
to allow ISP customers to add delgation records when using
DHCPv6 prefix delegations or when prefix delegation is used
within a site.
::
grant * 64-self * NS DS;
grant ISP-DHCPv6-SERVER-KEY zonesub ANY;
Which will allow customers to add delegation records and the
DHCPv6 server to clean up when the lease expires.
.. note::
It is theoretically possible to spoof these TCP sessions.
``external``
This rule allows :iscman:`named` to defer the decision of whether to allow a given update to an external daemon.
+1 -1
View File
@@ -58,7 +58,7 @@ zone <string> [ <class> ] {
sig-signing-type <integer>;
sig-validity-interval <integer> [ <integer> ]; // obsolete
update-check-ksk <boolean>; // obsolete
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>; ... } );
update-policy ( local | { ( deny | grant ) <string> ( 48-self | 52-self | 56-self | 60-self | 64-self | 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> );
};
+7 -2
View File
@@ -41,9 +41,14 @@ typedef enum {
dns_ssumatchtype_selfsubkrb5 = 15,
dns_ssumatchtype_subdomainselfkrb5rhs = 16,
dns_ssumatchtype_subdomainselfmsrhs = 17,
dns_ssumatchtype_max = 17, /* max value */
dns_ssumatchtype_64self = 18,
dns_ssumatchtype_60self = 19,
dns_ssumatchtype_56self = 20,
dns_ssumatchtype_52self = 21,
dns_ssumatchtype_48self = 22,
dns_ssumatchtype_max = 22, /* max value */
dns_ssumatchtype_dlz = 18 /* intentionally higher than _max */
dns_ssumatchtype_dlz = 23 /* intentionally higher than _max */
} dns_ssumatchtype_t;
typedef struct dns_ssuruletype {
+95 -17
View File
@@ -174,6 +174,16 @@ mtypetostring(dns_ssumatchtype_t matchtype) {
return "local";
case dns_ssumatchtype_dlz:
return "dlz";
case dns_ssumatchtype_64self:
return "64-self";
case dns_ssumatchtype_60self:
return "60-self";
case dns_ssumatchtype_56self:
return "56-self";
case dns_ssumatchtype_52self:
return "52-self";
case dns_ssumatchtype_48self:
return "48-self";
}
return "UnknownMatchType";
}
@@ -282,44 +292,72 @@ reverse_from_address(dns_name_t *tcpself, const isc_netaddr_t *tcpaddr) {
RUNTIME_CHECK(result == ISC_R_SUCCESS);
}
static void
stf_from_address(dns_name_t *stfself, const isc_netaddr_t *tcpaddr) {
char buf[sizeof("X.X.X.X.Y.Y.Y.Y.2.0.0.2.IP6.ARPA.")];
static bool
stf_from_address(dns_name_t *stfself, dns_ssumatchtype_t matchtype,
const isc_netaddr_t *tcpaddr) {
char buf[sizeof("1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.IP6.ARPA.")];
isc_result_t result;
const unsigned char *ap;
isc_buffer_t b;
unsigned long l;
char *s = buf;
int n;
switch (tcpaddr->family) {
case AF_INET:
if (matchtype != dns_ssumatchtype_6to4self) {
return false;
}
l = ntohl(tcpaddr->type.in.s_addr);
result = snprintf(
n = snprintf(
buf, sizeof(buf),
"%lx.%lx.%lx.%lx.%lx.%lx.%lx.%lx.2.0.0.2.IP6.ARPA.",
l & 0xf, (l >> 4) & 0xf, (l >> 8) & 0xf,
(l >> 12) & 0xf, (l >> 16) & 0xf, (l >> 20) & 0xf,
(l >> 24) & 0xf, (l >> 28) & 0xf);
RUNTIME_CHECK(result < sizeof(buf));
RUNTIME_CHECK(n != -1 && (size_t)n < sizeof(buf));
break;
case AF_INET6:
ap = tcpaddr->type.in6.s6_addr;
result = snprintf(
n = snprintf(
buf, sizeof(buf),
"%x.%x.%x.%x.%x.%x.%x.%x."
"%x.%x.%x.%x.IP6.ARPA.",
ap[5] & 0x0f, (ap[5] >> 4) & 0x0f, ap[4] & 0x0f,
(ap[4] >> 4) & 0x0f, ap[3] & 0x0f, (ap[3] >> 4) & 0x0f,
ap[2] & 0x0f, (ap[2] >> 4) & 0x0f, ap[1] & 0x0f,
(ap[1] >> 4) & 0x0f, ap[0] & 0x0f, (ap[0] >> 4) & 0x0f);
RUNTIME_CHECK(result < sizeof(buf));
"%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.IP6."
"ARPA.",
ap[7] & 0x0f, (ap[7] >> 4) & 0x0f, ap[6] & 0x0f,
(ap[6] >> 4) & 0x0f, ap[5] & 0x0f, (ap[5] >> 4) & 0x0f,
ap[4] & 0x0f, (ap[4] >> 4) & 0x0f, ap[3] & 0x0f,
(ap[3] >> 4) & 0x0f, ap[2] & 0x0f, (ap[2] >> 4) & 0x0f,
ap[1] & 0x0f, (ap[1] >> 4) & 0x0f, ap[0] & 0x0f,
(ap[0] >> 4) & 0x0f);
RUNTIME_CHECK(n != -1 && (size_t)n < sizeof(buf));
switch (matchtype) {
case dns_ssumatchtype_64self:
break;
case dns_ssumatchtype_60self:
s += 2;
break;
case dns_ssumatchtype_56self:
s += 4;
break;
case dns_ssumatchtype_52self:
s += 6;
break;
case dns_ssumatchtype_48self:
case dns_ssumatchtype_6to4self:
s += 8;
break;
default:
UNREACHABLE();
}
break;
default:
UNREACHABLE();
}
isc_buffer_init(&b, buf, strlen(buf));
isc_buffer_add(&b, strlen(buf));
isc_buffer_init(&b, s, strlen(s));
isc_buffer_add(&b, strlen(s));
result = dns_name_fromtext(stfself, &b, dns_rootname, 0);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
return true;
}
bool
@@ -402,10 +440,20 @@ dns_ssutable_checkrules(dns_ssutable_t *table, const dns_name_t *signer,
mtypetostring(rule->matchtype),
namebuf);
break;
case dns_ssumatchtype_48self:
case dns_ssumatchtype_52self:
case dns_ssumatchtype_56self:
case dns_ssumatchtype_60self:
case dns_ssumatchtype_64self:
case dns_ssumatchtype_6to4self:
stfself =
dns_fixedname_initname(&fixed);
stf_from_address(stfself, addr);
if (!stf_from_address(stfself,
rule->matchtype,
addr))
{
break;
}
dns_name_format(stfself, namebuf,
sizeof(namebuf));
isc_log_write(
@@ -492,6 +540,11 @@ dns_ssutable_checkrules(dns_ssutable_t *table, const dns_name_t *signer,
}
break;
case dns_ssumatchtype_tcpself:
case dns_ssumatchtype_48self:
case dns_ssumatchtype_52self:
case dns_ssumatchtype_56self:
case dns_ssumatchtype_60self:
case dns_ssumatchtype_64self:
case dns_ssumatchtype_6to4self:
if (!tcp || addr == NULL) {
if (logit) {
@@ -844,9 +897,24 @@ dns_ssutable_checkrules(dns_ssutable_t *table, const dns_name_t *signer,
continue;
}
break;
case dns_ssumatchtype_48self:
case dns_ssumatchtype_52self:
case dns_ssumatchtype_56self:
case dns_ssumatchtype_60self:
case dns_ssumatchtype_64self:
case dns_ssumatchtype_6to4self:
stfself = dns_fixedname_initname(&fixed);
stf_from_address(stfself, addr);
if (!stf_from_address(stfself, rule->matchtype, addr)) {
if (logit) {
isc_log_write(
DNS_LOGCATEGORY_UPDATE_POLICY,
DNS_LOGMODULE_SSU,
ISC_LOG_DEBUG(99),
"update-policy: next "
"rule: not IPv6 address");
}
continue;
}
if (dns_name_iswildcard(rule->identity)) {
if (!dns_name_matcheswildcard(stfself,
rule->identity))
@@ -1123,6 +1191,16 @@ dns_ssu_mtypefromstring(const char *str, dns_ssumatchtype_t *mtype) {
*mtype = dns_ssumatchtype_subdomain;
} else if (strcasecmp(str, "external") == 0) {
*mtype = dns_ssumatchtype_external;
} else if (strcasecmp(str, "64-self") == 0) {
*mtype = dns_ssumatchtype_64self;
} else if (strcasecmp(str, "60-self") == 0) {
*mtype = dns_ssumatchtype_60self;
} else if (strcasecmp(str, "56-self") == 0) {
*mtype = dns_ssumatchtype_56self;
} else if (strcasecmp(str, "52-self") == 0) {
*mtype = dns_ssumatchtype_56self;
} else if (strcasecmp(str, "48-self") == 0) {
*mtype = dns_ssumatchtype_48self;
} else {
return ISC_R_NOTFOUND;
}
+5
View File
@@ -2666,6 +2666,11 @@ check_update_policy(const cfg_obj_t *policy) {
case dns_ssumatchtype_selfsubkrb5:
case dns_ssumatchtype_selfsubms:
case dns_ssumatchtype_tcpself:
case dns_ssumatchtype_48self:
case dns_ssumatchtype_52self:
case dns_ssumatchtype_56self:
case dns_ssumatchtype_60self:
case dns_ssumatchtype_64self:
case dns_ssumatchtype_6to4self:
if (tresult == ISC_R_SUCCESS &&
!dns_name_equal(dns_rootname, name))
+6 -1
View File
@@ -347,7 +347,12 @@ doc_matchname(cfg_printer_t *pctx, const cfg_type_t *type) {
cfg_print_cstr(pctx, " ]");
}
static const char *matchtype_enums[] = { "6to4-self",
static const char *matchtype_enums[] = { "48-self",
"52-self",
"56-self",
"60-self",
"64-self",
"6to4-self",
"external",
"krb5-self",
"krb5-selfsub",