SRV: fixes a long standing neglect of SRV RRs.

This commit is contained in:
Philippe Pittoli 2024-03-18 02:30:39 +01:00
parent 729139232d
commit c7b0826da5

View File

@ -1,5 +1,22 @@
require "ipaddress" require "ipaddress"
# Domains cannot be parsed using regexes.
# Yet, that will be good enough for now.
def label_pattern
/(?:[0-9A-Za-z][0-9A-Za-z-]{0,62})/
end
def subdomain_pattern
/\b(?:[0-9A-Za-z][0-9A-Za-z-]{0,62})(?:\.(?:[0-9A-Za-z][0-9A-Za-z-]{0,62}))*\b/
end
# /^(((?!-))(xn--|_{1,1})?[a-z0-9-]{0,61}[a-z0-9]{1,1}\.)*
# ((xn--)?[a-z0-9][a-z0-9\-]{0,60}[a-z0-9]|(xn--)?[a-z0-9]{1,60})
# \.[a-z]{2,}\.?$/
def hostname_pattern
/\b(?:[0-9A-Za-z][0-9A-Za-z-]{0,62})(?:\.(?:[0-9A-Za-z][0-9A-Za-z-]{0,62}))*(\.?|\b)/
end
# Store a DNS zone. # Store a DNS zone.
# #
# Several common resource record types are accepted: SOA PTR A AAAA TXT CNAME NS MX SRV. # Several common resource record types are accepted: SOA PTR A AAAA TXT CNAME NS MX SRV.
@ -567,10 +584,8 @@ class DNSManager::Storage::Zone
end end
# MX target can either be a subdomain or a FQDN. # MX target can either be a subdomain or a FQDN.
unless Zone.is_subdomain_valid? @target unless (Zone.is_subdomain_valid? @target || Zone.is_domain_valid? @target)
unless Zone.is_domain_valid? @target errors << "MX invalid target (domain or subdomain): #{@target}"
errors << "MX invalid target (domain): #{@target}"
end
end end
errors errors
@ -589,15 +604,15 @@ class DNSManager::Storage::Zone
def get_errors : Array(Error) def get_errors : Array(Error)
errors = [] of Error errors = [] of Error
# SRV name should be created from scratch, client should send an empty name. # SRV name represents the service name.
# WON'T FIX: name verification.
if @ttl < Zone.ttl_limit_min if @ttl < Zone.ttl_limit_min
errors << "SRV invalid ttl: #{@ttl}, shouldn't be less than #{Zone.ttl_limit_min}" errors << "SRV invalid ttl: #{@ttl}, shouldn't be less than #{Zone.ttl_limit_min}"
end end
# SRV target can either be a subdomain or a FQDN.
unless Zone.is_domain_valid? @target unless Zone.is_domain_valid? @target
errors << "SRV invalid target (domain): #{@target}" errors << "SRV invalid target domain: #{@target}"
end end
errors errors
@ -605,7 +620,7 @@ class DNSManager::Storage::Zone
def to_s(io : IO) def to_s(io : IO)
io << "(#{ "%4d" % @rrid }) " io << "(#{ "%4d" % @rrid }) "
io << "#{ "%30s" % @name} " io << "_#{@name.downcase}._#{@protocol.downcase} "
io << "#{ "%6d" % @ttl} SRV " io << "#{ "%6d" % @ttl} SRV "
io << "#{ "%3d" % @priority} " io << "#{ "%3d" % @priority} "
io << "#{ "%3d" % @weight} " io << "#{ "%3d" % @weight} "
@ -614,7 +629,8 @@ class DNSManager::Storage::Zone
end end
def to_bind9(io : IO) def to_bind9(io : IO)
io << "#{@name} #{@ttl} IN SRV #{@priority} #{@weight} #{@port} #{@target}\n" io << "_#{@name.downcase}._#{@protocol.downcase} "
io << "#{@ttl} IN SRV #{@priority} #{@weight} #{@port} #{@target}\n"
end end
end end
@ -703,7 +719,7 @@ class DNSManager::Storage::Zone
# This regex only is "good enough for now". # This regex only is "good enough for now".
def self.is_domain_valid?(domain) : Bool def self.is_domain_valid?(domain) : Bool
if domain =~ /^(((?!-))(xn--|_{1,1})?[a-z0-9-]{0,61}[a-z0-9]{1,1}\.)*((xn--)?[a-z0-9][a-z0-9\-]{0,60}[a-z0-9]|(xn--)?[a-z0-9]{1,60})\.[a-z]{2,}\.?$/ if domain =~ hostname_pattern
true true
else else
false false
@ -715,7 +731,7 @@ class DNSManager::Storage::Zone
# This regex only is "good enough for now". # This regex only is "good enough for now".
def self.is_subdomain_valid?(subdomain) : Bool def self.is_subdomain_valid?(subdomain) : Bool
if subdomain =~ /^(((?!-))(xn--|_{1,1})?[a-z0-9-]{0,61}[a-z0-9]{1,1}\.)*(xn--)?[a-z0-9][a-z0-9\-]{0,60}[a-z0-9]*[a-z]+|[a-z]+|[a-z][a-z0-9]+[a-z]+$/ if subdomain =~ subdomain_pattern
true true
else else
false false