Merge pull request #2725 from swelljoe/bogus-bind-restriction
Some checks failed
Tests / prove (push) Has been cancelled
webmin.dev: webmin/webmin / build (push) Has been cancelled

Allow underscore in TXT, CNAME, etc.
This commit is contained in:
Jamie Cameron
2026-05-20 20:47:40 -07:00
committed by GitHub
3 changed files with 33 additions and 14 deletions

View File

@@ -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') {
@@ -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', "<tt>$fullname</tt>"),"<p>\n";
next;
}
&before_editing($zi);
my @recs = &read_zone_file($zi->{'file'}, $zi->{'name'});
my $clash;

View File

@@ -726,25 +726,38 @@ 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 $fqdn = $name !~ /\.$/ ? "$name.$origin." : $name;
my ($name, $wild, $origin, $type) = @_;
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));
}
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

View File

@@ -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]);
}