From c7b0826da54841af55180d86393c2437fe26a12c Mon Sep 17 00:00:00 2001 From: Philippe Pittoli Date: Mon, 18 Mar 2024 02:30:39 +0100 Subject: [PATCH] SRV: fixes a long standing neglect of SRV RRs. --- src/storage/zone.cr | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/src/storage/zone.cr b/src/storage/zone.cr index bcc7532..e7618ed 100644 --- a/src/storage/zone.cr +++ b/src/storage/zone.cr @@ -1,5 +1,22 @@ 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. # # 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 # MX target can either be a subdomain or a FQDN. - unless Zone.is_subdomain_valid? @target - unless Zone.is_domain_valid? @target - errors << "MX invalid target (domain): #{@target}" - end + unless (Zone.is_subdomain_valid? @target || Zone.is_domain_valid? @target) + errors << "MX invalid target (domain or subdomain): #{@target}" end errors @@ -589,15 +604,15 @@ class DNSManager::Storage::Zone def get_errors : Array(Error) errors = [] of Error - # SRV name should be created from scratch, client should send an empty name. - # WON'T FIX: name verification. + # SRV name represents the service name. if @ttl < Zone.ttl_limit_min errors << "SRV invalid ttl: #{@ttl}, shouldn't be less than #{Zone.ttl_limit_min}" end + # SRV target can either be a subdomain or a FQDN. unless Zone.is_domain_valid? @target - errors << "SRV invalid target (domain): #{@target}" + errors << "SRV invalid target domain: #{@target}" end errors @@ -605,7 +620,7 @@ class DNSManager::Storage::Zone def to_s(io : IO) io << "(#{ "%4d" % @rrid }) " - io << "#{ "%30s" % @name} " + io << "_#{@name.downcase}._#{@protocol.downcase} " io << "#{ "%6d" % @ttl} SRV " io << "#{ "%3d" % @priority} " io << "#{ "%3d" % @weight} " @@ -614,7 +629,8 @@ class DNSManager::Storage::Zone end 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 @@ -703,7 +719,7 @@ class DNSManager::Storage::Zone # This regex only is "good enough for now". 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 else false @@ -715,7 +731,7 @@ class DNSManager::Storage::Zone # This regex only is "good enough for now". 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 else false