spf-query 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a959789345d1c370b28b097cec96f35fc7507a44
4
+ data.tar.gz: 80505a4705b60f9baea7ed1c53c19b0527864e35
5
+ SHA512:
6
+ metadata.gz: fcf7ff0d96a794fbd894a5a2624ff3e30ed8c777f7deb1c7ee8e3d24c51e1df3b0a08c2f362c3eab1ce9ed38ba41af51d478bbd4e888c1534341705e85987615
7
+ data.tar.gz: d6c48a1958219e3c735b476884612017745a50a12492035fe91ee636b9f7d0b9442e695dfc2a39069ae21f8f0dbeb2abe66b0ffbf2eba9d34f719c62820848bc
data/.gitignore ADDED
@@ -0,0 +1,57 @@
1
+ <<<<<<< HEAD
2
+ <<<<<<< HEAD
3
+ /.bundle/
4
+ /.yardoc
5
+ /Gemfile.lock
6
+ /_yardoc/
7
+ /coverage/
8
+ /doc/
9
+ /pkg/
10
+ /spec/reports/
11
+ /tmp/
12
+ *.bundle
13
+ *.so
14
+ *.o
15
+ *.a
16
+ mkmf.log
17
+ =======
18
+ =======
19
+ >>>>>>> fed1141939dbe709d44dedb0247d31908300c31f
20
+ *.gem
21
+ *.rbc
22
+ /.config
23
+ /coverage/
24
+ /InstalledFiles
25
+ /pkg/
26
+ /spec/reports/
27
+ /test/tmp/
28
+ /test/version_tmp/
29
+ /tmp/
30
+
31
+ ## Specific to RubyMotion:
32
+ .dat*
33
+ .repl_history
34
+ build/
35
+
36
+ ## Documentation cache and generated files:
37
+ /.yardoc/
38
+ /_yardoc/
39
+ /doc/
40
+ /rdoc/
41
+
42
+ ## Environment normalisation:
43
+ /.bundle/
44
+ /lib/bundler/man/
45
+
46
+ # for a library or gem, you might want to ignore these files since the code is
47
+ # intended to run in multiple environments; otherwise, check them in:
48
+ # Gemfile.lock
49
+ # .ruby-version
50
+ # .ruby-gemset
51
+
52
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
53
+ .rvmrc
54
+ <<<<<<< HEAD
55
+ >>>>>>> 62c17ee30b1a7d25ef12fab39fd6c2de0bcbadbc
56
+ =======
57
+ >>>>>>> fed1141939dbe709d44dedb0247d31908300c31f
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour --format documentation
data/.travis.yml ADDED
@@ -0,0 +1,18 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0
5
+ - 2.1
6
+ - ruby-head
7
+ - jruby-19mode
8
+ - jruby-head
9
+ - rbx-2
10
+ matrix:
11
+ allow_failures:
12
+ - rvm: rbx-2
13
+ addons:
14
+ code_climate:
15
+ repo_token: 7ea441f6db20b42bf77b3d49f149f2fd683b58d714a1a2bc148820e963c77862
16
+ notifications:
17
+ slack:
18
+ secure: Z4Wgg8oVW8i20USH3GKfNB9pFR2tmL9a/Pg42Ck/cHNmBO+3UUDcfr7O1oOCrZEYcpobB+7rhLVHt3H0cSwXNDanpsDebi0ZcNHllSK7xDVLR1r0l6QHY15kCKMVIprrDgxCn80ANCE0Yb1x2V+cvZyNJAau6jTLgRmvUZ0oD1Y=
data/ChangeLog.md ADDED
@@ -0,0 +1,6 @@
1
+ ### 0.1.0 / 2015-07-01
2
+
3
+ * Initial release:
4
+ * Queries and parses SPF records.
5
+ * Supports querying both TXT and SPF records.
6
+
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'rake'
7
+ gem 'rspec', '~> 3.0'
8
+
9
+ gem 'yard', '~> 0.8'
10
+ end
11
+
12
+ group :test do
13
+ gem 'json'
14
+ gem 'codeclimate-test-reporter', require: nil
15
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Trail of Bits
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,75 @@
1
+ # spf-query
2
+
3
+ [![Code Climate](https://codeclimate.com/github/trailofbits/spf-query/badges/gpa.svg)](https://codeclimate.com/github/trailofbits/spf-query)
4
+ [![Test Coverage](https://codeclimate.com/github/trailofbits/spf-query/badges/coverage.svg)](https://codeclimate.com/github/trailofbits/spf-query)
5
+ [![Build Status](https://travis-ci.org/trailofbits/spf-query.svg)](https://travis-ci.org/trailofbits/spf-query)
6
+
7
+ The `spf-query` library searches the [SPF] records for a host. We assume the
8
+ host uses standard spf 'selectors', and also check if they use their own
9
+ 'selector'.
10
+
11
+ ## Features
12
+
13
+ * Queries and parses SPF records.
14
+ * Supports querying both TXT and SPF records.
15
+
16
+ ## Examples
17
+
18
+ require 'spf/query'
19
+
20
+ SPF::Query::Record.query('twitter.com')
21
+ # => #<SPF::Query::Record: v=spf1 ip4:199.16.156.0/22 ip4:199.59.148.0/22 ip4:8.25.194.0/23 ip4:8.25.196.0/23 ip4:204.92.114.203 ip4:204.92.114.204/31 ip4:107.20.52.15 ip4:23.21.83.90 include:_spf.google.com include:_thirdparty.twitter.com -all>
22
+
23
+ SPF::Query::Record.parse("v=spf1 ip4:199.16.156.0/22 ip4:199.59.148.0/22 ip4:8.25.194.0/23 ip4:8.25.196.0/23 ip4:204.92.114.203 ip4:204.92.114.204/31 ip4:107.20.52.15 ip4:23.21.83.90 include:_spf.google.com include:_thirdparty.twitter.com -all")
24
+ # => #<SPF::Query::Record: v=spf1 ip4:199.16.156.0/22 ip4:199.59.148.0/22 ip4:8.25.194.0/23 ip4:8.25.196.0/23 ip4:204.92.114.203 ip4:204.92.114.204/31 ip4:107.20.52.15 ip4:23.21.83.90 include:_spf.google.com include:_thirdparty.twitter.com -all>
25
+
26
+
27
+ ## Symopsis
28
+
29
+ Query a domain:
30
+
31
+ spf-query google.com
32
+ ____________________________
33
+ SPF record search for google.com
34
+ - found SPF record for google.com at google.com:
35
+ v=spf1 include:_spf.google.com ip4:216.73.93.70/31 ip4:216.73.93.72/31 ~all
36
+ ____________________________
37
+
38
+
39
+ Query multiple domains:
40
+
41
+ spf-query trailofbits.com facebook.com yahoo.com
42
+ ____________________________
43
+ SPF record search for trailofbits.com
44
+ - found SPF record for trailofbits.com at trailofbits.com:
45
+ v=spf1 include:_spf.google.com ~all
46
+ ____________________________
47
+
48
+ ____________________________
49
+ SPF record search for facebook.com
50
+ - found SPF record for facebook.com at facebook.com:
51
+ v=spf1 redirect=_spf.facebook.com
52
+ ____________________________
53
+
54
+ ____________________________
55
+ SPF record search for yahoo.com
56
+ - found SPF record for yahoo.com at yahoo.com:
57
+ v=spf1 redirect=_spf.mail.yahoo.com
58
+ ____________________________
59
+
60
+ ## Requirements
61
+
62
+ * [ruby] >= 1.9.1
63
+ * [parslet] ~> 1.0
64
+
65
+ ## Install
66
+
67
+ $ gem install spf-query
68
+
69
+ ## License
70
+
71
+ See the {file:LICENSE.txt} file.
72
+
73
+ [ruby]: https://www.ruby-lang.org/
74
+ [parslet]: http://kschiess.github.io/parslet/
75
+ [SPF]: https://tools.ietf.org/html/rfc7208
data/Rakefile ADDED
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+ require 'rubygems'
3
+
4
+ begin
5
+ require 'bundler/setup'
6
+ rescue LoadError => e
7
+ warn e.message
8
+ warn "Run `gem install bundler` to install Bundler."
9
+ exit -1
10
+ end
11
+
12
+ require 'rake'
13
+ require 'bundler/gem_tasks'
14
+
15
+ require 'rspec/core/rake_task'
16
+ RSpec::Core::RakeTask.new
17
+
18
+ task :test => :spec
19
+ task :default => :spec
20
+
21
+ require 'yard'
22
+ YARD::Rake::YardocTask.new
23
+ task :doc => :yard
data/bin/spf-query ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ lib_dir = File.expand_path('../../lib',__FILE__)
4
+ $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
5
+
6
+ require 'spf/query'
7
+
8
+ unless ARGV[0]
9
+ puts "Please supply at least one host name"
10
+ exit
11
+ end
12
+
13
+ ARGV.each do |arg|
14
+ puts "____________________________\n"
15
+ puts "SPF record search for #{arg}"
16
+
17
+ if (spf = SPFParse::Record.query(arg))
18
+ puts " - found SPF record for #{arg}"
19
+ puts " v=#{spf.version}"
20
+
21
+ spf.each do |rule|
22
+ puts " #{rule}"
23
+ end
24
+ else
25
+ puts " - no SPF record found for #{arg}"
26
+ end
27
+ puts "____________________________\n\n"
28
+ end
@@ -0,0 +1,9 @@
1
+ require 'resolv'
2
+
3
+ class Resolv::DNS::Resource::IN::SPF < Resolv::DNS::Resource::IN::TXT
4
+ # resolv.rb doesn't define an SPF resource type.
5
+ TypeValue = 99
6
+ ClassValue = Resolv::DNS::Resource::IN::ClassValue
7
+
8
+ Resolv::DNS::Resource::ClassHash[[TypeValue, ClassValue]] = self
9
+ end
data/lib/spf/query.rb ADDED
@@ -0,0 +1,3 @@
1
+ require "spf/query/query"
2
+ require "spf/query/record"
3
+ require "spf/query/version"
@@ -0,0 +1,8 @@
1
+ require 'parslet'
2
+
3
+ module SPF
4
+ module Query
5
+ class InvalidRecord < Parslet::ParseFailed
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,22 @@
1
+ module SPF
2
+ module Query
3
+ class IP
4
+
5
+ attr_reader :address
6
+
7
+ attr_reader :cidr_length
8
+
9
+ def initialize(address,cidr_length=nil)
10
+ @address = address
11
+ @cidr_length = cidr_length
12
+ end
13
+
14
+ def to_s
15
+ if @cidr_length then "#{@address}/#{@cidr_length}"
16
+ else "#{@address}"
17
+ end
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,28 @@
1
+ module SPF
2
+ module Query
3
+ class Macro
4
+
5
+ attr_reader :letter
6
+
7
+ attr_reader :digits
8
+
9
+ attr_reader :delimiters
10
+
11
+ def initialize(letter,options={})
12
+ @letter = letter
13
+ @digits = options[:digits]
14
+ @reverse = options[:reverse]
15
+ @delimiters = Array(options[:delimiters])
16
+ end
17
+
18
+ def reverse?
19
+ @reverse
20
+ end
21
+
22
+ def to_s
23
+ "%{#{@letter}#{@digits}#{@delimiters.join}}"
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,25 @@
1
+ module SPF
2
+ module Query
3
+ class MacroString
4
+
5
+ include Enumerable
6
+
7
+ def initialize(elements)
8
+ @elements = elements
9
+ end
10
+
11
+ def each(&block)
12
+ @elements.each(&block)
13
+ end
14
+
15
+ def [](*arguments)
16
+ @elements[*arguments]
17
+ end
18
+
19
+ def to_s
20
+ @elements.join
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,52 @@
1
+ module SPF
2
+ module Query
3
+ class Mechanism
4
+
5
+ QUALIFIERS = {
6
+ '+' => :pass,
7
+ '-' => :fail,
8
+ '~' => :soft_fail,
9
+ '?' => :neuatral
10
+ }
11
+
12
+ attr_reader :name
13
+
14
+ attr_reader :value
15
+
16
+ def initialize(name,options={})
17
+ @name = name
18
+
19
+ @value = options[:value]
20
+ @qualifier = options[:qualifier]
21
+ end
22
+
23
+ def qualifier
24
+ @qualifier || :pass
25
+ end
26
+
27
+ def pass?
28
+ @qualifier == :pass || @qualifier.nil?
29
+ end
30
+
31
+ def fail?
32
+ @qualifier == :fail
33
+ end
34
+
35
+ def soft_fail?
36
+ @qualifier == :soft_fail
37
+ end
38
+
39
+ def neutral?
40
+ @qualifier == :neutral
41
+ end
42
+
43
+ def to_s
44
+ str = "#{QUALIFIERS.invert[@qualifier]}#{@name}"
45
+ str << ":#{@value}" if value
46
+
47
+ return str
48
+ end
49
+
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,24 @@
1
+ module SPF
2
+ module Query
3
+ class Modifier
4
+
5
+ attr_reader :name
6
+
7
+ attr_reader :value
8
+
9
+ def initialize(name,value=nil)
10
+ @name, @value = name, value
11
+ end
12
+
13
+ def to_s
14
+ if @value then "#{@name}=#{@value}"
15
+ else "#{@name}"
16
+ end
17
+ end
18
+
19
+ end
20
+
21
+ class UnknownModifier < Modifier
22
+ end
23
+ end
24
+ end