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.

140 lines
3.6KB

  1. module CryptCheck
  2. module Tls
  3. class Grade
  4. attr_reader :server, :grade, :states
  5. def initialize(server)
  6. @server = server
  7. @checks = checks
  8. @states = calculate_states
  9. @grade = calculate_grade
  10. end
  11. def display
  12. color = case @grade
  13. when 'A', 'A+'
  14. :best
  15. when 'B', 'B+'
  16. :perfect
  17. when 'C', 'C+'
  18. :good
  19. when 'E'
  20. :warning
  21. when 'F'
  22. :error
  23. when 'G'
  24. :critical
  25. when 'M', 'T'
  26. :unknown
  27. end
  28. Logger.info { "Grade : #{self.grade.colorize color }" }
  29. Logger.info { '' }
  30. Status.each do |color|
  31. states = @states[color]
  32. Logger.info { "#{color.to_s.capitalize} : #{states.collect { |s| s.to_s.colorize color }.join ' '}" } unless states.empty?
  33. end
  34. end
  35. private
  36. def calculate_grade
  37. case
  38. when !@states[:critical].empty?
  39. return 'G'
  40. when !@states[:error].empty?
  41. return 'F'
  42. when !@states[:warning].empty?
  43. return 'E'
  44. end
  45. goods = @checks.select { |c| c.last == :good }.collect &:first
  46. unless goods.empty?
  47. return 'D' if @states[:good].empty?
  48. return 'C' if @states[:good] != goods
  49. end
  50. perfects = @checks.select { |c| c.last == :perfect }.collect &:first
  51. unless perfects.empty?
  52. return 'C+' if @states[:perfect].empty?
  53. return 'B' if @states[:perfect] != perfects
  54. end
  55. bests = @checks.select { |c| c.last == :best }.collect &:first
  56. unless bests.empty?
  57. return 'B+' if @states[:best].empty?
  58. return 'A' if @states[:best] != bests
  59. end
  60. 'A+'
  61. end
  62. CHECKS = ([
  63. # Certificates
  64. [:weak_sign, Proc.new { |s|
  65. Cert::WEAK_SIGN[:critical]
  66. }, :critical],
  67. # Keys
  68. [:weak_key, Proc.new { |s| Status.problem s.keys.collect &:status }],
  69. # DH
  70. [:weak_dh, Proc.new { |s| Status.problem s.dh.collect &:status }],
  71. # Protocols
  72. [:ssl, Proc.new { |s| s.ssl? }, :critical],
  73. [:tls12, Proc.new { |s| s.tlsv1_2? }, :good],
  74. [:tls12_only, Proc.new { |s| s.tlsv1_2_only? }, :perfect],
  75. # Ciphers
  76. [:dss, Proc.new { |s| s.dss? }, :critical],
  77. [:anonymous, Proc.new { |s| s.anonymous? }, :critical],
  78. [:null, Proc.new { |s| s.null? }, :critical],
  79. [:export, Proc.new { |s| s.export? }, :critical],
  80. [:des, Proc.new { |s| s.des? }, :critical],
  81. [:md5, Proc.new { |s| s.md5? }, :critical],
  82. [:rc4, Proc.new { |s| s.rc4? }, :error],
  83. [:sweet32, Proc.new { |s| s.sweet32? }, :error],
  84. [:no_pfs, Proc.new { |s| not s.pfs_only? }, :warning],
  85. [:pfs, Proc.new { |s| s.pfs? }, :good],
  86. [:pfs_only, Proc.new { |s| s.pfs_only? }, :perfect],
  87. [:no_ecdhe, Proc.new { |s| not s.ecdhe? }, :warning],
  88. [:ecdhe, Proc.new { |s| s.ecdhe? }, :good],
  89. [:ecdhe_only, Proc.new { |s| s.ecdhe_only? }, :perfect],
  90. [:aead, Proc.new { |s| s.aead? }, :good],
  91. #[:aead_only, Proc.new { |s| s.aead_only? }, :best],
  92. ] + Cert::WEAK_SIGN.collect do |level, hashes|
  93. hashes.collect do |hash|
  94. ["#{hash}_sig?".to_sym, Proc.new { |s| s.call "#{hash}_sig?".to_sym }, level ]
  95. end
  96. end.flatten(1)).freeze
  97. def checks
  98. checks = CHECKS
  99. unless @server.fallback_scsv? == nil
  100. checks += [
  101. [:no_fallback_scsv, Proc.new { |s| not s.fallback_scsv? }, :error],
  102. [:fallback_scsv, Proc.new { |s| s.fallback_scsv? }, :good]
  103. ]
  104. end
  105. checks
  106. end
  107. def calculate_states
  108. states = Status.empty
  109. @checks.each do |name, check, status|
  110. result = check.call @server
  111. if result
  112. state = states[status ? status : result]
  113. state << name if state
  114. end
  115. end
  116. states
  117. end
  118. end
  119. end
  120. end