Browse Source

Move checks in children again

new-scoring
aeris 2 years ago
parent
commit
c64c154b50

+ 1
- 1
lib/cryptcheck.rb View File

@@ -4,7 +4,7 @@ require 'timeout'
4 4
 require 'yaml'
5 5
 
6 6
 module CryptCheck
7
-	MAX_ANALYSIS_DURATION = 120
7
+	MAX_ANALYSIS_DURATION = 600
8 8
 	PARALLEL_ANALYSIS     = 10
9 9
 
10 10
 	class AnalysisFailure

+ 9
- 3
lib/cryptcheck/tls/cert.rb View File

@@ -109,9 +109,15 @@ module CryptCheck
109 109
 
110 110
 			include ::CryptCheck::State
111 111
 
112
-			CHECKS = [:weak_sign, -> (s) do
113
-				not (SIGNATURE_ALGORITHMS_X509[s.signature_algorithm] & WEAK_SIGN).empty?
114
-			end, :critical].freeze
112
+			CHECKS = WEAK_SIGN.collect do |level, hashes|
113
+				hashes.collect do |hash|
114
+					["#{hash}_sign".to_sym, -> (s) { s.send "#{hash}?" }, level]
115
+				end
116
+			end.flatten(1).freeze
117
+
118
+			def checks
119
+				CHECKS
120
+			end
115 121
 
116 122
 			def children
117 123
 				[self.key]

+ 45
- 58
lib/cryptcheck/tls/cipher.rb View File

@@ -36,11 +36,10 @@ module CryptCheck
36 36
 					ccm:       %w(CCM)
37 37
 			}
38 38
 
39
-			attr_reader :method, :name, :states, :status
39
+			attr_reader :method, :name
40 40
 
41 41
 			def initialize(method, name)
42 42
 				@method, @name = method, name
43
-				fetch_states
44 43
 			end
45 44
 
46 45
 			extend Enumerable
@@ -102,70 +101,33 @@ module CryptCheck
102 101
 				size <= 64
103 102
 			end
104 103
 
105
-			CHECKS = [
106
-					[:psk, Proc.new { |s| s.psk? }, :critical],
107
-					[:srp, Proc.new { |s| s.srp? }, :critical],
108
-					[:dss, Proc.new { |s| s.dss? }, :critical],
109
-					[:anonymous, Proc.new { |s| s.anonymous? }, :critical],
110
-					[:null, Proc.new { |s| s.null? }, :critical],
111
-					[:export, Proc.new { |s| s.export? }, :critical],
112
-					[:des, Proc.new { |s| s.des? }, :critical],
113
-					[:md5, Proc.new { |s| s.md5? }, :critical],
114
-
115
-					[:rc4, Proc.new { |s| s.rc4? }, :error],
116
-					[:sweet32, Proc.new { |s| s.sweet32? }, :error],
117
-
118
-					#[:cbc, Proc.new { |s| s.cbc? }, :warning],
119
-					[:dhe, Proc.new { |s| s.dhe? }, :warning],
120
-					[:no_pfs, Proc.new { |s| not s.pfs? }, :warning],
121
-
122
-					[:pfs, Proc.new { |s| s.pfs? }, :good],
123
-					[:ecdhe, Proc.new { |s| s.ecdhe? }, :good],
124
-					[:aead, Proc.new { |s| s.aead? }, :good],
125
-			]
126
-
127
-			def fetch_states
128
-				@states = Status.collect { |s| [s, []] }.to_h
129
-				CHECKS.each do |name, check, status|
130
-					result = check.call self
131
-					@states[status ? status : result] << name if result
132
-				end
133
-				statuses = @states.reject { |_, v| v.empty? }.keys
134
-				@status  = Status[statuses]
135
-			end
136
-
137 104
 			def to_s(type = :long)
138 105
 				case type
139 106
 					when :long
140
-						states = @states.collect { |k, vs| vs.collect { |v| v.to_s.colorize k } }.flatten.join ' '
141
-						"#{@method} #{@name.colorize @status} [#{states}]"
107
+						states = self.states.collect { |k, vs| vs.collect { |v| v.to_s.colorize k } }.flatten.join ' '
108
+						"#{@method} #{@name.colorize self.status} [#{states}]"
142 109
 					when :short
143
-						@name.colorize @status
110
+						@name.colorize self.status
144 111
 				end
145 112
 			end
146 113
 
147
-			PRIORITY = { good: 1, none: 2, warning: 3, error: 4, critical: 5 }
148
-
149
-			def self.sort(ciphers)
150
-				ciphers.sort do |a, b|
151
-					error_a, error_b = PRIORITY[a.score], PRIORITY[b.score]
152
-					compare          = error_a <=> error_b
153
-					next compare unless compare == 0
114
+			def <=>(other)
115
+				compare = State.compare self, other
116
+				return compare unless compare == 0
154 117
 
155
-					size_a, size_b = a.size, b.size
156
-					compare        = size_b <=> size_a
157
-					next compare unless compare == 0
118
+				size_a, size_b = a.size, b.size
119
+				compare        = size_b <=> size_a
120
+				return compare unless compare == 0
158 121
 
159
-					dh_a, dh_b = a.dh, b.dh
160
-					next -1 if not dh_a and dh_b
161
-					next 1 if dh_a and not dh_b
162
-					next a.name <=> b.name if not dh_a and not dh_b
122
+				dh_a, dh_b = a.dh, b.dh
123
+				return -1 if not dh_a and dh_b
124
+				return 1 if dh_a and not dh_b
125
+				return a.name <=> b.name if not dh_a and not dh_b
163 126
 
164
-					compare = b.dh.size <=> a.dh.size
165
-					next compare unless compare == 0
127
+				compare = b.dh.size <=> a.dh.size
128
+				return compare unless compare == 0
166 129
 
167
-					a.name <=> b.name
168
-				end
130
+				a.name <=> b.name
169 131
 			end
170 132
 
171 133
 			def self.list(cipher_suite = 'ALL:COMPLEMENTOFALL', method: :TLSv1_2)
@@ -265,8 +227,33 @@ module CryptCheck
265 227
 				end
266 228
 			end
267 229
 
230
+			include State
231
+
232
+			CHECKS = [
233
+					[:dss, -> (c) { c.dss? }, :critical],
234
+					[:anonymous, -> (c) { c.anonymous? }, :critical],
235
+					[:null, -> (c) { c.null? }, :critical],
236
+					[:export, -> (c) { c.export? }, :critical],
237
+					[:des, -> (c) { c.des? }, :critical],
238
+					[:md5, -> (c) { c.md5? }, :critical],
239
+
240
+					[:rc4, -> (c) { c.rc4? }, :error],
241
+					[:sweet32, -> (c) { c.sweet32? }, :error],
242
+
243
+					[:no_pfs, -> (c) { not c.pfs? }, :warning],
244
+					[:pfs, -> (c) { c.pfs? }, :good],
245
+					[:dhe, -> (c) { c.dhe? }, :warning],
246
+					[:ecdhe, -> (c) { c.ecdhe? }, :good],
247
+
248
+					[:aead, -> (c) { c.aead? }, :good]
249
+			].freeze
250
+
251
+			def checks
252
+				CHECKS
253
+			end
254
+
268 255
 			def <=>(other)
269
-				status = Status.compare self, other
256
+				status = State.compare self, other
270 257
 				return status if status != 0
271 258
 				@name <=> other.name
272 259
 			end
@@ -275,8 +262,8 @@ module CryptCheck
275 262
 			SUPPORTED = Method.collect do |m|
276 263
 				context         = ::OpenSSL::SSL::SSLContext.new m.to_sym
277 264
 				context.ciphers = ALL
278
-
279
-				[m, context.ciphers.collect { |c| Cipher.new m, c.first }.sort ]
265
+				ciphers         = context.ciphers.collect { |c| Cipher.new m, c.first }
266
+				[m, ciphers.sort]
280 267
 			end.to_h.freeze
281 268
 		end
282 269
 	end

+ 0
- 2
lib/cryptcheck/tls/fixture.rb View File

@@ -114,8 +114,6 @@ class ::OpenSSL::PKey::DH
114 114
 						:critical
115 115
 					when 1024...2048
116 116
 						:error
117
-					else
118
-						:warning
119 117
 				end
120 118
 			end]
121 119
 	].freeze

+ 44
- 13
lib/cryptcheck/tls/grade.rb View File

@@ -1,12 +1,12 @@
1 1
 module CryptCheck
2 2
 	module Tls
3 3
 		class Grade
4
-			attr_reader :server, :grade, :states
4
+			attr_reader :server, :grade, :status
5 5
 
6 6
 			def initialize(server)
7 7
 				@server = server
8
+				@status = @server.status
8 9
 				@checks = checks
9
-				@states = calculate_states
10 10
 				@grade  = calculate_grade
11 11
 			end
12 12
 
@@ -30,39 +30,70 @@ module CryptCheck
30 30
 
31 31
 				Logger.info { "Grade : #{self.grade.colorize color }" }
32 32
 				Logger.info { '' }
33
-				Status.each do |color|
34
-					states = @states[color]
33
+				State.each do |color|
34
+					states = @status[color]
35 35
 					Logger.info { "#{color.to_s.capitalize} : #{states.collect { |s| s.to_s.colorize color }.join ' '}" } unless states.empty?
36 36
 				end
37 37
 			end
38 38
 
39 39
 			private
40
+			CHECKS = {
41
+					critical: %i(
42
+						mdc2_sign md2_sign md4_sign md5_sign sha_sign sha1_sign
43
+						weak_key
44
+						weak_dh
45
+						sslv2 sslv3
46
+					),
47
+					error:    %i(
48
+						weak_key
49
+						weak_dh
50
+					),
51
+					warning:  %i(
52
+						weak_key
53
+						weak_dh
54
+						dhe
55
+					),
56
+					good:     %i(
57
+						tls12
58
+					),
59
+					perfect:  %i(
60
+						tls12_only
61
+					),
62
+					best:     %i(
63
+
64
+							  )
65
+			}.freeze
66
+
67
+			def checks
68
+
69
+			end
70
+
40 71
 			def calculate_grade
41 72
 				case
42
-					when !@states[:critical].empty?
73
+					when !@status[:critical].empty?
43 74
 						return 'G'
44
-					when !@states[:error].empty?
75
+					when !@status[:error].empty?
45 76
 						return 'F'
46
-					when !@states[:warning].empty?
77
+					when !@status[:warning].empty?
47 78
 						return 'E'
48 79
 				end
49 80
 
50 81
 				goods = @checks.select { |c| c.last == :good }.collect &:first
51 82
 				unless goods.empty?
52
-					return 'D' if @states[:good].empty?
53
-					return 'C' if @states[:good] != goods
83
+					return 'D' if @status[:good].empty?
84
+					return 'C' if @status[:good] != goods
54 85
 				end
55 86
 
56 87
 				perfects = @checks.select { |c| c.last == :perfect }.collect &:first
57 88
 				unless perfects.empty?
58
-					return 'C+' if @states[:perfect].empty?
59
-					return 'B' if @states[:perfect] != perfects
89
+					return 'C+' if @status[:perfect].empty?
90
+					return 'B' if @status[:perfect] != perfects
60 91
 				end
61 92
 
62 93
 				bests = @checks.select { |c| c.last == :best }.collect &:first
63 94
 				unless bests.empty?
64
-					return 'B+' if @states[:best].empty?
65
-					return 'A' if @states[:best] != bests
95
+					return 'B+' if @status[:best].empty?
96
+					return 'A' if @status[:best] != bests
66 97
 				end
67 98
 
68 99
 				'A+'

+ 0
- 8
lib/cryptcheck/tls/https/grade.rb View File

@@ -2,14 +2,6 @@ module CryptCheck
2 2
 	module Tls
3 3
 		module Https
4 4
 			class Grade < Tls::Grade
5
-				def checks
6
-					super + [
7
-						[:hsts, Proc.new { |s| s.hsts? }, :good],
8
-						[:hsts_long, Proc.new { |s| s.hsts_long? }, :perfect],
9
-
10
-						#[:must_staple, Proc.new { |s| s.must_staple? }, :best],
11
-					]
12
-				end
13 5
 			end
14 6
 		end
15 7
 	end

+ 11
- 7
lib/cryptcheck/tls/method.rb View File

@@ -33,13 +33,17 @@ module CryptCheck
33 33
 				EXISTING.find_index(self) <=> EXISTING.find_index(other)
34 34
 			end
35 35
 
36
-			# def eql?(other)
37
-			# 	self.to_sym.eql? other.to_sym
38
-			# end
39
-			#
40
-			# def equal?(other)
41
-			# 	self.to_sym.equal? other.to_sym
42
-			# end
36
+			include State
37
+
38
+			CHECKS = [
39
+					[:sslv2, -> (s) { s == :SSLv2 }, :critical],
40
+					[:sslv3, -> (s) { s == :SSLv3 }, :critical],
41
+					[:tlsv1_2, -> (s) { s == :TLSv1_2 }, :good]
42
+			]
43
+
44
+			def checks
45
+				CHECKS
46
+			end
43 47
 		end
44 48
 	end
45 49
 end

+ 2
- 40
lib/cryptcheck/tls/server.rb View File

@@ -33,34 +33,18 @@ module CryptCheck
33 33
 				tlsv1_2? and not ssl? and not tlsv1? and not tlsv1_1?
34 34
 			end
35 35
 
36
-			def pfs?
37
-				uniq_supported_ciphers.any? { |c| c.pfs? }
38
-			end
39
-
40 36
 			def pfs_only?
41 37
 				uniq_supported_ciphers.all? { |c| c.pfs? }
42 38
 			end
43 39
 
44
-			def ecdhe?
45
-				uniq_supported_ciphers.any? { |c| c.ecdhe? }
46
-			end
47
-
48 40
 			def ecdhe_only?
49 41
 				uniq_supported_ciphers.all? { |c| c.ecdhe? }
50 42
 			end
51 43
 
52
-			def aead?
53
-				uniq_supported_ciphers.any? { |c| c.aead? }
54
-			end
55
-
56 44
 			def aead_only?
57 45
 				uniq_supported_ciphers.all? { |c| c.aead? }
58 46
 			end
59 47
 
60
-			def sweet32?
61
-				uniq_supported_ciphers.any? { |c| c.sweet32? }
62
-			end
63
-
64 48
 			def fallback_scsv?
65 49
 				@fallback_scsv
66 50
 			end
@@ -72,31 +56,9 @@ module CryptCheck
72 56
 			include State
73 57
 
74 58
 			CHECKS = [
75
-					# Protocols
76
-					[:ssl, -> (s) { s.ssl? }, :critical],
77
-					[:tls12, -> (s) { s.tlsv1_2? }, :good],
78
-					[:tls12_only, -> (s) { s.tlsv1_2_only? }, :perfect],
79
-
80
-					# Ciphers
81
-					[:dss, -> (s) { s.dss? }, :critical],
82
-					[:anonymous, -> (s) { s.anonymous? }, :critical],
83
-					[:null, -> (s) { s.null? }, :critical],
84
-					[:export, -> (s) { s.export? }, :critical],
85
-					[:des, -> (s) { s.des? }, :critical],
86
-					[:md5, -> (s) { s.md5? }, :critical],
87
-
88
-					[:rc4, -> (s) { s.rc4? }, :error],
89
-					[:sweet32, -> (s) { s.sweet32? }, :error],
90
-
91
-					[:no_pfs, -> (s) { not s.pfs_only? }, :warning],
92
-					[:pfs, -> (s) { s.pfs? }, :good],
59
+					[:tlsv1_2_only, -> (s) { s.tlsv1_2_only? }, :perfect],
93 60
 					[:pfs_only, -> (s) { s.pfs_only? }, :perfect],
94
-
95
-					[:no_ecdhe, -> (s) { not s.ecdhe? }, :warning],
96
-					[:ecdhe, -> (s) { s.ecdhe? }, :good],
97 61
 					[:ecdhe_only, -> (s) { s.ecdhe_only? }, :perfect],
98
-
99
-					[:aead, -> (s) { s.aead? }, :good],
100 62
 					#[:aead_only, -> (s) { s.aead_only? }, :best],
101 63
 			].freeze
102 64
 
@@ -112,7 +74,7 @@ module CryptCheck
112 74
 			end
113 75
 
114 76
 			def children
115
-				@certs + @dh
77
+				@certs + @dh + @supported_methods + uniq_supported_ciphers
116 78
 			end
117 79
 
118 80
 			include Engine

Loading…
Cancel
Save