You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

122 lines
3.6KB

  1. module CryptCheck
  2. module Tls
  3. class TlsNotSupportedGrade
  4. attr_reader :server, :score, :grade
  5. def initialize(server)
  6. @server, @score, @grade = server, -1, 'X'
  7. end
  8. end
  9. class Grade
  10. attr_reader :server, :protocol_score, :key_exchange_score, :cipher_strengths_score, :score, :grade, :error, :danger, :warning, :success
  11. def initialize(server)
  12. @server = server
  13. calculate_protocol_score
  14. calculate_key_exchange_score
  15. calculate_cipher_strengths_score
  16. @score = @protocol_score*0.3 + @key_exchange_score*0.3 + @cipher_strengths_score*0.4
  17. calculate_states
  18. calculate_grade
  19. end
  20. def display
  21. color = case self.grade
  22. when 'A+' then :blue
  23. when 'A' then :green
  24. when 'B', 'C' then :yellow
  25. when 'E', 'F' then :red
  26. when 'M', 'T' then { color: :white, background: :red }
  27. end
  28. Logger.info { "Grade : #{self.grade.colorize color }" }
  29. Logger.info { '' }
  30. Logger.info { "Protocole : #{self.protocol_score} / 100" }
  31. Logger.info { "Key exchange : #{self.key_exchange_score} / 100" }
  32. Logger.info { "Ciphers strength : #{self.cipher_strengths_score} / 100" }
  33. Logger.info { "Overall score : #{self.score} / 100" }
  34. Logger.info { '' }
  35. Logger.info { "Errors : #{self.error.join(' ').colorize :red }" } unless self.error.empty?
  36. Logger.info { "Warnings : #{self.warning.join(' ').colorize :yellow }" } unless self.warning.empty?
  37. Logger.info { "Best practices : #{self.success.join(' ').colorize :green }" } unless self.success.empty?
  38. end
  39. private
  40. def calculate_grade
  41. @grade = case @score
  42. when 0...20 then 'F'
  43. when 20...35 then 'E'
  44. when 35...50 then 'D'
  45. when 50...65 then 'C'
  46. when 65...80 then 'B'
  47. else 'A'
  48. end
  49. @grade = [@grade, 'B'].max if !@server.tlsv1_2? or @server.key_size < 2048
  50. @grade = [@grade, 'C'].max if @server.des3?
  51. @grade = [@grade, 'F'].max unless @error.empty?
  52. @grade = 'M' unless @server.cert_valid
  53. @grade = 'T' unless @server.cert_trusted
  54. @grade = 'A+' if @grade == 'A' and @error.empty? and @warning.empty? and (all_success & @success) == all_success
  55. end
  56. def calculate_states
  57. ok = Proc.new { |n| @server.send "#{n}?" }
  58. state = {
  59. success: %i().select { |n| ok.call n },
  60. warning: %i(sha1_sig).select { |n| ok.call n },
  61. danger: %i(des3).select { |n| ok.call n },
  62. error: %i(md5_sig md5 sslv2 sslv3 anonymous dss null export des rc4).select { |n| ok.call n }
  63. }
  64. state[:success] << :pfs if @server.pfs_only?
  65. @success, @warning, @danger, @error = state[:success], state[:warning], state[:danger], state[:error]
  66. end
  67. ALL_ERROR = %i(md5_sig md5 anonymous dss null export des rc4)
  68. def all_error
  69. ALL_ERROR
  70. end
  71. ALL_WARNING = %i(sha1_sig des3)
  72. def all_warning
  73. ALL_WARNING
  74. end
  75. ALL_SUCCESS = %i(pfs)
  76. def all_success
  77. ALL_SUCCESS
  78. end
  79. METHODS_SCORES = { SSLv2: 0, SSLv3: 20, TLSv1: 60, TLSv1_1: 80, TLSv1_2: 100 }
  80. def calculate_protocol_score
  81. @protocol_score = @server.supported_protocols.collect { |p| METHODS_SCORES[p] }.min
  82. end
  83. def calculate_key_exchange_score
  84. @key_exchange_score = case @server.key_size
  85. when 0 then 0
  86. when 0...512 then 10
  87. when 512...1024 then 20
  88. when 1024...3072 then 50
  89. when 3072...4096 then 90
  90. else 100
  91. end
  92. end
  93. def calculate_cipher_strengths_score
  94. @cipher_strengths_score = case @server.cipher_size
  95. when 0 then 0
  96. when 0...112 then 10
  97. when 112...128 then 50
  98. when 128...256 then 90
  99. else 100
  100. end
  101. end
  102. end
  103. end
  104. end