From d87808ca733757e35512b8914e7bfb502bcc6976 Mon Sep 17 00:00:00 2001 From: Joe Cooper Date: Wed, 20 May 2026 19:54:18 -0500 Subject: [PATCH 1/3] Allow underscore in TXT, CNAME, etc. --- bind8/mass_rcreate.cgi | 2 +- bind8/records-lib.pl | 24 +++++++++++++++++------- bind8/save_record.cgi | 10 +++++----- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/bind8/mass_rcreate.cgi b/bind8/mass_rcreate.cgi index 3ef08061a..22c28df99 100755 --- a/bind8/mass_rcreate.cgi +++ b/bind8/mass_rcreate.cgi @@ -23,7 +23,7 @@ foreach my $d (split(/\0/, $in{'d'})) { $access{'ro'} && &error($text{'master_ero'}); # Validate inputs -&valdnsname($in{'name'}) || $in{'name'} eq '@' || &error($text{'rmass_ename'}); +&valdnsname($in{'name'}, 0, undef, $in{'type'}) || $in{'name'} eq '@' || &error($text{'rmass_ename'}); $in{'name'} =~ /\.$/ && &error($text{'rmass_ename2'}); my $mxpri; if ($in{'type'} eq 'A') { diff --git a/bind8/records-lib.pl b/bind8/records-lib.pl index 8c20af4a6..b883c6966 100755 --- a/bind8/records-lib.pl +++ b/bind8/records-lib.pl @@ -726,25 +726,35 @@ return $addr; our $uscore = $config{'allow_underscore'} ? "_" : ""; our $star = $config{'allow_wild'} ? "\\*" : ""; -# valdnsname(name, wild, origin) -# Returns 1 if a DNS record has a valid name +# Record types whose owner names must follow hostname rules. Other types +# (TXT, CNAME, SRV, PTR, TLSA, CAA, ...) may legitimately use underscores +# in their owner names (e.g. _domainkey, _dmarc, _acme-challenge), so the +# allow_underscore config is ignored for them, matching BIND's check-names. +our %hostname_owner_types = map { $_ => 1 } qw(A AAAA MX NS DS DNAME); + +# valdnsname(name, wild, [origin], [type]) +# Returns 1 if a DNS record has a valid name. If a type is supplied and +# isn't one of the hostname-bearing types, underscores are accepted in +# the name regardless of the allow_underscore config. sub valdnsname { -my ($name, $wild, $origin) = @_; +my ($name, $wild, $origin, $type) = @_; my $fqdn = $name !~ /\.$/ ? "$name.$origin." : $name; if (length($fqdn) > 255) { &error(&text('edit_efqdn', $fqdn)); } -if ($_[0] =~ /[^\.]{64}/) { +if ($name =~ /[^\.]{64}/) { # no label longer than 63 chars - &error(&text('edit_elabel', $_[0])); + &error(&text('edit_elabel', $name)); } +my $u = ($config{'allow_underscore'} || + ($type && !$hostname_owner_types{uc($type)})) ? "_" : ""; return ((($wild && $config{'allow_wild'}) - ? (($name =~ /^[\*A-Za-z0-9\-\.$uscore]+$/) + ? (($name =~ /^[\*A-Za-z0-9\-\.$u]+$/) && ($name !~ /.\*/ || $bind_version >= 9) # "*" can be only the first # char, for bind 8 && ($name !~ /\*[^\.]/)) # a "." must always follow "*" - : ($name =~ /^[\A-Za-z0-9\-\.$uscore]+$/)) + : ($name =~ /^[\A-Za-z0-9\-\.$u]+$/)) && ($name !~ /\.\./) # no ".." inside && ($name !~ /^\../) # no "." at the beginning && ($name !~ /^\-/) # no "-" at the beginning diff --git a/bind8/save_record.cgi b/bind8/save_record.cgi index dc3eed0d7..69c1a352a 100755 --- a/bind8/save_record.cgi +++ b/bind8/save_record.cgi @@ -153,7 +153,7 @@ if ($in{'type'} eq "PTR" && $reverse) { } else { # some other kind of record - $in{'name'} eq "" || $in{'name'} eq "@" || &valnamewild($in{'name'}) || + $in{'name'} eq "" || $in{'name'} eq "@" || &valnamewild($in{'name'}, $in{'type'}) || &error(&text('edit_ename', $in{'name'})); if ($in{'type'} eq "A") { &check_ipaddress($vals) || @@ -723,14 +723,14 @@ $r->{'newvalues'} = $vals; &redirect("edit_recs.cgi?zone=$in{'zone'}&view=$in{'view'}&". "type=$in{'redirtype'}&sort=$in{'sort'}"); -# valname(name) +# valname(name, [type]) sub valname { -return valdnsname($_[0], 0, $in{'origin'}); +return valdnsname($_[0], 0, $in{'origin'}, $_[1]); } -# valnamewild(name) +# valnamewild(name, [type]) sub valnamewild { -return valdnsname($_[0], 1, $in{'origin'}); +return valdnsname($_[0], 1, $in{'origin'}, $_[1]); } From 91f51f739072a8a86b24fffb8b1a8657da4376af Mon Sep 17 00:00:00 2001 From: Joe Cooper Date: Wed, 20 May 2026 20:21:40 -0500 Subject: [PATCH 2/3] Handle trailing dot, fix length check in mass_rcreate.cgi --- bind8/mass_rcreate.cgi | 6 ++++++ bind8/records-lib.pl | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/bind8/mass_rcreate.cgi b/bind8/mass_rcreate.cgi index 22c28df99..208d4d96b 100755 --- a/bind8/mass_rcreate.cgi +++ b/bind8/mass_rcreate.cgi @@ -70,6 +70,12 @@ foreach my $zi (@zones) { my $fullname = $in{'name'} eq '@' ? $zi->{'name'}."." : $in{'name'}.".".$zi->{'name'}."."; + if (length($fullname) > 255) { + # The owner name fits on its own but exceeds the 255-octet + # DNS limit once this zone's name is appended; skip this one. + print &text('edit_efqdn', "$fullname"),"

\n"; + next; + } &before_editing($zi); my @recs = &read_zone_file($zi->{'file'}, $zi->{'name'}); my $clash; diff --git a/bind8/records-lib.pl b/bind8/records-lib.pl index b883c6966..a16d2b9e9 100755 --- a/bind8/records-lib.pl +++ b/bind8/records-lib.pl @@ -739,7 +739,10 @@ our %hostname_owner_types = map { $_ => 1 } qw(A AAAA MX NS DS DNAME); sub valdnsname { my ($name, $wild, $origin, $type) = @_; -my $fqdn = $name !~ /\.$/ ? "$name.$origin." : $name; +my $root = !defined($origin) || $origin eq "" || $origin eq "."; +my $fqdn = $name =~ /\.$/ ? $name + : $root ? "$name." + : "$name.$origin."; if (length($fqdn) > 255) { &error(&text('edit_efqdn', $fqdn)); } From e83202988ee9ed8fa74742984d9fcd02e93f5c04 Mon Sep 17 00:00:00 2001 From: Joe Cooper Date: Wed, 20 May 2026 20:51:26 -0500 Subject: [PATCH 3/3] Remove misleading backslash in regex --- bind8/records-lib.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bind8/records-lib.pl b/bind8/records-lib.pl index a16d2b9e9..9a28be1c6 100755 --- a/bind8/records-lib.pl +++ b/bind8/records-lib.pl @@ -757,7 +757,7 @@ return ((($wild && $config{'allow_wild'}) && ($name !~ /.\*/ || $bind_version >= 9) # "*" can be only the first # char, for bind 8 && ($name !~ /\*[^\.]/)) # a "." must always follow "*" - : ($name =~ /^[\A-Za-z0-9\-\.$u]+$/)) + : ($name =~ /^[A-Za-z0-9\-\.$u]+$/)) && ($name !~ /\.\./) # no ".." inside && ($name !~ /^\../) # no "." at the beginning && ($name !~ /^\-/) # no "-" at the beginning