dkimverify 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: be888e240c37308c063950bd2bab4b67c28d0b62
4
+ data.tar.gz: 2726298b7ec6e5ac4dc7c00392908de20ad33744
5
+ SHA512:
6
+ metadata.gz: 33a309ba077205dd8d3683a6460a9bc89afc6177cbef24601628b2368886ebd81fae09ed500b6333bc7973f91e4c3d7a5297514fc0615e60f3ceb14e966acd15
7
+ data.tar.gz: 7078d239bbc4d4a2efbccbcd1c36b7267945d70150937245f1397d463da747837e65f6e77c80592077e7108104655b76717ebb6aa427071bd95037e20faf2d17
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ pydkim
2
+ *.gem
3
+ Gemfile.lock # becuase this is a gem and apparently you're not supposed to check that in for gems
4
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Jeremy B. F. Merrill
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,28 @@
1
+ dkimverify
2
+ ==========
3
+
4
+ a gem for verifying DKIM signatures in Ruby
5
+
6
+ this gem does not sign mail messages (but a PR to enable it would likely be accepted, I just have no use for it.)
7
+
8
+ with a debt of gratitude to:
9
+ ----------------------------
10
+
11
+ - [pydkim](https://github.com/ghewgill/pydkim) by @ghewgill which I used as a reference implementation
12
+ - [dkim-query](https://github.com/trailofbits/dkim-query) by @trailofbits (and included here in slightly-modified form)
13
+ - [mail](https://github.com/mikel/mail) by @mikel
14
+ - [carsonreinke's fork of the jhawthorne's dkim gem](https://github.com/carsonreinke/dkim/tree/feature_verification) which I wish I had found before I started this.
15
+ - [rfc6376 authors](https://tools.ietf.org/html/rfc6376)
16
+
17
+ not yet implemented
18
+ -------------------
19
+ checking expiration dates (x=, t=)
20
+ accounting for length limits (l= tag)
21
+ tests (which I really ought to add)
22
+
23
+ by
24
+ --
25
+
26
+ Jeremy B. Merrill
27
+ The New York Times
28
+ January 2017
@@ -0,0 +1,51 @@
1
+ <<<<<<< HEAD
2
+ /.bundle/
3
+ /.yardoc
4
+ /Gemfile.lock
5
+ /_yardoc/
6
+ /coverage/
7
+ /doc/
8
+ /pkg/
9
+ /spec/reports/
10
+ /tmp/
11
+ *.bundle
12
+ *.so
13
+ *.o
14
+ *.a
15
+ mkmf.log
16
+ =======
17
+ *.gem
18
+ *.rbc
19
+ /.config
20
+ /coverage/
21
+ /InstalledFiles
22
+ /pkg/
23
+ /spec/reports/
24
+ /test/tmp/
25
+ /test/version_tmp/
26
+ /tmp/
27
+
28
+ ## Specific to RubyMotion:
29
+ .dat*
30
+ .repl_history
31
+ build/
32
+
33
+ ## Documentation cache and generated files:
34
+ /.yardoc/
35
+ /_yardoc/
36
+ /doc/
37
+ /rdoc/
38
+
39
+ ## Environment normalisation:
40
+ /.bundle/
41
+ /lib/bundler/man/
42
+
43
+ # for a library or gem, you might want to ignore these files since the code is
44
+ # intended to run in multiple environments; otherwise, check them in:
45
+ # Gemfile.lock
46
+ # .ruby-version
47
+ # .ruby-gemset
48
+
49
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
50
+ .rvmrc
51
+ >>>>>>> 62c17ee30b1a7d25ef12fab39fd6c2de0bcbadbc
data/dkim-query/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour --format documentation
@@ -0,0 +1,16 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.8
4
+ - 2.2.4
5
+ - 2.3.0
6
+ - jruby
7
+ - rbx-2
8
+ matrix:
9
+ allow_failures:
10
+ - rvm: rbx-2
11
+ addons:
12
+ code_climate:
13
+ repo_token: 151a667c2c51ff76ac825c07c33e8e63c1ae9956a73f4d0ec7a043d877d05c95
14
+ notifications:
15
+ slack:
16
+ secure: Ykcz/gLRZcXhyOGedVgj1u3CDUbZS4y/nL1dREBE0Ar73Vrz+ulcMhri3VzfVBQGkWw06EjqHcIwsIomEInLJKxk3RTfpcYQAdYN+5iEDNOri9a5NK618WdrCuaCS3sKqYbJ/KB0slJDcJ1W+EXkr4GRqZTr5rPdmllUnoaqDCQ=
@@ -0,0 +1 @@
1
+ --markup markdown --title "DKIM::Query Documentation" --protected
@@ -0,0 +1,25 @@
1
+ ### 0.2.6 / 2016-08-3
2
+
3
+ * Fixed a typo in the parser rules.
4
+
5
+ ### 0.2.5 / 2016-06-17
6
+
7
+ * Added `mandrill` and `google` to the list of default DKIM selectors.
8
+
9
+ ### 0.2.4 / 2015-08-13
10
+
11
+ * Fixed a bug where the queried host has no TLD (ex: `test`).
12
+
13
+ ### 0.2.3 / 2015-07-22
14
+
15
+ * Fixed a typo in the `dkim-query` util.
16
+ * Convert all text into Strings.
17
+ * Convert `t=y` or `t=s` values to Symbols.
18
+
19
+ ### 0.2.2 / 2015-07-04
20
+
21
+ * Fixed {DKIM::Query::MalformedKey#to_s}.
22
+
23
+ ### 0.2.1 / 2015-07-01
24
+
25
+ * Initial release.
@@ -0,0 +1,19 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in dkim-query.gemspec
4
+ gemspec
5
+
6
+ group :development do
7
+ gem 'rake'
8
+ gem 'rubygems-tasks', '~> 0.2'
9
+
10
+ gem 'rspec', '~> 3.0'
11
+
12
+ gem 'kramdown'
13
+ gem 'yard', '~> 0.8'
14
+ end
15
+
16
+ group :test do
17
+ gem 'json'
18
+ gem 'codeclimate-test-reporter', require: nil
19
+ end
@@ -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.
@@ -0,0 +1,105 @@
1
+ # dkim-query
2
+
3
+ [![Code Climate](https://codeclimate.com/github/trailofbits/dkim-query/badges/gpa.svg)](https://codeclimate.com/github/trailofbits/dkim-query)
4
+ [![Test Coverage](https://codeclimate.com/github/trailofbits/dkim-query/badges/coverage.svg)](https://codeclimate.com/github/trailofbits/dkim-query)
5
+ [![Build Status](https://travis-ci.org/trailofbits/dkim-query.svg)](https://travis-ci.org/trailofbits/dkim-query)
6
+
7
+ The `dkim-query` library searches the [DKIM] records for a host. We assume the
8
+ host uses standard dkim 'selectors', and also check if they use their own
9
+ 'selector'.
10
+
11
+ ## Examples
12
+
13
+ Parse a DKIM record:
14
+
15
+ require 'dkim/query'
16
+
17
+ key = DKIM::Query::Key.parse("k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDrEee0Ri4Juz+QfiWYui/E9UGSXau/2P8LjnTD8V4Unn+2FAZVGE3kL23bzeoULYv4PeleB3gfmJiDJOKU3Ns5L4KJAUUHjFwDebt0NP+sBK0VKeTATL2Yr/S3bT/xhy+1xtj4RkdV7fVxTn56Lb4udUnwuxK4V5b5PdOKj/+XcwIDAQAB; n=A 1024 bit key")
18
+
19
+ key.v
20
+ # => nil
21
+
22
+ key.g
23
+ # => nil
24
+
25
+ key.h
26
+ # => nil
27
+
28
+ key.k
29
+ # => :rsa
30
+
31
+ key.n
32
+ # => "A 1024 bit key"
33
+
34
+ key.p
35
+ # => "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDrEee0Ri4Juz+QfiWYui/E9UGSXau/2P8LjnTD8V4Unn+2FAZVGE3kL23bzeoULYv4PeleB3gfmJiDJOKU3Ns5L4KJAUUHjFwDebt0NP+sBK0VKeTATL2Yr/S3bT/xhy+1xtj4RkdV7fVxTn56Lb4udUnwuxK4V5b5PdOKj/+XcwIDAQAB"
36
+
37
+ key.s
38
+ # => nil
39
+
40
+ key.t
41
+ # => nil
42
+
43
+ Query all keys for a domain:
44
+
45
+ domain = DKIM::Query::Domain.query('yahoo.com')
46
+ # => #<DKIM::Query::Domain:0x0000000315c950 @name="yahoo.com", @keys={"s1024"=>#<DKIM::Query::Key:0x0000000315c9f0 @v=nil, @g=nil, @h=nil, @k=:rsa, @n="A 1024 bit key;", @p="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDrEee0Ri4Juz+QfiWYui/E9UGSXau/2P8LjnTD8V4Unn+2FAZVGE3kL23bzeoULYv4PeleB3gfmJiDJOKU3Ns5L4KJAUUHjFwDebt0NP+sBK0VKeTATL2Yr/S3bT/xhy+1xtj4RkdV7fVxTn56Lb4udUnwuxK4V5b5PdOKj/+XcwIDAQAB", @s=nil, @t=nil>}>
47
+
48
+ domain['s1024']
49
+ # => #<DKIM::Query::Key:0x0000000315c9f0 @v=nil, @g=nil, @h=nil, @k=:rsa, @n="A 1024 bit key;", @p="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDrEee0Ri4Juz+QfiWYui/E9UGSXau/2P8LjnTD8V4Unn+2FAZVGE3kL23bzeoULYv4PeleB3gfmJiDJOKU3Ns5L4KJAUUHjFwDebt0NP+sBK0VKeTATL2Yr/S3bT/xhy+1xtj4RkdV7fVxTn56Lb4udUnwuxK4V5b5PdOKj/+XcwIDAQAB", @s=nil, @t=nil>
50
+
51
+ domain.each do |key|
52
+ # ...
53
+ end
54
+
55
+ ## Synopsis
56
+
57
+ Query a domain:
58
+
59
+ dkim-query google.com
60
+ ____________________________
61
+ DKIM record search for google.com
62
+ - using selectors: ["default", "dkim", "google"]
63
+ - no DKIM record found for google.com
64
+ ____________________________
65
+
66
+
67
+ Query multiple domains:
68
+
69
+ dkim-query trailofbits.com facebook.com yahoo.com
70
+ ____________________________
71
+ DKIM record search for trailofbits.com
72
+ - using selectors: ["default", "dkim", "google", "trailofbits"]
73
+ - found DKIM record for trailofbits.com at trailofbits._domainkey.trailofbits.com:
74
+ v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwe04g1hSR55ACcRiLAg0MoEiY5BBviJHJHq/d9r6o+F50fa1TrNNulwKXaST+WCEcW6D2KZ+dt9JvgB9ApIEAFCzHRXhawga0GsfDkOllvpXgT95IPcnYrSkM+rJSbaqHh+YI5sV9sKnvzZDVmB7l5gU3yD74aDmjs9wSg8RC5wIDAQAB
75
+ ____________________________
76
+
77
+ ____________________________
78
+ DKIM record search for facebook.com
79
+ - using selectors: ["default", "dkim", "google", "facebook"]
80
+ - found DKIM record for facebook.com at default._domainkey.facebook.com:
81
+ t=y; k=rsa; p=MHwwDQYJKoZIhvcNAQEBBQADawAwaAJhALkZ4wTn2SQ3EW0vVBExi8izmZZnjZH8JIY5Y964jzDORZku43o6ooFq6HLMjBxmcDYOrJFRdcsKDWtI0Be/uLfc/rClXuyEbcENXfadg77HHv35BI85RNy4TKeai3hxoQIDAQAB;
82
+ ____________________________
83
+
84
+ ____________________________
85
+ DKIM record search for yahoo.com
86
+ - using selectors: ["default", "dkim", "google", "yahoo"]
87
+ - no DKIM record found for yahoo.com
88
+ ____________________________
89
+
90
+ ## Requirements
91
+
92
+ * [ruby] >= 1.9.1
93
+ * [parslet] ~> 1.6
94
+
95
+ ## Install
96
+
97
+ $ gem install dkim-query
98
+
99
+ ## License
100
+
101
+ See the {file:LICENSE.txt} file.
102
+
103
+ [DKIM]: https://tools.ietf.org/html/rfc6376
104
+ [ruby]: https://www.ruby-lang.org/
105
+ [parslet]: http://kschiess.github.io/parslet/
@@ -0,0 +1,24 @@
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 'rubygems/tasks'
14
+ Gem::Tasks.new
15
+
16
+ require 'rspec/core/rake_task'
17
+ RSpec::Core::RakeTask.new
18
+
19
+ task :test => :spec
20
+ task :default => :spec
21
+
22
+ require 'yard'
23
+ YARD::Rake::YardocTask.new
24
+ task :doc => :yard
@@ -0,0 +1,34 @@
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 'dkim/query'
7
+
8
+ unless ARGV[0]
9
+ warn "Please supply at least one host name"
10
+ exit
11
+ end
12
+
13
+ ARGV.each do |arg|
14
+ puts "____________________________\n"
15
+ puts "DKIM record search for #{arg}"
16
+
17
+ domain = DKIM::Query::Domain.query(arg)
18
+
19
+ unless domain.keys.empty?
20
+ puts "- found DKIM record for #{arg}"
21
+
22
+ domain.keys.each do |selector,key|
23
+ puts " #{selector}:"
24
+
25
+ [:v, :g, :h, :k, :n, :p, :s, :t].each do |field|
26
+ value = key.send(field)
27
+ puts " #{field}: #{value}" if value
28
+ end
29
+ end
30
+ else
31
+ puts "- no DKIM record found for #{arg}"
32
+ end
33
+ puts "____________________________\n\n"
34
+ end
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'dkim/query/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "dkim-query"
8
+ gem.version = DKIM::Query::VERSION
9
+ gem.authors = ["nicktitle"]
10
+ gem.email = ["nick.esposito@trailofbits.com"]
11
+ gem.summary = %q{DKIM Retriever and Parser}
12
+ gem.description = %q{Search and retrieve DKIM records for any number of hosts}
13
+ gem.homepage = "https://github.com/trailofbits/dkim-query#readme"
14
+ gem.license = "MIT"
15
+
16
+ gem.files = `git ls-files -z`.split("\x0")
17
+ gem.executables = ['dkim-query']
18
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
+ gem.require_paths = ["lib"]
20
+ gem.required_ruby_version = '>= 1.9.1'
21
+
22
+ gem.add_dependency "parslet", "~> 1.6"
23
+
24
+ gem.add_development_dependency "bundler", "~> 1.6"
25
+ gem.add_development_dependency "rake", "~> 10.0"
26
+ end
@@ -0,0 +1,141 @@
1
+ require_relative 'query'
2
+ require_relative 'key'
3
+
4
+ require 'resolv'
5
+
6
+ module DKIM
7
+ module Query
8
+ #
9
+ # Represents the DKIM keys of a domain.
10
+ #
11
+ class Domain
12
+
13
+ include Enumerable
14
+
15
+ # Name of the domain
16
+ #
17
+ # @return [String]
18
+ attr_reader :name
19
+
20
+ # DKIM Keys of the domain
21
+ #
22
+ # @return [Hash{String => Key}]
23
+ attr_reader :keys
24
+
25
+ #
26
+ # Initializes the domain.
27
+ #
28
+ # @param [String] name
29
+ # The domain name.
30
+ #
31
+ # @param [Hash{String => Key}] keys
32
+ # The DKIM Keys of the domain.
33
+ #
34
+ # @api public
35
+ #
36
+ def initialize(name,keys={})
37
+ @name = name
38
+ @keys = keys
39
+ end
40
+
41
+ #
42
+ # Parses the DKIM Keys.
43
+ #
44
+ # @param [String] domain
45
+ # The domain the keys belong to.
46
+ #
47
+ # @param [Hash{String => String}] keys
48
+ # The DKIM selectors and keys.
49
+ #
50
+ # @return [Domain]
51
+ # The domain and it's parsed DKIM keys.
52
+ #
53
+ # @api semipublic
54
+ #
55
+ def self.parse(domain,keys={})
56
+ keys = Hash[keys.map { |selector,record|
57
+ [selector, Key.parse(record)]
58
+ }]
59
+
60
+ return new(domain,keys)
61
+ end
62
+
63
+ #
64
+ # Parses the DKIM Keys.
65
+ #
66
+ # @param [String] domain
67
+ # The domain the keys belong to.
68
+ #
69
+ # @param [Hash{String => String}] keys
70
+ # The DKIM selectors and keys.
71
+ #
72
+ # @return [Domain]
73
+ # The domain and it's parsed DKIM keys.
74
+ #
75
+ # @raise [Parslet::ParseFailed]
76
+ # One of the keys was invalid.
77
+ #
78
+ # @api semipublic
79
+ #
80
+ def self.parse!(domain,keys={})
81
+ keys = Hash[keys.map { |selector,record|
82
+ [selector, Key.parse!(record)]
83
+ }]
84
+
85
+ return new(domain,keys)
86
+ end
87
+
88
+ #
89
+ # Queries the domain for all DKIM selectors.
90
+ #
91
+ # @param [String] domain
92
+ # The domain to query.
93
+ #
94
+ # @option options [Array<String>] :selectors
95
+ # sub-domain selectors.
96
+ #
97
+ # @option options [Resolv::DNS] :resolver
98
+ #
99
+ # @return [Domain]
100
+ # The domain and it's DKIM Keys.
101
+ #
102
+ # @api public
103
+ #
104
+ def self.query(domain,options={})
105
+ parse(domain,Query.query(domain,options))
106
+ end
107
+
108
+ #
109
+ # Enumerates over each individual key.
110
+ #
111
+ # @yield [key]
112
+ # The given block will be passed each key.
113
+ #
114
+ # @yieldparam [DKIM::Query::Key] key
115
+ # A key belonging to the domain.
116
+ #
117
+ # @return [Enumerator]
118
+ # If no block was given, an Enumerator will be returned.
119
+ #
120
+ # @api public
121
+ #
122
+ def each(&block)
123
+ @keys.each_value(&block)
124
+ end
125
+
126
+ #
127
+ # Selects a key from the domain.
128
+ #
129
+ # @param [String] selector
130
+ # The selector.
131
+ #
132
+ # @return [Key, nil]
133
+ # The key within that selector.
134
+ #
135
+ def [](selector)
136
+ @keys[selector]
137
+ end
138
+
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,8 @@
1
+ require 'parslet'
2
+
3
+ module DKIM
4
+ module Query
5
+ class InvalidKey < Parslet::ParseFailed
6
+ end
7
+ end
8
+ end