-
Notifications
You must be signed in to change notification settings - Fork 10
Description
I've spent a significant amount of time trying to debug/fix this issue but the further down the rabbit hole I get, the more I'm worried that I don't fully understand how to handle global modifiers.
If you have an spf record that has includes:gmail.com - Gmail subsequently uses a redirect global modifier redirect=_spf.google.com (the entire txt record is v=spf1 redirect=_spf.google.com)
When this gem goes into SPF::Record#eval there are no @terms for this subrequest so the .each block just returns [] and the rescue SPF::Result => result on line 1001 never gets hit which would break into the processing of the global mods. Result for this subrequest is nil and when that's being raised (since we never processed the global_mod to get a result) we get TypeError: exception object expected
Even when I modify the conditional to check if there are global_mods present but no terms present and then hit global_mod.process(server, request, result) for the one global_mod - SPF::Mod::Redirect seems to incorrectly try and call authority_domain = @domain_spec.new({:server => server, :request => request}) (@domain_spec is already a SPF::MacroString and doesn't respond to new). If SPF::Mod::Redirect is modified to act like SPF::Mech::Include and call
authority_domain = self.domain(server, request) it will try to process all the sub requests for the redirect:_spf.google.com but eventually returns nil which bubbles up through the call stack and I'm eventually left in the same place with nil trying to be raised somewhere along the line which produces TypeError: exception object expected
I would be more than happy to work on this with someone more knowledgeable but at this point I've just followed this so far down the hole to the point that I'm not sure I fully understand what's going on or would be able to without some assistance. 🤘
Here's what happens if you just call the gem without any of the debugging/fixes that I've tried to put in place:
$ be irb 2.2.2
irb(main):001:0> require 'spf'
=> true
irb(main):002:0> spf_server = SPF::Server.new
=> #<SPF::Server:0x007fbed93910a8 @default_authority_explanation=#<SPF::MacroString:0x007fbed9390fe0 @text="Please see http://www.openspf.org/Why?s=%{_scope};id=%{S};ip=%{C};r=%{R}", @server=#<SPF::Server:0x007fbed93910a8 ...>, @request=nil, @expanded="Please see http://www.openspf.org/Why?s=%{_scope};id=%{S};ip=%{C};r=%{R}">, @hostname="scott-berke-mba.local", @dns_resolver=#<Resolv::DNS:0x007fbed9390bd0 @mutex=#<Mutex:0x007fbed9390b30>, @config=#<Resolv::DNS::Config:0x007fbed9390b08 @mutex=#<Mutex:0x007fbed9390a90>, @config_info=nil, @initialized=nil, @timeouts=nil>, @initialized=nil>, @query_rr_types=1, @max_dns_interactive_terms=10, @max_name_lookups_per_term=10, @max_name_lookups_per_mx_mech=10, @max_name_lookups_per_ptr_mech=10, @max_void_dns_lookups=2, @raise_exceptions=true>
irb(main):003:0> request = SPF::Request.new(
irb(main):004:1* versions: [1],
irb(main):005:1* scope: 'mfrom',
irb(main):006:1* identity: "example@gmail.com",
irb(main):007:1* ip_address: "167.89.50.131"
irb(main):008:1> )
=> #<SPF::Request:0x007fbed934aef0 @opt={:versions=>[1], :scope=>"mfrom", :identity=>"example@gmail.com", :ip_address=>"167.89.50.131"}, @state={}, @versions=[1], @scope=:mfrom, @authority_domain=nil, @identity="example@gmail.com", @ip_address=#<IP::V4 167.89.50.131>, @helo_identity=nil, @root_request=#<SPF::Request:0x007fbed934aef0 ...>, @super_request=#<SPF::Request:0x007fbed934aef0 ...>, @record=nil, @sub_requests=[], @localpart="example", @domain="gmail.com", @ip_address_v6=#<IP::V6 ::ffff:167.89.50.131>>
irb(main):009:0> spf_server.process(request)
TypeError: exception object expected
from /Users/scottberke/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spf-0.0.46/lib/spf/model.rb:566:in `raise'
from /Users/scottberke/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spf-0.0.46/lib/spf/model.rb:566:in `match'
from /Users/scottberke/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spf-0.0.46/lib/spf/model.rb:989:in `block in eval'
from /Users/scottberke/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spf-0.0.46/lib/spf/model.rb:985:in `each'
from /Users/scottberke/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spf-0.0.46/lib/spf/model.rb:985:in `eval'
from /Users/scottberke/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spf-0.0.46/lib/spf/eval.rb:103:in `process'
from /Users/scottberke/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spf-0.0.46/lib/spf/model.rb:799:in `process'
from /Users/scottberke/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spf-0.0.46/lib/spf/model.rb:1020:in `block in process_global_mods'
from /Users/scottberke/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spf-0.0.46/lib/spf/model.rb:1019:in `each'
from /Users/scottberke/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spf-0.0.46/lib/spf/model.rb:1019:in `process_global_mods'
from /Users/scottberke/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spf-0.0.46/lib/spf/model.rb:983:in `eval'
from /Users/scottberke/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/spf-0.0.46/lib/spf/eval.rb:103:in `process'
from (irb):9
from /Users/scottberke/.rbenv/versions/2.2.2/bin/irb:11:in `<main>'
irb(main):010:0> ```