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.

helpers.rb 4.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. $:.unshift File.expand_path File.join File.dirname(__FILE__), '../lib'
  2. require 'rubygems'
  3. require 'bundler/setup'
  4. require 'cryptcheck'
  5. CryptCheck::Logger.level = ENV['LOG'] || :none
  6. module Helpers
  7. OpenSSL::PKey::EC.send :alias_method, :private?, :private_key?
  8. def key(name)
  9. open(File.join(File.dirname(__FILE__), 'resources', "#{name}.pem"), 'r') { |f| OpenSSL::PKey.read f }
  10. end
  11. def dh(name)
  12. open(File.join(File.dirname(__FILE__), 'resources', "dh-#{name}.pem"), 'r') { |f| OpenSSL::PKey::DH.new f }
  13. end
  14. def certificate(key, domain)
  15. cert = OpenSSL::X509::Certificate.new
  16. cert.version = 2
  17. cert.serial = rand 2**(20*8-1) .. 2**(20*8)
  18. cert.not_before = Time.now
  19. cert.not_after = cert.not_before + 60*60
  20. cert.public_key = case key
  21. when OpenSSL::PKey::EC
  22. curve = key.group.curve_name
  23. public = OpenSSL::PKey::EC.new curve
  24. public.public_key = key.public_key
  25. public
  26. else
  27. key.public_key
  28. end
  29. name = OpenSSL::X509::Name.parse "CN=#{domain}"
  30. cert.subject = name
  31. cert.issuer = name
  32. extension_factory = OpenSSL::X509::ExtensionFactory.new nil, cert
  33. extension_factory.subject_certificate = cert
  34. extension_factory.issuer_certificate = cert
  35. cert.add_extension extension_factory.create_extension 'basicConstraints', 'CA:TRUE', true
  36. cert.add_extension extension_factory.create_extension 'keyUsage', 'keyEncipherment, dataEncipherment, digitalSignature,nonRepudiation,keyCertSign'
  37. cert.add_extension extension_factory.create_extension 'extendedKeyUsage', 'serverAuth, clientAuth'
  38. cert.add_extension extension_factory.create_extension 'subjectKeyIdentifier', 'hash'
  39. cert.add_extension extension_factory.create_extension 'authorityKeyIdentifier', 'keyid:always'
  40. cert.add_extension extension_factory.create_extension 'subjectAltName', "DNS:#{domain}"
  41. cert.sign key, OpenSSL::Digest::SHA512.new
  42. end
  43. def server(key: 'rsa-1024', domain: 'localhost', # Key & certificate
  44. host: '127.0.0.1', port: 5000, # Binding
  45. version: :TLSv1_2, ciphers: 'AES128-SHA', # TLS version and ciphers
  46. dh: 1024, ecdh: 'secp256r1') # DHE & ECDHE
  47. key = key key
  48. cert = certificate key, domain
  49. context = OpenSSL::SSL::SSLContext.new version
  50. context.cert = cert
  51. context.key = key
  52. context.ciphers = ciphers
  53. if dh
  54. dh = dh dh
  55. context.tmp_dh_callback = proc { dh }
  56. end
  57. if ecdh
  58. ecdh = key ecdh
  59. context.tmp_ecdh_callback = proc { ecdh }
  60. end
  61. IO.pipe do |stop_pipe_r, stop_pipe_w|
  62. threads = []
  63. mutex = Mutex.new
  64. started = ConditionVariable.new
  65. threads << Thread.start do
  66. tcp_server = TCPServer.new host, port
  67. ssl_server = OpenSSL::SSL::SSLServer.new tcp_server, context
  68. mutex.synchronize { started.signal }
  69. loop do
  70. readable, = IO.select [ssl_server, stop_pipe_r]
  71. break if readable.include? stop_pipe_r
  72. begin
  73. ssl_server.accept
  74. rescue
  75. end
  76. end
  77. ssl_server.close
  78. tcp_server.close
  79. end
  80. mutex.synchronize { started.wait mutex }
  81. begin
  82. yield
  83. ensure
  84. stop_pipe_w.close
  85. threads.each &:join
  86. end
  87. end
  88. end
  89. def plain_server(host: '127.0.0.1', port: 5000)
  90. IO.pipe do |stop_pipe_r, stop_pipe_w|
  91. threads = []
  92. mutex = Mutex.new
  93. started = ConditionVariable.new
  94. threads << Thread.start do
  95. tcp_server = TCPServer.new host, port
  96. mutex.synchronize { started.signal }
  97. loop do
  98. readable, = IO.select [tcp_server, stop_pipe_r]
  99. break if readable.include? stop_pipe_r
  100. begin
  101. tcp_server.accept
  102. rescue
  103. end
  104. end
  105. tcp_server.close
  106. end
  107. mutex.synchronize { started.wait mutex }
  108. begin
  109. yield
  110. ensure
  111. stop_pipe_w.close
  112. threads.each &:join
  113. end
  114. end
  115. end
  116. def expect_grade(grades, host, ip, port, family)
  117. server = grades[[host, ip, port]].server
  118. expect(server).to be_a CryptCheck::Tls::Server
  119. expect(server.hostname).to eq host
  120. expect(server.ip).to eq ip
  121. expect(server.port).to eq port
  122. expect(server.family).to eq case family
  123. when :ipv4 then Socket::AF_INET
  124. when :ipv6 then Socket::AF_INET6
  125. end
  126. end
  127. def expect_grade_error(grades, host, ip, port, error)
  128. server = grades[[host, ip, port]]
  129. expect(server).to be_a CryptCheck::AnalysisFailure
  130. expect(server.to_s).to eq error
  131. end
  132. end
  133. RSpec.configure do |c|
  134. c.include Helpers
  135. end