ruby-sslyze 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/.document +3 -0
  3. data/.gitignore +4 -0
  4. data/.rspec +1 -0
  5. data/.travis.yml +19 -0
  6. data/.yardopts +1 -0
  7. data/ChangeLog.md +8 -0
  8. data/Gemfile +18 -0
  9. data/LICENSE.txt +20 -0
  10. data/README.md +70 -0
  11. data/Rakefile +23 -0
  12. data/lib/sslyze.rb +3 -0
  13. data/lib/sslyze/cert_info.rb +55 -0
  14. data/lib/sslyze/certificate.rb +139 -0
  15. data/lib/sslyze/certificate/domain_name.rb +77 -0
  16. data/lib/sslyze/certificate/extensions.rb +127 -0
  17. data/lib/sslyze/certificate/extensions/authority_information_access.rb +38 -0
  18. data/lib/sslyze/certificate/extensions/extension.rb +26 -0
  19. data/lib/sslyze/certificate/extensions/x509v3_basic_constraints.rb +60 -0
  20. data/lib/sslyze/certificate/extensions/x509v3_certificate_policies.rb +50 -0
  21. data/lib/sslyze/certificate/extensions/x509v3_crl_distribution_points.rb +32 -0
  22. data/lib/sslyze/certificate/extensions/x509v3_extended_key_usage.rb +32 -0
  23. data/lib/sslyze/certificate/extensions/x509v3_key_usage.rb +50 -0
  24. data/lib/sslyze/certificate/extensions/x509v3_subject_alternative_name.rb +71 -0
  25. data/lib/sslyze/certificate/issuer.rb +56 -0
  26. data/lib/sslyze/certificate/public_key.rb +9 -0
  27. data/lib/sslyze/certificate/subject.rb +117 -0
  28. data/lib/sslyze/certificate/subject_public_key_info.rb +53 -0
  29. data/lib/sslyze/certificate/validity.rb +9 -0
  30. data/lib/sslyze/certificate_chain.rb +89 -0
  31. data/lib/sslyze/certificate_validation.rb +44 -0
  32. data/lib/sslyze/cipher_suite.rb +237 -0
  33. data/lib/sslyze/key_exchange.rb +106 -0
  34. data/lib/sslyze/ocsp_response.rb +87 -0
  35. data/lib/sslyze/program.rb +66 -0
  36. data/lib/sslyze/protocol.rb +133 -0
  37. data/lib/sslyze/target.rb +295 -0
  38. data/lib/sslyze/task.rb +65 -0
  39. data/lib/sslyze/types.rb +17 -0
  40. data/lib/sslyze/version.rb +4 -0
  41. data/lib/sslyze/xml.rb +139 -0
  42. data/ruby-sslyze.gemspec +24 -0
  43. data/spec/cert_info_spec.rb +29 -0
  44. data/spec/certificate/subject_name_spec.rb +72 -0
  45. data/spec/certificate_chain_spec.rb +61 -0
  46. data/spec/certificate_spec.rb +330 -0
  47. data/spec/certificate_validation_spec.rb +27 -0
  48. data/spec/cipher_suite_spec.rb +50 -0
  49. data/spec/issuer_spec.rb +33 -0
  50. data/spec/key_exchange_spec.rb +97 -0
  51. data/spec/ocsp_response_spec.rb +59 -0
  52. data/spec/protocol_spec.rb +99 -0
  53. data/spec/spec_helper.rb +9 -0
  54. data/spec/sslyze.xml +2798 -0
  55. data/spec/sslyze_spec.rb +8 -0
  56. data/spec/subject_public_key_info_spec.rb +35 -0
  57. data/spec/subject_spec.rb +67 -0
  58. data/spec/target_spec.rb +176 -0
  59. data/spec/xml_examples.rb +9 -0
  60. data/spec/xml_spec.rb +72 -0
  61. metadata +162 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c4013d128b21d94004ca8c15715b85531acfe46f
4
+ data.tar.gz: bfcbc3a8309309dbc5e03986f153fdd1792174a3
5
+ SHA512:
6
+ metadata.gz: ce2fd295c02224d87157bedfec3cf4d63f4b0d9f9558a12fa00063c104c3eef986bfae25c2ec1378136a17db1fb4ff24589a0ad902df1591e80b95559a134662
7
+ data.tar.gz: 9d5cf5e4dca31f544e6cae4cdad4a7b09ba4a2c80350bdac8094e793f2626622d30c42489ae6baec63749ab7729ba66b11af36fa079a95b633b117425b21092f
data/.document ADDED
@@ -0,0 +1,3 @@
1
+ -
2
+ ChangeLog.md
3
+ LICENSE.txt
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ Gemfile.lock
2
+ doc/
3
+ pkg/
4
+ vendor/cache/*.gem
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour --format documentation
data/.travis.yml ADDED
@@ -0,0 +1,19 @@
1
+ language: ruby
2
+ sudo: false
3
+ rvm:
4
+ - 1.9.3
5
+ - 2.0
6
+ - 2.1
7
+ - ruby-head
8
+ - jruby-19mode
9
+ - jruby-head
10
+ - rbx-2
11
+ matrix:
12
+ allow_failures:
13
+ - rvm: rbx-2
14
+ addons:
15
+ code_climate:
16
+ repo_token: 2a03fa37ce5a5cb21bb117a736be5d83dcf9f1c3ea2b248f7af4c0a7b330d8c8
17
+ notifications:
18
+ slack:
19
+ secure: IfKhtia5nM6KA9nK8jiSkNnVOLN96er6gK5jgjYKFNrVyWAKRUJZ0TB9L+igjUWDq7t+tRvj8yGT2k61xVJgF+ZDlQiWvyazTsgQeqbjieCxCrj/BTGZLyD1hhOLg7vqpyeQvp/34hDahx6XNp6XPvkxeofjc0H6STv2UjJkpQk=
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --markup markdown --title "ruby-sslyze Documentation" --protected
data/ChangeLog.md ADDED
@@ -0,0 +1,8 @@
1
+ ### 0.1.0 / 2015-10-13
2
+
3
+ * Initial release:
4
+ * Provides a Ruby interface to `sslyze.py`.
5
+ * Provides a Parser for consuming the sslyze XML output.
6
+ * [sslyze] >= 0.12
7
+
8
+ [sslyze]: https://github.com/nabla-c0d3/sslyze#readme
data/Gemfile ADDED
@@ -0,0 +1,18 @@
1
+ source 'https://rubygems.org/'
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'rake'
7
+ gem 'rubygems-tasks', '~> 0.2'
8
+
9
+ gem 'rspec', '~> 3.0'
10
+
11
+ gem 'yard', '~> 0.8'
12
+ gem 'kramdown'
13
+ end
14
+
15
+ group :test do
16
+ gem 'json'
17
+ gem 'codeclimate-test-reporter', require: nil
18
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2014-2015 Hal Brodigan
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,70 @@
1
+ # ruby-sslyze
2
+
3
+ [![Code Climate](https://codeclimate.com/github/trailofbits/ruby-sslyze/badges/gpa.svg)](https://codeclimate.com/github/trailofbits/ruby-sslyze)
4
+ [![Test Coverage](https://codeclimate.com/github/trailofbits/ruby-sslyze/badges/coverage.svg)](https://codeclimate.com/github/trailofbits/ruby-sslyze)
5
+ [![Build Status](https://travis-ci.org/trailofbits/ruby-sslyze.svg)](https://travis-ci.org/trailofbits/ruby-sslyze)
6
+
7
+ * [Homepage](https://github.com/trailofbits/ruby-sslyze#readme)
8
+ * [Issues](https://github.com/trailofbits/ruby-sslyze/issues)
9
+ * [Documentation](http://rubydoc.info/gems/ruby-sslyze/frames)
10
+ * [Email](mailto:hal at trailofbits.com)
11
+
12
+ ## Description
13
+
14
+ A Ruby interface to [sslyze] python utility.
15
+
16
+ ## Features
17
+
18
+ * Provides a Ruby interface to `sslyze.py`.
19
+ * Provides a Parser for consuming the sslyze XML output.
20
+ * [sslyze] >= 0.12
21
+
22
+ ## Examples
23
+
24
+ Analyze a domain:
25
+
26
+ require 'sslyze'
27
+
28
+ SSLyze::Program.analyze(targets: 'twitter.com', regular: true, timeout: 5)
29
+
30
+ Analyze multiple domains:
31
+
32
+ SSLyze::Program.analyze(
33
+ targets: ['twitter.com', 'github.com'],
34
+ regular: true,
35
+ timeout: 5
36
+ )
37
+
38
+ Output to XML:
39
+
40
+ SSLyze::Program.analyze(
41
+ targets: 'twitter.com',
42
+ regular: true,
43
+ timeout: 5,
44
+ xml_out: 'path/to/xml'
45
+ )
46
+
47
+ Parsing sslyze XML output:
48
+
49
+ xml = SSLyze::XML.open('path/to/xml')
50
+
51
+ ## Requirements
52
+
53
+ * [rprogram] ~> 0.3
54
+ * [nokogiri] ~> 1.0
55
+ * [sslyze] >= 0.12
56
+
57
+ ## Install
58
+
59
+ $ gem install ruby-sslyze
60
+
61
+ ## Copyright
62
+
63
+ Copyright (c) 2014 Hal Brodigan
64
+
65
+ See {file:LICENSE.txt} for details.
66
+
67
+ [sslyze]: https://github.com/nabla-c0d3/sslyze#readme
68
+
69
+ [rpgoram]: https://github.com/postmodern/rprogram#readme
70
+ [nokogiri]: http://www.nokogiri.org/
data/Rakefile ADDED
@@ -0,0 +1,23 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError => e
4
+ abort e.message
5
+ end
6
+
7
+ require 'rake'
8
+ require 'rubygems/tasks'
9
+ Gem::Tasks.new
10
+
11
+ require 'rspec/core/rake_task'
12
+ RSpec::Core::RakeTask.new
13
+
14
+ task :test => :spec
15
+ task :default => :spec
16
+
17
+ require 'yard'
18
+ YARD::Rake::YardocTask.new
19
+ task :doc => :yard
20
+
21
+ file 'spec/sslyze.xml' do
22
+ sh 'sslyze.py --xml_out spec/sslyze.xml --regular --timeout 5 twitter.com github.com:443 yahoo.com:443'
23
+ end
data/lib/sslyze.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'sslyze/program'
2
+ require 'sslyze/xml'
3
+ require 'sslyze/version'
@@ -0,0 +1,55 @@
1
+ require 'sslyze/certificate_chain'
2
+ require 'sslyze/certificate_validation'
3
+ require 'sslyze/ocsp_response'
4
+
5
+ module SSLyze
6
+ #
7
+ # Represents the `<certinfo>` element.
8
+ #
9
+ class CertInfo
10
+
11
+ #
12
+ # Initializes the cert info.
13
+ #
14
+ # @param [Nokogiri::XML::Node] node
15
+ # The `<certinfo>` element.
16
+ #
17
+ def initialize(node)
18
+ @node = node
19
+ end
20
+
21
+ #
22
+ # Certificate chain.
23
+ #
24
+ # @return [CertificateChain, nil]
25
+ #
26
+ def chain
27
+ @chain ||= if (cert_chain = @node.at('certificateChain'))
28
+ CertificateChain.new(cert_chain)
29
+ end
30
+ end
31
+
32
+ #
33
+ # Certificate validation information.
34
+ #
35
+ # @return [CertificateValidation]
36
+ #
37
+ def validation
38
+ @validation ||= CertificateValidation.new(@node.at('certificateValidation'))
39
+ end
40
+
41
+ #
42
+ # OCSP response stapling information.
43
+ #
44
+ # @return [OCSPResponse, nil]
45
+ #
46
+ def ocsp_response
47
+ @ocsp_response ||= if (ocsp_response = @node.at('ocspStapling/ocspResponse'))
48
+ OCSPResponse.new(ocsp_response)
49
+ end
50
+ end
51
+
52
+ alias ocsp_stapling ocsp_response
53
+
54
+ end
55
+ end
@@ -0,0 +1,139 @@
1
+ require 'sslyze/certificate/subject_public_key_info'
2
+ require 'sslyze/certificate/extensions'
3
+ require 'sslyze/certificate/subject'
4
+ require 'sslyze/certificate/validity'
5
+ require 'sslyze/certificate/issuer'
6
+
7
+ require 'date'
8
+
9
+ module SSLyze
10
+ #
11
+ # Represents the `<certificate>` XML element.
12
+ #
13
+ class Certificate
14
+
15
+ #
16
+ # Initializes the certificate.
17
+ #
18
+ # @param [Nokogiri::XML::Node] node
19
+ # The `<certificate>` XML element.
20
+ #
21
+ def initialize(node)
22
+ @node = node
23
+ end
24
+
25
+ #
26
+ # The position of the certificate within the cert chain.
27
+ #
28
+ # @return [:leaf, :intermediate]
29
+ #
30
+ def position
31
+ @position ||= @node['position'].to_sym
32
+ end
33
+
34
+ #
35
+ # The SHA1 fingerprint of the cert.
36
+ #
37
+ # @return [String]
38
+ #
39
+ def sha1_fingerprint
40
+ @sha1_fingerprint ||= @node['sha1Fingerprint']
41
+ end
42
+
43
+ #
44
+ # The AS PEM information.
45
+ #
46
+ # @return [String]
47
+ #
48
+ def as_pem
49
+ @as_pem ||= @node.at('asPEM').inner_text
50
+ end
51
+
52
+ #
53
+ # The subject public key information.
54
+ #
55
+ # @return [SubjectPublicKeyInfo]
56
+ #
57
+ def subject_public_key_info
58
+ @subject_public_key_info ||= SubjectPublicKeyInfo.new(
59
+ @node.at('subjectPublicKeyInfo')
60
+ )
61
+ end
62
+
63
+ #
64
+ # The certificate SSL version.
65
+ #
66
+ # @return [Integer]
67
+ #
68
+ def version
69
+ @version ||= @node.at('version').inner_text.to_i
70
+ end
71
+
72
+ #
73
+ # The SSL extensions.
74
+ #
75
+ # @return [Extensions]
76
+ #
77
+ def extensions
78
+ @extensions ||= Extensions.new(@node.at('extensions'))
79
+ end
80
+
81
+ #
82
+ # The certificate signature.
83
+ #
84
+ # @return [String]
85
+ #
86
+ def signature_value
87
+ @signature_value ||= @node.at('signatureValue').inner_text
88
+ end
89
+
90
+ #
91
+ # The certificate signature algorithm.
92
+ #
93
+ # @return [String]
94
+ #
95
+ def signature_algorithm
96
+ @signature_algorithm ||= @node.at('signatureAlgorithm').inner_text
97
+ end
98
+
99
+ #
100
+ # The certificate serial number.
101
+ #
102
+ # @return [String]
103
+ #
104
+ def serial_number
105
+ @serial_number ||= @node.at('serialNumber').inner_text
106
+ end
107
+
108
+ #
109
+ # The certificate subject information.
110
+ #
111
+ # @return [Subject]
112
+ #
113
+ def subject
114
+ @subject ||= Subject.new(@node.at('subject'))
115
+ end
116
+
117
+ #
118
+ # The certificate validity.
119
+ #
120
+ # @return [Validity]
121
+ #
122
+ def validity
123
+ @validity ||= Validity.new(
124
+ Date.parse(@node.at('validity/notAfter').inner_text),
125
+ Date.parse(@node.at('validity/notBefore').inner_text)
126
+ )
127
+ end
128
+
129
+ #
130
+ # The certificate issuer.
131
+ #
132
+ # @return [Issuer]
133
+ #
134
+ def issuer
135
+ @issuer ||= Issuer.new(@node.at('issuer'))
136
+ end
137
+
138
+ end
139
+ end
@@ -0,0 +1,77 @@
1
+ module SSLyze
2
+ class Certificate
3
+ #
4
+ # Represents a domain name pattern.
5
+ #
6
+ class DomainName
7
+
8
+ # The subject name.
9
+ #
10
+ # @return [String]
11
+ attr_reader :name
12
+
13
+ # The domain part of the subject name.
14
+ #
15
+ # @return [String]
16
+ attr_reader :domain
17
+
18
+ # The literal suffix of the subject name.
19
+ #
20
+ # @return [String]
21
+ attr_reader :suffix
22
+
23
+ #
24
+ # Initializes the subject name.
25
+ #
26
+ # @param [String] name
27
+ # The subject name.
28
+ #
29
+ def initialize(name)
30
+ @name = name
31
+
32
+ if @name.start_with?('*.')
33
+ @suffix = @name[1..-1]
34
+ @domain = @name[2..-1]
35
+ else
36
+ @domain = @name
37
+ end
38
+ end
39
+
40
+ #
41
+ # Compares two subject names.
42
+ #
43
+ # @return [Boolean]
44
+ #
45
+ def ==(other)
46
+ @name == other.name
47
+ end
48
+
49
+ #
50
+ # Tests whether the domain is matched by the subject name.
51
+ #
52
+ def include?(domain)
53
+ if @name.start_with?('*.') # wildcard
54
+ domain.end_with?(@suffix) || # does the domain share the suffix
55
+ domain == @domain # does the domain match the suffix
56
+ else # exact match
57
+ domain == @name
58
+ end
59
+ end
60
+
61
+ alias === include?
62
+
63
+ alias to_s name
64
+ alias to_str name
65
+
66
+ #
67
+ # Inspects the subject name.
68
+ #
69
+ # @return [String]
70
+ #
71
+ def inspect
72
+ "#<#{self.class}: #{self}>"
73
+ end
74
+
75
+ end
76
+ end
77
+ end