dkimverify 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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