spf 0.0.26 → 0.0.27

Sign up to get free protection for your applications and to get access to all the features.
data/lib/spf/error.rb CHANGED
@@ -14,15 +14,15 @@ module SPF
14
14
 
15
15
  class DNSError < Error; end # DNS error
16
16
  class DNSTimeoutError < DNSError; end # DNS timeout
17
- class RecordSelectionError < Error; end # Record selection error
18
- class NoAcceptableRecordError < RecordSelectionError; end # No acceptable record found
19
- class RedundantAcceptableRecordsError < RecordSelectionError # Redundant acceptable records found
20
- attr_accessor :records
21
- def initialize(message, records=[])
22
- @records = records
23
- super(message)
24
- end
17
+ class RecordSelectionError < Error # Record selection error
18
+ attr_accessor :records
19
+ def initialize(message, records=[])
20
+ @records = records
21
+ super(message)
25
22
  end
23
+ end
24
+ class NoAcceptableRecordError < RecordSelectionError; end # No acceptable record found
25
+ class RedundantAcceptableRecordsError < RecordSelectionError; end # Redundant acceptable records found
26
26
  class NoUnparsedTextError < Error; end # No unparsed text available
27
27
  class UnexpectedTermObjectError < Error; end # Unexpected term object encountered
28
28
  class ProcessingLimitExceededError < Error; end # Processing limit exceeded
@@ -33,7 +33,7 @@ module SPF
33
33
 
34
34
  class NothingToParseError < Error; end # Nothing to parse
35
35
  class SyntaxError < Error # Generic syntax error
36
- attr_accessor :text, :parse_text
36
+ attr_accessor :text, :parse_text, :domain
37
37
  def initialize(message, text=nil, parse_text=nil)
38
38
  @text = text
39
39
  @parse_text = parse_text
data/lib/spf/eval.rb CHANGED
@@ -44,6 +44,8 @@ class SPF::Server
44
44
  DEFAULT_MAX_NAME_LOOKUPS_PER_PTR_MECH = DEFAULT_MAX_NAME_LOOKUPS_PER_TERM
45
45
  DEFAULT_MAX_VOID_DNS_LOOKUPS = 2
46
46
 
47
+ LOOSE_SPF_MATCH_PATTERN = 'v=spf'
48
+
47
49
  def initialize(options = {})
48
50
  @default_authority_explanation = options[:default_authority_explanation] ||
49
51
  DEFAULT_DEFAULT_AUTHORITY_EXPLANATION
@@ -159,7 +161,7 @@ class SPF::Server
159
161
  return packet
160
162
  end
161
163
 
162
- def select_record(request)
164
+ def select_record(request, loose_match = false)
163
165
  domain = request.authority_domain
164
166
  versions = request.versions
165
167
  scope = request.scope
@@ -169,9 +171,10 @@ class SPF::Server
169
171
  # in future revisions of SPF):
170
172
  # Query for SPF type records first, then fall back to TXT type records.
171
173
 
172
- records = []
173
- query_count = 0
174
- dns_errors = []
174
+ records = []
175
+ loose_records = []
176
+ query_count = 0
177
+ dns_errors = []
175
178
 
176
179
  # Query for SPF-type RRs first:
177
180
  if (@query_rr_types == QUERY_RR_TYPE_ALL or
@@ -179,8 +182,10 @@ class SPF::Server
179
182
  begin
180
183
  query_count += 1
181
184
  packet = self.dns_lookup(domain, 'SPF')
182
- records << self.get_acceptable_records_from_packet(
183
- packet, 'SPF', versions, scope, domain)
185
+ matches = self.get_acceptable_records_from_packet(
186
+ packet, 'SPF', versions, scope, domain, loose_match)
187
+ records << matches[0]
188
+ loose_records << matches[1]
184
189
  rescue SPF::DNSError => e
185
190
  dns_errors << e
186
191
  #rescue SPF::DNSTimeout => e
@@ -205,8 +210,10 @@ class SPF::Server
205
210
  begin
206
211
  query_count += 1
207
212
  packet = self.dns_lookup(domain, 'TXT')
208
- records << self.get_acceptable_records_from_packet(
209
- packet, 'TXT', versions, scope, domain)
213
+ matches = self.get_acceptable_records_from_packet(
214
+ packet, 'TXT', versions, scope, domain, loose_match)
215
+ records << matches[0]
216
+ loose_records << matches[1]
210
217
  rescue SPF::DNSError => e
211
218
  dns_errors << e
212
219
  end
@@ -215,10 +222,12 @@ class SPF::Server
215
222
  raise dns_errors[0] unless dns_errors.length < query_count
216
223
 
217
224
  records.flatten!
225
+ loose_records.flatten!
218
226
 
219
227
  if records.empty?
220
228
  # RFC 4408, 4.5/7
221
- raise SPF::NoAcceptableRecordError.new('No applicable sender policy available')
229
+ raise SPF::NoAcceptableRecordError.new('No applicable sender policy available',
230
+ loose_records)
222
231
  end
223
232
 
224
233
  # Discard all records but the highest acceptable version:
@@ -238,7 +247,7 @@ class SPF::Server
238
247
  end
239
248
  end
240
249
 
241
- def get_acceptable_records_from_packet(packet, rr_type, versions, scope, domain)
250
+ def get_acceptable_records_from_packet(packet, rr_type, versions, scope, domain, loose_match)
242
251
 
243
252
  # Try higher record versions first.
244
253
  # (This may be too simplistic for future revisions of SPF.)
@@ -246,6 +255,7 @@ class SPF::Server
246
255
 
247
256
  rr_type = resource_typeclass_for_rr_type(rr_type)
248
257
  records = []
258
+ possible_matches = []
249
259
  packet.each do |rr|
250
260
  next unless rr_type === rr
251
261
  text = rr.strings.join('')
@@ -255,6 +265,9 @@ class SPF::Server
255
265
  begin
256
266
  record = klass.new_from_string(text, {:raise_exceptions => @raise_exceptions})
257
267
  rescue SPF::InvalidRecordVersionError => error
268
+ if text =~ /#{LOOSE_SPF_MATCH_PATTERN}/
269
+ possible_matches << text
270
+ end
258
271
  # Ignore non-SPF and unknown-version records.
259
272
  # Propagate other errors (including syntax errors), though.
260
273
  end
@@ -266,7 +279,7 @@ class SPF::Server
266
279
  end
267
280
  end
268
281
  end
269
- return records
282
+ return records, possible_matches
270
283
  end
271
284
 
272
285
  def count_dns_interactive_term(request)
data/lib/spf/model.rb CHANGED
@@ -551,12 +551,12 @@ class SPF::Mech < SPF::Term
551
551
  raise result
552
552
  end
553
553
 
554
- def nested_record(server=nil, request=nil)
554
+ def nested_record(server=nil, request=nil, loose_match = false)
555
555
  return @nested_record if @nested_record
556
556
  authority_domain = self.domain(server, request)
557
557
  return nil unless request
558
558
  sub_request = request.new_sub_request({:authority_domain => authority_domain})
559
- return @nested_record = server.select_record(sub_request)
559
+ return @nested_record = server.select_record(sub_request, loose_match)
560
560
  end
561
561
 
562
562
  end
data/lib/spf/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module SPF
2
- VERSION = '0.0.26'
2
+ VERSION = '0.0.27'
3
3
  end
4
4
 
5
5
  # vim:sw=2 sts=2
data/spf.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "spf"
8
- s.version = "0.0.26"
8
+ s.version = "0.0.27"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Andrew Flury", "Julian Mehnle"]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.26
4
+ version: 0.0.27
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors: