DMARC.
This commit is contained in:
		
							parent
							
								
									cad863e5f9
								
							
						
					
					
						commit
						9b6457f575
					
				
					 1 changed files with 140 additions and 7 deletions
				
			
		| 
						 | 
				
			
			@ -521,11 +521,11 @@ class DNSManager::Storage::Zone
 | 
			
		|||
			errors = [] of Error
 | 
			
		||||
 | 
			
		||||
			unless Zone.is_subdomain_valid? @name
 | 
			
		||||
				errors << "CNAME invalid subdomain: #{@name}"
 | 
			
		||||
				errors << "DKIM invalid subdomain: #{@name}"
 | 
			
		||||
			end
 | 
			
		||||
 | 
			
		||||
			if @ttl < Zone.ttl_limit_min
 | 
			
		||||
				errors << "CNAME invalid ttl: #{@ttl}, shouldn't be less than #{Zone.ttl_limit_min}"
 | 
			
		||||
				errors << "DKIM invalid ttl: #{@ttl}, shouldn't be less than #{Zone.ttl_limit_min}"
 | 
			
		||||
			end
 | 
			
		||||
			errors
 | 
			
		||||
		end
 | 
			
		||||
| 
						 | 
				
			
			@ -542,22 +542,155 @@ class DNSManager::Storage::Zone
 | 
			
		|||
 | 
			
		||||
	# TODO
 | 
			
		||||
	class DMARC < ResourceRecord
 | 
			
		||||
		def initialize(@name, @ttl, @target)
 | 
			
		||||
		enum Version
 | 
			
		||||
			DMARC1
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		class DMARCURI
 | 
			
		||||
			include JSON::Serializable
 | 
			
		||||
			property mail : String
 | 
			
		||||
			property limit : UInt32? = nil
 | 
			
		||||
 | 
			
		||||
			def to_s(io : IO)
 | 
			
		||||
				io << "#{mail}"
 | 
			
		||||
				if l = @limit
 | 
			
		||||
					io << "!#{l}k"
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		enum ReportFormat
 | 
			
		||||
			AFRF
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		enum ConsistencyPolicy
 | 
			
		||||
			Strict
 | 
			
		||||
			Relaxed
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		enum Policy
 | 
			
		||||
			None
 | 
			
		||||
			Quarantine
 | 
			
		||||
			Reject
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		enum ReportOccasion
 | 
			
		||||
			BOTH
 | 
			
		||||
			DKIMONLY
 | 
			
		||||
			SPFONLY
 | 
			
		||||
			ANY
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		class DMARCProperties
 | 
			
		||||
			include JSON::Serializable
 | 
			
		||||
 | 
			
		||||
			property p     : Policy
 | 
			
		||||
			property sp    : Policy? = nil
 | 
			
		||||
			property v     : Version = Version::DMARC1
 | 
			
		||||
			property adkim : ConsistencyPolicy? = nil
 | 
			
		||||
			property aspf  : ConsistencyPolicy? = nil
 | 
			
		||||
			property pct   : UInt32? = nil
 | 
			
		||||
			property fo    : ReportOccasion? = nil
 | 
			
		||||
			property rua   : Array(DMARCURI)? = nil
 | 
			
		||||
			property ruf   : Array(DMARCURI)? = nil
 | 
			
		||||
			property rf    : Array(ReportFormat)? = nil
 | 
			
		||||
			property ri    : UInt32
 | 
			
		||||
 | 
			
		||||
			def initialize(@p, @sp, @v, @adkim, @aspf, @pct, @fo, @rua, @ruf, @rf, @ri)
 | 
			
		||||
			end
 | 
			
		||||
 | 
			
		||||
			def self.consistency_policy_to_bind9(p : ConsistencyPolicy)
 | 
			
		||||
				p == ConsistencyPolicy::Strict ? "s" : "r"
 | 
			
		||||
			end
 | 
			
		||||
 | 
			
		||||
			def self.report_occasion_to_bind9(fo : ReportOccasion)
 | 
			
		||||
				case fo
 | 
			
		||||
				when ReportOccasion::BOTH
 | 
			
		||||
					"0"
 | 
			
		||||
				when ReportOccasion::DKIMONLY
 | 
			
		||||
					"d"
 | 
			
		||||
				when ReportOccasion::SPFONLY
 | 
			
		||||
					"s"
 | 
			
		||||
				else
 | 
			
		||||
					"1"
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
 | 
			
		||||
			def to_s(io : IO)
 | 
			
		||||
				io << "v=#{v}"
 | 
			
		||||
				io << ";p=#{@p.to_s.downcase}"
 | 
			
		||||
				if val = @sp
 | 
			
		||||
					io << ";sp=#{val.to_s.downcase}"
 | 
			
		||||
				end
 | 
			
		||||
				if val = adkim
 | 
			
		||||
					io << ";adkim=#{DMARCProperties.consistency_policy_to_bind9(val)}"
 | 
			
		||||
				end
 | 
			
		||||
				if val = aspf
 | 
			
		||||
					io << ";aspf=#{DMARCProperties.consistency_policy_to_bind9(val)}"
 | 
			
		||||
				end
 | 
			
		||||
				if val = pct
 | 
			
		||||
					io << ";pct=#{val}"
 | 
			
		||||
				end
 | 
			
		||||
				if val = fo
 | 
			
		||||
					io << ";fo=#{DMARCProperties.report_occasion_to_bind9(val)}"
 | 
			
		||||
				end
 | 
			
		||||
				if val = rua
 | 
			
		||||
					io << ";rua="
 | 
			
		||||
					arr = val.map { |x| x.to_s }
 | 
			
		||||
					while arr.size > 1
 | 
			
		||||
						io << arr.pop
 | 
			
		||||
						io << ","
 | 
			
		||||
					end
 | 
			
		||||
					io << arr.pop
 | 
			
		||||
				end
 | 
			
		||||
				if val = ruf
 | 
			
		||||
					io << ";ruf="
 | 
			
		||||
					arr = val.map { |x| x.to_s }
 | 
			
		||||
					while arr.size > 1
 | 
			
		||||
						io << arr.pop
 | 
			
		||||
						io << ","
 | 
			
		||||
					end
 | 
			
		||||
					io << arr.pop
 | 
			
		||||
				end
 | 
			
		||||
				if val = rf
 | 
			
		||||
					io << ";rf=#{val}"
 | 
			
		||||
				end
 | 
			
		||||
				if val = ri
 | 
			
		||||
					io << ";ri=#{val}"
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		property dmarc : DMARCProperties
 | 
			
		||||
 | 
			
		||||
		def initialize(@name, @ttl, @target,
 | 
			
		||||
		               p, sp, v, adkim, aspf, pct, fo, rua, ruf, rf, ri)
 | 
			
		||||
			@rrtype = "DMARC"
 | 
			
		||||
			@dmarc = DMARCProperties.new p, sp, v, adkim, aspf, pct, fo, rua, ruf, rf, ri
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		def get_errors : Array(Error)
 | 
			
		||||
			errors = [] of Error
 | 
			
		||||
 | 
			
		||||
			unless Zone.is_subdomain_valid? @name
 | 
			
		||||
				errors << "CNAME invalid subdomain: #{@name}"
 | 
			
		||||
			end
 | 
			
		||||
			# TODO: label can (and is expected to) start with an underscore.
 | 
			
		||||
			#unless Zone.is_subdomain_valid? @name
 | 
			
		||||
			#	errors << "DMARC invalid subdomain: #{@name}"
 | 
			
		||||
			#end
 | 
			
		||||
 | 
			
		||||
			if @ttl < Zone.ttl_limit_min
 | 
			
		||||
				errors << "CNAME invalid ttl: #{@ttl}, shouldn't be less than #{Zone.ttl_limit_min}"
 | 
			
		||||
				errors << "DMARC invalid ttl: #{@ttl}, shouldn't be less than #{Zone.ttl_limit_min}"
 | 
			
		||||
			end
 | 
			
		||||
			errors
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		def to_s(io : IO)
 | 
			
		||||
			io << "(#{ "%4d" % @rrid }) "
 | 
			
		||||
			io << "#{ "%30s" % @name} #{ "%6d" % @ttl} DMARC #{split_line dmarc.to_s}\n"
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		def to_bind9(io : IO)
 | 
			
		||||
			io << "#{@name} #{@ttl} IN TXT #{split_line dmarc.to_s}\n"
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	class MX < ResourceRecord
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue