tangled
alpha
login
or
join now
jcs.org
/
sockhole
0
fork
atom
decrypting SOCKS proxy
0
fork
atom
overview
issues
pulls
pipelines
sockhole: Fix TLS hostname validation including SNI support
jcs.org
4 years ago
8a50070d
7b630d34
+23
-27
1 changed file
expand all
collapse all
unified
split
sockhole.rb
+23
-27
sockhole.rb
···
84
84
class ClientDead < StandardError; end
85
85
86
86
module EMProxyConnection
87
87
-
attr_reader :client, :hostname, :connected, :tls, :did_tls_verification
87
87
+
attr_reader :client, :hostname, :connected, :tls, :certificate_store,
88
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
95
-
end
96
96
+
@last_cert = nil
96
97
97
97
-
def post_init
98
98
-
if tls
99
99
-
start_tls(:verify_peer => true, :cert_chain_file => ssl_cert_chain_file)
100
100
-
end
98
98
+
@certificate_store = OpenSSL::X509::Store.new
99
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
115
+
def post_init
116
116
+
if tls
117
117
+
start_tls(:verify_peer => true, :sni_hostname => hostname)
118
118
+
end
119
119
+
end
120
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
121
-
log :debug, "TLS handshake completed, sending reply"
126
126
+
if !last_cert ||
127
127
+
!OpenSSL::SSL.verify_certificate_identity(last_cert, hostname)
128
128
+
log :warn, "TLS verification failed for #{hostname.inspect}, aborting"
129
129
+
close_connection
130
130
+
return
131
131
+
end
132
132
+
133
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
126
-
if hostname.empty?
127
127
-
return true
128
128
-
end
129
129
-
130
130
-
# we'll get called again for other certs in the chain
131
131
-
if did_tls_verification
132
132
-
return true
133
133
-
end
134
134
-
135
135
-
log :debug, "verifying TLS hostname #{hostname.inspect}"
136
136
-
137
138
cert = OpenSSL::X509::Certificate.new(pem)
138
138
-
ret = OpenSSL::SSL.verify_certificate_identity(cert, hostname)
139
139
140
140
-
@did_tls_verification = true
141
141
-
142
142
-
# XXX: this always seems to fail, even when no OpenSSL error is reported
143
143
-
if !ret
144
144
-
log :warn, "TLS verification failed for #{hostname.inspect}, aborting"
145
145
-
#close_connection
146
146
-
#return false
140
140
+
if certificate_store.verify(cert)
141
141
+
@last_cert = cert
142
142
+
certificate_store.add_cert(cert)
147
143
end
148
144
149
149
-
return ret
145
145
+
return true
150
146
151
147
rescue => e
152
148
log :warn, "error in ssl_verify_peer: #{e.inspect}"