Skip to content
Browse files

added support of SSL Certificate handshake

  • Loading branch information...
1 parent 9e9443a commit 93a684fdb184b2dde7ecfd19313e0c995704f87f @khrvi khrvi committed Sep 19, 2011
View
30 features/ssl.feature
@@ -5,26 +5,50 @@ Feature: RightHTTPConnection can connect to a secure web server
Scenario: normal operation
Given an HTTPS URL
+ And a really dumb SSL enabled web server
When I request that URL using RightHTTPConnection
Then I should get the contents of the URL
+ Scenario: normal operation with ssl handshake
+ Given a test client certificate file
+ Given a test client key file
+ Given a CA certification file containing that server
+ Given an HTTPS URL
+ And a really dumb SSL handshake enabled web server
+ When I request that URL using RightHTTPConnection
+ Then I should get the contents of the URL
+ And there should not be a warning about certificate verification failing
+
+ Scenario: failed ssl handshake
+ Given a not verified test client certificate file
+ Given a not verified test client key file
+ Given a CA certification file not containing that server
+ Given an HTTPS URL
+ And a really dumb SSL handshake enabled web server
+ When I request that URL using RightHTTPConnection
+ Then I should get an exception
+ And there should be a warning about certificate verification failing
+
Scenario: normal operation with a CA certification file
+ Given a CA certification file containing that server
Given an HTTPS URL
- And a CA certification file containing that server
+ And a really dumb SSL enabled web server
When I request that URL using RightHTTPConnection
Then I should get the contents of the URL
And there should not be a warning about certificate verification failing
Scenario: man in the middle
+ Given a CA certification file not containing that server
Given an HTTPS URL
- And a CA certification file not containing that server
+ And a really dumb SSL enabled web server
When I request that URL using RightHTTPConnection
Then I should get the contents of the URL
And there should be a warning about certificate verification failing
Scenario: strict man in the middle
+ Given a CA certification file not containing that server
Given an HTTPS URL
- And a CA certification file not containing that server
+ And a really dumb SSL enabled web server
And the strict failure option turned on
When I request that URL using RightHTTPConnection
Then I should get an exception
View
2 features/step_definitions/right_http_connection.rb
@@ -38,6 +38,8 @@ class RightHttpConnectionFailure < Exception
hash = {:logger => @logger, :exception => RightHttpConnectionFailure}
hash[:user_agent] = @user_agent if @user_agent
hash[:ca_file] = @ca_file if @ca_file
+ hash[:cert_file] = @client_cert_file if @client_cert_file
+ hash[:key_file] = @client_key_file if @client_key_file
hash[:proxy_host] = @proxy_host if @proxy_host
hash[:proxy_port] = @proxy_port if @proxy_port
hash[:proxy_username] = @proxy_username if @proxy_username
View
22 features/step_definitions/ssl.rb
@@ -22,7 +22,6 @@
#++
Given /^an HTTPS URL$/ do
- Given "a really dumb SSL enabled web server"
@uri = URI.parse("https://127.0.0.1:7890/good")
@expected_contents = "good"
end
@@ -35,6 +34,25 @@
@ca_file = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "spec", "bad.ca"))
end
+Given /^a not verified test client certificate file$/ do
+ puts "*******************************"
+ puts "!!! PEM pass phrase: foobar !!!"
+ puts "*******************************"
+ @client_cert_file = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "spec/ca/ca.crt"))
+end
+
+Given /^a not verified test client key file$/ do
+ @client_key_file = File.expand_path(File.join(File.dirname(__FILE__), "..", "..","spec/ca/ca.key"))
+end
+
+Given /^a test client certificate file$/ do
+ @client_cert_file = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "spec/client/cert.pem"))
+end
+
+Given /^a test client key file$/ do
+ @client_key_file = File.expand_path(File.join(File.dirname(__FILE__), "..", "..","spec/client/key.pem"))
+end
+
Given /^the strict failure option turned on$/ do
@fail_if_ca_mismatch = true
end
@@ -45,4 +63,4 @@
Then /^there should not be a warning about certificate verification failing$/ do
@output.string.should_not =~ /.*WARN -- : ##### 127\.0\.0\.1 certificate verify failed:.*/
-end
+end
View
20 features/step_definitions/web_server.rb
@@ -52,6 +52,26 @@
Given "a server listening on port 7890"
end
+Given /^a really dumb SSL handshake enabled web server$/ do
+ @subprocess_pids << fork do
+ ENV['RACK_ENV'] = "test"
+ Dir.chdir(@tmpdir)
+ STDIN.close
+ output = File.open("#{@tmpdir}/weblog.out", "w")
+ STDOUT.reopen(output)
+ exec("ruby",
+ File.expand_path(File.join(File.dirname(__FILE__), "..", "..",
+ "spec/really_dumb_webserver.rb")),
+ File.expand_path(File.join(File.dirname(__FILE__), "..", "..",
+ "spec/server.crt")),
+ File.expand_path(File.join(File.dirname(__FILE__), "..", "..",
+ "spec/server.key")),
+ File.expand_path(File.join(File.dirname(__FILE__), "..", "..",
+ "spec/client/cacert.pem")))
+ end
+ Given "a server listening on port 7890"
+end
+
Given /^a URL$/ do
Given "a really dumb web server"
@uri = URI.parse("http://127.0.0.1:7890/good")
View
16 lib/right_http_connection.rb
@@ -305,6 +305,7 @@ def start(request_params)
if @protocol == 'https'
verifyCallbackProc = Proc.new{ |ok, x509_store_ctx|
+ # List of error codes: http://www.openssl.org/docs/apps/verify.html
code = x509_store_ctx.error
msg = x509_store_ctx.error_string
#debugger
@@ -317,10 +318,25 @@ def start(request_params)
}
@http.use_ssl = true
ca_file = get_param(:ca_file)
+ cert_file = get_param(:cert_file)
+ key_file = get_param(:key_file)
+
if ca_file
+ # Documentation for 'http.rb':
+ # : verify_mode, verify_mode=((|mode|))
+ # Sets the flags for server the certification verification at
+ # beginning of SSL/TLS session.
+ # OpenSSL::SSL::VERIFY_NONE or OpenSSL::SSL::VERIFY_PEER is acceptable.
+ #
+ # KHRVI: looks like the constant VERIFY_FAIL_IF_NO_PEER_CERT is not acceptable
@http.verify_mode = OpenSSL::SSL::VERIFY_PEER
@http.verify_callback = verifyCallbackProc
@http.ca_file = ca_file
+ # The depth count is 'level 0:peer certificate', 'level 1: CA certificate', 'level 2: higher level CA certificate', and so on.
+ # Setting the maximum depth to 2 allows the levels 0, 1, and 2. The default depth limit is 9, allowing for the peer certificate and additional 9 CA certificates.
+ @http.verify_depth = 9
+ @http.cert = OpenSSL::X509::Certificate.new(File.read(cert_file)) if cert_file
+ @http.key = OpenSSL::PKey::RSA.new(File.read(key_file)) if key_file
else
@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
View
BIN spec/client/cacert.cer
Binary file not shown.
View
17 spec/client/cacert.pem
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICxjCCAa6gAwIBAgIJAJYV+DprCQ1CMA0GCSqGSIb3DQEBBQUAMBMxETAPBgNV
+BAMTCE15VGVzdENBMB4XDTExMDkxMzIyNTMxMVoXDTEyMDkxMjIyNTMxMVowEzER
+MA8GA1UEAxMITXlUZXN0Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQCwmvBNrd7t/Z7ZVo1YfimpGgerOn1vXZY+OGJtqo+pN11Ei7dhVQfWBd2dAkYH
+B8NlPr5QyxmIT88JIRKEzk7ZZ+nRdfyoocg63FeLn+b6OeR5hwyK38aMRbhqY1Gq
+aIKMYyEpv0YNbuwoomv5Atl8mwvuUFr2XKndyzsrP1TrTCHH4lA5P0UUzIjVyyz9
+F4YAjGLjjoVO5R02LmZ/h/LqT6bJQ+cu/2JeIWGVnjKoFvyWHd0TOaOGDHlQc5h8
+RxgdOFrjsZGpQ5sKlhcI+9p0LOXqVfoC2J2ZWtAjFo0d54E/OarnBPFB6VNtoSmj
+l0z+OLGMKuDGaLflXNE0STVdAgMBAAGjHTAbMAwGA1UdEwQFMAMBAf8wCwYDVR0P
+BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAAbVkvPzS59uhX6Ox1ZT92cJXW8yjP
+IyXrZjcWlaKQSKcn8v5RpebtVA+pL6mCActBE8fMac5ixlwTTnF5LHb9v80XuXMe
+MXooQZBliyim5lVCp9gjKZYXEeVDphsuwDr5M4qO7tdZTB1ezCULObVF1N7qMwpO
+yWI6zifRtLsgWmnRyaeVyv2uNRYoAEsAd2Dj4oJjvuyc9U5QUhtsXwD3jvSPsdi6
+Mbr5tVIcZSpT4W9PSiZw2ZUZXIEbxX+w+FsuehhvoFJCi05R1ashCPxQA13bOJK0
+BmbHqeLDzJCK0+kQs8CRIGWGTGng84AyJ5MygGzd0WN9jtZslWTPDtbz
+-----END CERTIFICATE-----
View
18 spec/client/cert.pem
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC9TCCAd2gAwIBAgIBAjANBgkqhkiG9w0BAQUFADATMREwDwYDVQQDEwhNeVRl
+c3RDQTAeFw0xMTA5MTMyMzAxMDVaFw0xMjA5MTIyMzAxMDVaMDgxJTAjBgNVBAMM
+HE1haGVuZHJhLUt1dGFyZXMtTWFjQm9vay1Qcm8xDzANBgNVBAoMBmNsaWVudDCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMcEhrVTKKgWVqTUBCGBWJlD
+u7RIk7kPcGAARy7Ctx+4VReEYlgVRqECzt4itglNdrQkUVCHXE0rwJMOozE8Hsgh
+rAOQvxzPJhG3hPUJf/VkfB+Dn0xRsPvrE90HpRlSqdT8X6iuryPEmp5RyMaY122P
+r/+Xs+lHhRlKQPdRpYXHlOwWX/U56Wy7jjGU9lONBEIEV8tD5ExzkCG23nbCvrFr
+/2c4VjrAwXR2RyYfSDRyc/obky49ydKZ8/HKbS3VdJYAWBI4Wnj2hayCcZggEFB0
+zg/IDXpOjnr6zV5UEfdaMIH4/K44ISX7xmZWGmQ3464NTmykj5xUMmfy3rVNREsC
+AwEAAaMvMC0wCQYDVR0TBAIwADALBgNVHQ8EBAMCB4AwEwYDVR0lBAwwCgYIKwYB
+BQUHAwIwDQYJKoZIhvcNAQEFBQADggEBACmNyOoCvNsz8N3LN47VZK7aev54tjtd
+zJilLgAxEGBeaIvHX9LDkgi3sQAvHMHc3VIq4BoEd9TNtyxIrUdc2EG1TCJvHINP
+7YoHtbajvT3bhVLlnWjB7jHp9jNfZtHL7aEDp+5eqPT6wzaVeiu1nABs7gudCQq1
+CJw0Mfz1U3mG0sTb5JlRt7toce9dW0R6jfYTmTj6Yzu3kcgYjQKy2k2BCInLOIhz
+6tyOH51mCGAy1zgcWMvuyKYCeJQxRd46GrR2peyE2wYY6SfSlrK16pjaz48S3uhI
+01jd+HA1LARcImMhkMa/QFTo4uI7lx9Q+Y06Ny+rMuTNSnBSIgCUPQk=
+-----END CERTIFICATE-----
View
27 spec/client/key.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAxwSGtVMoqBZWpNQEIYFYmUO7tEiTuQ9wYABHLsK3H7hVF4Ri
+WBVGoQLO3iK2CU12tCRRUIdcTSvAkw6jMTweyCGsA5C/HM8mEbeE9Ql/9WR8H4Of
+TFGw++sT3QelGVKp1PxfqK6vI8SanlHIxpjXbY+v/5ez6UeFGUpA91GlhceU7BZf
+9TnpbLuOMZT2U40EQgRXy0PkTHOQIbbedsK+sWv/ZzhWOsDBdHZHJh9INHJz+huT
+Lj3J0pnz8cptLdV0lgBYEjhaePaFrIJxmCAQUHTOD8gNek6OevrNXlQR91owgfj8
+rjghJfvGZlYaZDfjrg1ObKSPnFQyZ/LetU1ESwIDAQABAoIBAB23pU3KHxYKT+HI
+7tz57XrlTE/9TmGh1ovfPsHSvXl1Eu+yCuVQN/2u56jv0fLNqF351lKKA9RaJiVP
+WDrv2UDVFlRp9r+chvi6SJY2Vu8TlB04kD7bK+xSC+NDUvnXCBkPnlEX1HsozlW5
+rJtLE0/+1q75vhmlXlCKb+z+OhMhmFnaWTf/xLNbkItO5tOf+mv/CoqBUSEk+i9t
+O6Zjzh02jbpW7xH3jJ/UexKMYOuqxoOMfC/MI6q3Qcu2OeZgl8cEIi94sjafq9ob
+WcFTrZY+YG5b1SE8ILg69Fkqve5d2Mn1sN8mYZxLeM0C/ATNghM5uSWhdze06bNu
+fpcgvOECgYEA/L+J/xVgUySUByELEBosY8q0HYG5Msq+GT7L5GMIoEmEp4j6MPRu
+kF/DihxefcvDyVRLhJh7o/kwR7Vwe4wP9145e3MOe9b7IH6pEwV0nAsBO6ldVToX
+gvrHOIoySNt/XtRurrbtZ08OtUDCLIRQATTnY9ieh8sxTyl1G9GehoMCgYEAyZQE
+r4ByBzXjTiuaODH6tPndbKFxRo2iis9CyxqYXAMDkjvF4NEpQyW5ucRxpRqTt51P
+kR13jdadnOF4t82M0qqEH3G6H4biKisY1jXRNH7mPSbyPbC4vxrQhnAEF3RiqbXz
+f2LUC4uOtLzW7HeyjEiZy2mg7UKdOfsmmJ//oJkCgYEAxZF/8GqoQjW8lJoKyMp8
+2oDQLKSDvSVoVdmVjfCwBIOTc1aKpAveBXMmKealIlZOtCj1Yy/CrlmSmOtGgvzo
+WihIbKxyrPFOmocH6PuBvJyJmTZ5464mRNd9NUApsHQL63fJET+i8feFer+lSSEg
+XOEa4xyoR2PZJpU0mstPzLsCgYBvcS3F+TURV3F7Xg+80aTROPJ5hCej4dni9ALx
+Vpq1A9WNmw4i5H/zZ3/ue/R4WuEfuhCrIade+y/X869RrooUTcENwUos891Fgt4Q
+T2CBrUaMuGNkR7dbr+9o47TfYrDJMpaT7odceqNCuMP5p5NGizy7gII/qXxS+c60
+woAIwQKBgQCiIfXZtAgYTPL23CQrxIMFwnlO0TiOe0ha0et7hjCh/CStG7NET7KK
+U1L1kfyl1YDgoJbLXTsG2WwGZRnK1oyEEFj2iY5EvwoMPr0Sv8/CiOIyEfC62s3V
+MoHemunnFhAj+JAy2HTKV0VYiNNNAxz3CBG8yMLK7YAMgPw1/HQQLQ==
+-----END RSA PRIVATE KEY-----
View
17 spec/really_dumb_webserver.rb
@@ -23,7 +23,7 @@
require 'webrick'
-ssl_cert, ssl_key = ARGV[0], ARGV[1]
+ssl_cert, ssl_key, ca_cert = ARGV[0], ARGV[1], ARGV[2]
# Monkey patch bad User-Agent parsing
module WEBrick::AccessLog
@@ -52,18 +52,27 @@ def format(format_string, params)
end
end
-logger = WEBrick::Log.new($stderr, WEBrick::Log::WARN)
+logger = WEBrick::Log.new($stderr, WEBrick::Log::WARN)#WEBrick::Log::DEBUG
config = {}
config[:Port] = 7890
config[:Logger] = logger
config[:AccessLog] = [[$stdout, WEBrick::AccessLog::COMBINED_LOG_FORMAT]]
unless ssl_cert.nil? || ssl_key.nil?
require 'webrick/https'
config[:SSLEnable] = true
- config[:SSLVerifyClient] = OpenSSL::SSL::VERIFY_NONE
+ # http://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html#
+ # SSL_VERIFY_FAIL_IF_NO_PEER_CERT
+ # => Server mode: if the client did not return a certificate, the TLS/SSL handshake is immediately terminated with a 'handshake failure' alert.
+ # => This flag must be used together with SSL_VERIFY_PEER.
+ config[:SSLVerifyClient] = OpenSSL::SSL::VERIFY_PEER
+ config[:SSLVerifyClient] |= OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT if ca_cert
config[:SSLPrivateKey] = OpenSSL::PKey::RSA.new(File.open(ssl_key).read)
config[:SSLCertificate] = OpenSSL::X509::Certificate.new(File.open(ssl_cert).read)
- config[:SSLCertName] = [["CN", "Graham Hughes"]]
+ # KHRVI: option config[:SSLCertName] does make sense only when config[:SSLCertificate] isn't specified
+ # see: webrick/ssl.rb method :setup_ssl_context
+ # config[:SSLCertName] = [["CN", "Graham Hughes"]]
+ config[:SSLVerifyDepth] = 9
+ config[:SSLCACertificateFile] = ca_cert if ca_cert
end
$stdout.sync = true
server = WEBrick::HTTPServer.new(config)

0 comments on commit 93a684f

Please sign in to comment.
Something went wrong with that request. Please try again.