Skip to content

Commit e5fa144

Browse files
authored
Merge TLS verification patch from Faraday (#340)
Closes #339, CVE-2020-13482 Credit to Mislav Marohnić for original implementation, merged from Faraday.
1 parent 1d1f82f commit e5fa144

File tree

2 files changed

+57
-0
lines changed

2 files changed

+57
-0
lines changed

lib/em-http.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
require 'base64'
77
require 'socket'
8+
require 'openssl'
89

910
require 'em-http/core_ext/bytesize'
1011
require 'em-http/http_connection'

lib/em-http/http_connection.rb

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,62 @@ def connection_completed
3636
def unbind(reason=nil)
3737
@parent.unbind(reason)
3838
end
39+
40+
# TLS verification support, original implementation by Mislav Marohnić
41+
# https://github.com/lostisland/faraday/blob/63cf47c95b573539f047c729bd9ad67560bc83ff/lib/faraday/adapter/em_http_ssl_patch.rb
42+
def ssl_verify_peer(cert_string)
43+
cert = nil
44+
begin
45+
cert = OpenSSL::X509::Certificate.new(cert_string)
46+
rescue OpenSSL::X509::CertificateError
47+
return false
48+
end
49+
50+
@last_seen_cert = cert
51+
52+
if certificate_store.verify(@last_seen_cert)
53+
begin
54+
certificate_store.add_cert(@last_seen_cert)
55+
rescue OpenSSL::X509::StoreError => e
56+
raise e unless e.message == 'cert already in hash table'
57+
end
58+
true
59+
else
60+
raise OpenSSL::SSL::SSLError.new(%(unable to verify the server certificate for "#{host}"))
61+
end
62+
end
63+
64+
def ssl_handshake_completed
65+
unless verify_peer?
66+
warn "[WARNING; em-http-request] TLS hostname validation is disabled (use 'tls: {verify_peer: true}'), see" +
67+
" CVE-2020-13482 and https://github.com/igrigorik/em-http-request/issues/339 for details"
68+
return true
69+
end
70+
71+
unless OpenSSL::SSL.verify_certificate_identity(@last_seen_cert, host)
72+
raise OpenSSL::SSL::SSLError.new(%(host "#{host}" does not match the server certificate))
73+
else
74+
true
75+
end
76+
end
77+
78+
def verify_peer?
79+
parent.connopts.tls[:verify_peer]
80+
end
81+
82+
def host
83+
parent.connopts.host
84+
end
85+
86+
def certificate_store
87+
@certificate_store ||= begin
88+
store = OpenSSL::X509::Store.new
89+
store.set_default_paths
90+
ca_file = parent.connopts.tls[:cert_chain_file]
91+
store.add_file(ca_file) if ca_file
92+
store
93+
end
94+
end
3995
end
4096

4197
class HttpConnection

0 commit comments

Comments
 (0)