blob: 3b77e391b86b7ae22fdf0efe3e4a9e786e328fbe [file] [log] [blame]
Nobuaki Sukegawaad835862015-12-23 23:32:09 +09001#
2# Licensed to the Apache Software Foundation (ASF) under one
3# or more contributor license agreements. See the NOTICE file
4# distributed with this work for additional information
5# regarding copyright ownership. The ASF licenses this file
6# to you under the Apache License, Version 2.0 (the
7# "License"); you may not use this file except in compliance
8# with the License. You may obtain a copy of the License at
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing,
13# software distributed under the License is distributed on an
14# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15# KIND, either express or implied. See the License for the
16# specific language governing permissions and limitations
17# under the License.
18#
19
Nobuaki Sukegawa66f50532016-02-14 21:47:38 +090020import inspect
Nobuaki Sukegawa355116e2016-02-11 18:01:20 +090021import logging
Nobuaki Sukegawaad835862015-12-23 23:32:09 +090022import os
23import platform
Nobuaki Sukegawaad835862015-12-23 23:32:09 +090024import ssl
25import sys
John Siroisac067042016-02-12 08:10:13 -070026import tempfile
Nobuaki Sukegawaad835862015-12-23 23:32:09 +090027import threading
Nobuaki Sukegawaad835862015-12-23 23:32:09 +090028import unittest
29import warnings
John Siroisac067042016-02-12 08:10:13 -070030from contextlib import contextmanager
31
Nobuaki Sukegawa6a0ca7f2016-02-13 03:11:16 +090032import _import_local_thrift # noqa
Nobuaki Sukegawaad835862015-12-23 23:32:09 +090033
34SCRIPT_DIR = os.path.realpath(os.path.dirname(__file__))
35ROOT_DIR = os.path.dirname(os.path.dirname(os.path.dirname(SCRIPT_DIR)))
36SERVER_PEM = os.path.join(ROOT_DIR, 'test', 'keys', 'server.pem')
37SERVER_CERT = os.path.join(ROOT_DIR, 'test', 'keys', 'server.crt')
38SERVER_KEY = os.path.join(ROOT_DIR, 'test', 'keys', 'server.key')
Nobuaki Sukegawaf39f7db2016-02-04 15:09:41 +090039CLIENT_CERT_NO_IP = os.path.join(ROOT_DIR, 'test', 'keys', 'client.crt')
40CLIENT_KEY_NO_IP = os.path.join(ROOT_DIR, 'test', 'keys', 'client.key')
41CLIENT_CERT = os.path.join(ROOT_DIR, 'test', 'keys', 'client_v3.crt')
42CLIENT_KEY = os.path.join(ROOT_DIR, 'test', 'keys', 'client_v3.key')
43CLIENT_CA = os.path.join(ROOT_DIR, 'test', 'keys', 'CA.pem')
Nobuaki Sukegawaad835862015-12-23 23:32:09 +090044
Aki Sukegawaeb9f65b2018-06-03 19:15:53 +090045TEST_CIPHERS = 'DES-CBC3-SHA:ECDHE-RSA-AES128-GCM-SHA256'
Nobuaki Sukegawaad835862015-12-23 23:32:09 +090046
47
48class ServerAcceptor(threading.Thread):
Nobuaki Sukegawa66f50532016-02-14 21:47:38 +090049 def __init__(self, server, expect_failure=False):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090050 super(ServerAcceptor, self).__init__()
John Siroisac067042016-02-12 08:10:13 -070051 self.daemon = True
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090052 self._server = server
John Siroisac067042016-02-12 08:10:13 -070053 self._listening = threading.Event()
54 self._port = None
55 self._port_bound = threading.Event()
56 self._client = None
57 self._client_accepted = threading.Event()
Nobuaki Sukegawa66f50532016-02-14 21:47:38 +090058 self._expect_failure = expect_failure
59 frame = inspect.stack(3)[2]
60 self.name = frame[3]
61 del frame
Nobuaki Sukegawaad835862015-12-23 23:32:09 +090062
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090063 def run(self):
64 self._server.listen()
John Siroisac067042016-02-12 08:10:13 -070065 self._listening.set()
66
67 try:
68 address = self._server.handle.getsockname()
69 if len(address) > 1:
70 # AF_INET addresses are 2-tuples (host, port) and AF_INET6 are
71 # 4-tuples (host, port, ...), but in each case port is in the second slot.
72 self._port = address[1]
73 finally:
74 self._port_bound.set()
75
76 try:
77 self._client = self._server.accept()
James E. King III3131fe92019-07-02 14:21:05 -040078 if self._client:
79 self._client.read(5) # hello
80 self._client.write(b"there")
Nobuaki Sukegawa66f50532016-02-14 21:47:38 +090081 except Exception:
82 logging.exception('error on server side (%s):' % self.name)
83 if not self._expect_failure:
84 raise
John Siroisac067042016-02-12 08:10:13 -070085 finally:
86 self._client_accepted.set()
87
88 def await_listening(self):
89 self._listening.wait()
90
91 @property
92 def port(self):
93 self._port_bound.wait()
94 return self._port
95
96 @property
97 def client(self):
98 self._client_accepted.wait()
99 return self._client
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900100
Aki Sukegawaeb9f65b2018-06-03 19:15:53 +0900101 def close(self):
102 if self._client:
103 self._client.close()
104 self._server.close()
105
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900106
107# Python 2.6 compat
108class AssertRaises(object):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900109 def __init__(self, expected):
110 self._expected = expected
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900111
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900112 def __enter__(self):
113 pass
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900114
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900115 def __exit__(self, exc_type, exc_value, traceback):
116 if not exc_type or not issubclass(exc_type, self._expected):
117 raise Exception('fail')
118 return True
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900119
120
121class TSSLSocketTest(unittest.TestCase):
John Siroisac067042016-02-12 08:10:13 -0700122 def _server_socket(self, **kwargs):
123 return TSSLServerSocket(port=0, **kwargs)
124
125 @contextmanager
Nobuaki Sukegawa66f50532016-02-14 21:47:38 +0900126 def _connectable_client(self, server, expect_failure=False, path=None, **client_kwargs):
127 acc = ServerAcceptor(server, expect_failure)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900128 try:
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900129 acc.start()
John Siroisac067042016-02-12 08:10:13 -0700130 acc.await_listening()
131
132 host, port = ('localhost', acc.port) if path is None else (None, None)
Nobuaki Sukegawa66f50532016-02-14 21:47:38 +0900133 client = TSSLSocket(host, port, unix_socket=path, **client_kwargs)
John Siroisac067042016-02-12 08:10:13 -0700134 yield acc, client
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900135 finally:
Aki Sukegawaeb9f65b2018-06-03 19:15:53 +0900136 acc.close()
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900137
John Siroisac067042016-02-12 08:10:13 -0700138 def _assert_connection_failure(self, server, path=None, **client_args):
Nobuaki Sukegawa66f50532016-02-14 21:47:38 +0900139 logging.disable(logging.CRITICAL)
Nobuaki Sukegawad2b4f242016-09-04 18:49:23 +0900140 try:
141 with self._connectable_client(server, True, path=path, **client_args) as (acc, client):
John Siroisac067042016-02-12 08:10:13 -0700142 # We need to wait for a connection failure, but not too long. 20ms is a tunable
143 # compromise between test speed and stability
144 client.setTimeout(20)
145 with self._assert_raises(TTransportException):
146 client.open()
James E. King III3131fe92019-07-02 14:21:05 -0400147 client.write(b"hello")
148 client.read(5) # b"there"
Nobuaki Sukegawad2b4f242016-09-04 18:49:23 +0900149 finally:
150 logging.disable(logging.NOTSET)
John Siroisac067042016-02-12 08:10:13 -0700151
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900152 def _assert_raises(self, exc):
153 if sys.hexversion >= 0x020700F0:
154 return self.assertRaises(exc)
155 else:
156 return AssertRaises(exc)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900157
John Siroisac067042016-02-12 08:10:13 -0700158 def _assert_connection_success(self, server, path=None, **client_args):
159 with self._connectable_client(server, path=path, **client_args) as (acc, client):
John Siroisac067042016-02-12 08:10:13 -0700160 try:
Michael Smithe3eb9af2022-06-08 17:23:27 -0700161 self.assertFalse(client.isOpen())
James E. King III3131fe92019-07-02 14:21:05 -0400162 client.open()
Michael Smithe3eb9af2022-06-08 17:23:27 -0700163 self.assertTrue(client.isOpen())
James E. King III3131fe92019-07-02 14:21:05 -0400164 client.write(b"hello")
165 self.assertEqual(client.read(5), b"there")
John Siroisac067042016-02-12 08:10:13 -0700166 self.assertTrue(acc.client is not None)
167 finally:
168 client.close()
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900169
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900170 # deprecated feature
171 def test_deprecation(self):
172 with warnings.catch_warnings(record=True) as w:
Nobuaki Sukegawa6a0ca7f2016-02-13 03:11:16 +0900173 warnings.filterwarnings('always', category=DeprecationWarning, module=self.__module__)
John Siroisac067042016-02-12 08:10:13 -0700174 TSSLSocket('localhost', 0, validate=True, ca_certs=SERVER_CERT)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900175 self.assertEqual(len(w), 1)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900176
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900177 with warnings.catch_warnings(record=True) as w:
Nobuaki Sukegawa6a0ca7f2016-02-13 03:11:16 +0900178 warnings.filterwarnings('always', category=DeprecationWarning, module=self.__module__)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900179 # Deprecated signature
180 # def __init__(self, host='localhost', port=9090, validate=True, ca_certs=None, keyfile=None, certfile=None, unix_socket=None, ciphers=None):
Nobuaki Sukegawa6a0ca7f2016-02-13 03:11:16 +0900181 TSSLSocket('localhost', 0, True, SERVER_CERT, CLIENT_KEY, CLIENT_CERT, None, TEST_CIPHERS)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900182 self.assertEqual(len(w), 7)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900183
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900184 with warnings.catch_warnings(record=True) as w:
Nobuaki Sukegawa6a0ca7f2016-02-13 03:11:16 +0900185 warnings.filterwarnings('always', category=DeprecationWarning, module=self.__module__)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900186 # Deprecated signature
187 # def __init__(self, host=None, port=9090, certfile='cert.pem', unix_socket=None, ciphers=None):
Nobuaki Sukegawa6a0ca7f2016-02-13 03:11:16 +0900188 TSSLServerSocket(None, 0, SERVER_PEM, None, TEST_CIPHERS)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900189 self.assertEqual(len(w), 3)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900190
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900191 # deprecated feature
192 def test_set_cert_reqs_by_validate(self):
Nobuaki Sukegawa6a0ca7f2016-02-13 03:11:16 +0900193 with warnings.catch_warnings(record=True) as w:
194 warnings.filterwarnings('always', category=DeprecationWarning, module=self.__module__)
195 c1 = TSSLSocket('localhost', 0, validate=True, ca_certs=SERVER_CERT)
196 self.assertEqual(c1.cert_reqs, ssl.CERT_REQUIRED)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900197
Nobuaki Sukegawa6a0ca7f2016-02-13 03:11:16 +0900198 c1 = TSSLSocket('localhost', 0, validate=False)
199 self.assertEqual(c1.cert_reqs, ssl.CERT_NONE)
200
201 self.assertEqual(len(w), 2)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900202
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900203 # deprecated feature
204 def test_set_validate_by_cert_reqs(self):
Nobuaki Sukegawa6a0ca7f2016-02-13 03:11:16 +0900205 with warnings.catch_warnings(record=True) as w:
206 warnings.filterwarnings('always', category=DeprecationWarning, module=self.__module__)
207 c1 = TSSLSocket('localhost', 0, cert_reqs=ssl.CERT_NONE)
208 self.assertFalse(c1.validate)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900209
Nobuaki Sukegawa6a0ca7f2016-02-13 03:11:16 +0900210 c2 = TSSLSocket('localhost', 0, cert_reqs=ssl.CERT_REQUIRED, ca_certs=SERVER_CERT)
211 self.assertTrue(c2.validate)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900212
Nobuaki Sukegawa6a0ca7f2016-02-13 03:11:16 +0900213 c3 = TSSLSocket('localhost', 0, cert_reqs=ssl.CERT_OPTIONAL, ca_certs=SERVER_CERT)
214 self.assertTrue(c3.validate)
215
216 self.assertEqual(len(w), 3)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900217
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900218 def test_unix_domain_socket(self):
219 if platform.system() == 'Windows':
220 print('skipping test_unix_domain_socket')
221 return
John Siroisac067042016-02-12 08:10:13 -0700222 fd, path = tempfile.mkstemp()
223 os.close(fd)
junnplusfe11c482019-01-12 02:15:05 +0800224 os.unlink(path)
John Siroisac067042016-02-12 08:10:13 -0700225 try:
226 server = self._server_socket(unix_socket=path, keyfile=SERVER_KEY, certfile=SERVER_CERT)
227 self._assert_connection_success(server, path=path, cert_reqs=ssl.CERT_NONE)
228 finally:
229 os.unlink(path)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900230
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900231 def test_server_cert(self):
John Siroisac067042016-02-12 08:10:13 -0700232 server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT)
233 self._assert_connection_success(server, cert_reqs=ssl.CERT_REQUIRED, ca_certs=SERVER_CERT)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900234
John Siroisac067042016-02-12 08:10:13 -0700235 server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT)
236 # server cert not in ca_certs
237 self._assert_connection_failure(server, cert_reqs=ssl.CERT_REQUIRED, ca_certs=CLIENT_CERT)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900238
John Siroisac067042016-02-12 08:10:13 -0700239 server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT)
240 self._assert_connection_success(server, cert_reqs=ssl.CERT_NONE)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900241
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900242 def test_set_server_cert(self):
John Siroisac067042016-02-12 08:10:13 -0700243 server = self._server_socket(keyfile=SERVER_KEY, certfile=CLIENT_CERT)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900244 with self._assert_raises(Exception):
245 server.certfile = 'foo'
246 with self._assert_raises(Exception):
247 server.certfile = None
248 server.certfile = SERVER_CERT
John Siroisac067042016-02-12 08:10:13 -0700249 self._assert_connection_success(server, cert_reqs=ssl.CERT_REQUIRED, ca_certs=SERVER_CERT)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900250
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900251 def test_client_cert(self):
Nobuaki Sukegawae8ba7872017-02-12 21:14:48 +0900252 if not _match_has_ipaddress:
253 print('skipping test_client_cert')
254 return
John Siroisac067042016-02-12 08:10:13 -0700255 server = self._server_socket(
256 cert_reqs=ssl.CERT_REQUIRED, keyfile=SERVER_KEY,
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900257 certfile=SERVER_CERT, ca_certs=CLIENT_CERT)
John Siroisac067042016-02-12 08:10:13 -0700258 self._assert_connection_failure(server, cert_reqs=ssl.CERT_NONE, certfile=SERVER_CERT, keyfile=SERVER_KEY)
Nobuaki Sukegawaf39f7db2016-02-04 15:09:41 +0900259
John Siroisac067042016-02-12 08:10:13 -0700260 server = self._server_socket(
261 cert_reqs=ssl.CERT_REQUIRED, keyfile=SERVER_KEY,
Nobuaki Sukegawaf39f7db2016-02-04 15:09:41 +0900262 certfile=SERVER_CERT, ca_certs=CLIENT_CA)
John Siroisac067042016-02-12 08:10:13 -0700263 self._assert_connection_failure(server, cert_reqs=ssl.CERT_NONE, certfile=CLIENT_CERT_NO_IP, keyfile=CLIENT_KEY_NO_IP)
Nobuaki Sukegawaf39f7db2016-02-04 15:09:41 +0900264
John Siroisac067042016-02-12 08:10:13 -0700265 server = self._server_socket(
266 cert_reqs=ssl.CERT_REQUIRED, keyfile=SERVER_KEY,
Nobuaki Sukegawaf39f7db2016-02-04 15:09:41 +0900267 certfile=SERVER_CERT, ca_certs=CLIENT_CA)
John Siroisac067042016-02-12 08:10:13 -0700268 self._assert_connection_success(server, cert_reqs=ssl.CERT_NONE, certfile=CLIENT_CERT, keyfile=CLIENT_KEY)
Nobuaki Sukegawaf39f7db2016-02-04 15:09:41 +0900269
John Siroisac067042016-02-12 08:10:13 -0700270 server = self._server_socket(
271 cert_reqs=ssl.CERT_OPTIONAL, keyfile=SERVER_KEY,
Nobuaki Sukegawaf39f7db2016-02-04 15:09:41 +0900272 certfile=SERVER_CERT, ca_certs=CLIENT_CA)
John Siroisac067042016-02-12 08:10:13 -0700273 self._assert_connection_success(server, cert_reqs=ssl.CERT_NONE, certfile=CLIENT_CERT, keyfile=CLIENT_KEY)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900274
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900275 def test_ciphers(self):
John Siroisac067042016-02-12 08:10:13 -0700276 server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT, ciphers=TEST_CIPHERS)
277 self._assert_connection_success(server, ca_certs=SERVER_CERT, ciphers=TEST_CIPHERS)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900278
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900279 if not TSSLSocket._has_ciphers:
280 # unittest.skip is not available for Python 2.6
281 print('skipping test_ciphers')
282 return
John Siroisac067042016-02-12 08:10:13 -0700283 server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT)
284 self._assert_connection_failure(server, ca_certs=SERVER_CERT, ciphers='NULL')
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900285
John Siroisac067042016-02-12 08:10:13 -0700286 server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT, ciphers=TEST_CIPHERS)
287 self._assert_connection_failure(server, ca_certs=SERVER_CERT, ciphers='NULL')
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900288
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900289 def test_ssl2_and_ssl3_disabled(self):
290 if not hasattr(ssl, 'PROTOCOL_SSLv3'):
291 print('PROTOCOL_SSLv3 is not available')
292 else:
John Siroisac067042016-02-12 08:10:13 -0700293 server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT)
294 self._assert_connection_failure(server, ca_certs=SERVER_CERT, ssl_version=ssl.PROTOCOL_SSLv3)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900295
John Siroisac067042016-02-12 08:10:13 -0700296 server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT, ssl_version=ssl.PROTOCOL_SSLv3)
297 self._assert_connection_failure(server, ca_certs=SERVER_CERT)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900298
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900299 if not hasattr(ssl, 'PROTOCOL_SSLv2'):
300 print('PROTOCOL_SSLv2 is not available')
301 else:
John Siroisac067042016-02-12 08:10:13 -0700302 server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT)
303 self._assert_connection_failure(server, ca_certs=SERVER_CERT, ssl_version=ssl.PROTOCOL_SSLv2)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900304
John Siroisac067042016-02-12 08:10:13 -0700305 server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT, ssl_version=ssl.PROTOCOL_SSLv2)
306 self._assert_connection_failure(server, ca_certs=SERVER_CERT)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900307
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900308 def test_newer_tls(self):
309 if not TSSLSocket._has_ssl_context:
310 # unittest.skip is not available for Python 2.6
311 print('skipping test_newer_tls')
312 return
313 if not hasattr(ssl, 'PROTOCOL_TLSv1_2'):
314 print('PROTOCOL_TLSv1_2 is not available')
315 else:
John Siroisac067042016-02-12 08:10:13 -0700316 server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT, ssl_version=ssl.PROTOCOL_TLSv1_2)
317 self._assert_connection_success(server, ca_certs=SERVER_CERT, ssl_version=ssl.PROTOCOL_TLSv1_2)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900318
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900319 if not hasattr(ssl, 'PROTOCOL_TLSv1_1'):
320 print('PROTOCOL_TLSv1_1 is not available')
321 else:
John Siroisac067042016-02-12 08:10:13 -0700322 server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT, ssl_version=ssl.PROTOCOL_TLSv1_1)
323 self._assert_connection_success(server, ca_certs=SERVER_CERT, ssl_version=ssl.PROTOCOL_TLSv1_1)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900324
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900325 if not hasattr(ssl, 'PROTOCOL_TLSv1_1') or not hasattr(ssl, 'PROTOCOL_TLSv1_2'):
326 print('PROTOCOL_TLSv1_1 and/or PROTOCOL_TLSv1_2 is not available')
327 else:
John Siroisac067042016-02-12 08:10:13 -0700328 server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT, ssl_version=ssl.PROTOCOL_TLSv1_2)
329 self._assert_connection_failure(server, ca_certs=SERVER_CERT, ssl_version=ssl.PROTOCOL_TLSv1_1)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900330
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900331 def test_ssl_context(self):
332 if not TSSLSocket._has_ssl_context:
333 # unittest.skip is not available for Python 2.6
334 print('skipping test_ssl_context')
335 return
336 server_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
337 server_context.load_cert_chain(SERVER_CERT, SERVER_KEY)
Nobuaki Sukegawaf39f7db2016-02-04 15:09:41 +0900338 server_context.load_verify_locations(CLIENT_CA)
339 server_context.verify_mode = ssl.CERT_REQUIRED
John Siroisac067042016-02-12 08:10:13 -0700340 server = self._server_socket(ssl_context=server_context)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900341
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900342 client_context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
343 client_context.load_cert_chain(CLIENT_CERT, CLIENT_KEY)
344 client_context.load_verify_locations(SERVER_CERT)
Nobuaki Sukegawaf39f7db2016-02-04 15:09:41 +0900345 client_context.verify_mode = ssl.CERT_REQUIRED
Nobuaki Sukegawaf39f7db2016-02-04 15:09:41 +0900346
John Siroisac067042016-02-12 08:10:13 -0700347 self._assert_connection_success(server, ssl_context=client_context)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900348
James E. King, III0ad20bd2017-09-30 15:44:16 -0700349
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900350if __name__ == '__main__':
Nobuaki Sukegawad2b4f242016-09-04 18:49:23 +0900351 logging.basicConfig(level=logging.WARN)
Nobuaki Sukegawae8ba7872017-02-12 21:14:48 +0900352 from thrift.transport.TSSLSocket import TSSLSocket, TSSLServerSocket, _match_has_ipaddress
Nobuaki Sukegawad2b4f242016-09-04 18:49:23 +0900353 from thrift.transport.TTransport import TTransportException
354
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900355 unittest.main()