decrypting SOCKS proxy

sockhole: Fix TLS hostname validation including SNI support

+23 -27
+23 -27
sockhole.rb
··· 84 84 class ClientDead < StandardError; end 85 85 86 86 module EMProxyConnection 87 - attr_reader :client, :hostname, :connected, :tls, :did_tls_verification 87 + attr_reader :client, :hostname, :connected, :tls, :certificate_store, 88 + :last_cert 88 89 89 90 def initialize(client, hostname, tls) 90 91 @client = client ··· 92 93 @connected = false 93 94 @tls = tls 94 95 @did_tls_verification = false 95 - end 96 + @last_cert = nil 96 97 97 - def post_init 98 - if tls 99 - start_tls(:verify_peer => true, :cert_chain_file => ssl_cert_chain_file) 100 - end 98 + @certificate_store = OpenSSL::X509::Store.new 99 + @certificate_store.set_default_paths 101 100 end 102 101 103 102 def connection_completed ··· 113 112 client.log(prio, str) 114 113 end 115 114 115 + def post_init 116 + if tls 117 + start_tls(:verify_peer => true, :sni_hostname => hostname) 118 + end 119 + end 120 + 116 121 def receive_data(_data) 117 122 client.send_data _data 118 123 end 119 124 120 125 def ssl_handshake_completed 121 - log :debug, "TLS handshake completed, sending reply" 126 + if !last_cert || 127 + !OpenSSL::SSL.verify_certificate_identity(last_cert, hostname) 128 + log :warn, "TLS verification failed for #{hostname.inspect}, aborting" 129 + close_connection 130 + return 131 + end 132 + 133 + log :info, "TLS verification succeeded for #{hostname.inspect}, sending reply" 122 134 client.send_reply REPLY_SUCCESS 123 135 end 124 136 125 137 def ssl_verify_peer(pem) 126 - if hostname.empty? 127 - return true 128 - end 129 - 130 - # we'll get called again for other certs in the chain 131 - if did_tls_verification 132 - return true 133 - end 134 - 135 - log :debug, "verifying TLS hostname #{hostname.inspect}" 136 - 137 138 cert = OpenSSL::X509::Certificate.new(pem) 138 - ret = OpenSSL::SSL.verify_certificate_identity(cert, hostname) 139 139 140 - @did_tls_verification = true 141 - 142 - # XXX: this always seems to fail, even when no OpenSSL error is reported 143 - if !ret 144 - log :warn, "TLS verification failed for #{hostname.inspect}, aborting" 145 - #close_connection 146 - #return false 140 + if certificate_store.verify(cert) 141 + @last_cert = cert 142 + certificate_store.add_cert(cert) 147 143 end 148 144 149 - return ret 145 + return true 150 146 151 147 rescue => e 152 148 log :warn, "error in ssl_verify_peer: #{e.inspect}"