blob: 2cbf5f8dde26ceb42dc3727a889c241585b93f9e [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
bwangelme0ed4a1d2024-04-15 12:17:40 +080022import time
Nobuaki Sukegawaad835862015-12-23 23:32:09 +090023import os
24import platform
Nobuaki Sukegawaad835862015-12-23 23:32:09 +090025import ssl
26import sys
John Siroisac067042016-02-12 08:10:13 -070027import tempfile
Nobuaki Sukegawaad835862015-12-23 23:32:09 +090028import threading
Nobuaki Sukegawaad835862015-12-23 23:32:09 +090029import unittest
30import warnings
John Siroisac067042016-02-12 08:10:13 -070031from contextlib import contextmanager
32
Nobuaki Sukegawa6a0ca7f2016-02-13 03:11:16 +090033import _import_local_thrift # noqa
Nobuaki Sukegawaad835862015-12-23 23:32:09 +090034
35SCRIPT_DIR = os.path.realpath(os.path.dirname(__file__))
36ROOT_DIR = os.path.dirname(os.path.dirname(os.path.dirname(SCRIPT_DIR)))
37SERVER_PEM = os.path.join(ROOT_DIR, 'test', 'keys', 'server.pem')
38SERVER_CERT = os.path.join(ROOT_DIR, 'test', 'keys', 'server.crt')
39SERVER_KEY = os.path.join(ROOT_DIR, 'test', 'keys', 'server.key')
Nobuaki Sukegawaf39f7db2016-02-04 15:09:41 +090040CLIENT_CERT_NO_IP = os.path.join(ROOT_DIR, 'test', 'keys', 'client.crt')
41CLIENT_KEY_NO_IP = os.path.join(ROOT_DIR, 'test', 'keys', 'client.key')
42CLIENT_CERT = os.path.join(ROOT_DIR, 'test', 'keys', 'client_v3.crt')
43CLIENT_KEY = os.path.join(ROOT_DIR, 'test', 'keys', 'client_v3.key')
44CLIENT_CA = os.path.join(ROOT_DIR, 'test', 'keys', 'CA.pem')
Nobuaki Sukegawaad835862015-12-23 23:32:09 +090045
Aki Sukegawaeb9f65b2018-06-03 19:15:53 +090046TEST_CIPHERS = 'DES-CBC3-SHA:ECDHE-RSA-AES128-GCM-SHA256'
Nobuaki Sukegawaad835862015-12-23 23:32:09 +090047
48
49class ServerAcceptor(threading.Thread):
Nobuaki Sukegawa66f50532016-02-14 21:47:38 +090050 def __init__(self, server, expect_failure=False):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090051 super(ServerAcceptor, self).__init__()
John Siroisac067042016-02-12 08:10:13 -070052 self.daemon = True
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090053 self._server = server
John Siroisac067042016-02-12 08:10:13 -070054 self._listening = threading.Event()
55 self._port = None
56 self._port_bound = threading.Event()
57 self._client = None
58 self._client_accepted = threading.Event()
Nobuaki Sukegawa66f50532016-02-14 21:47:38 +090059 self._expect_failure = expect_failure
60 frame = inspect.stack(3)[2]
61 self.name = frame[3]
62 del frame
Nobuaki Sukegawaad835862015-12-23 23:32:09 +090063
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090064 def run(self):
65 self._server.listen()
John Siroisac067042016-02-12 08:10:13 -070066 self._listening.set()
67
68 try:
69 address = self._server.handle.getsockname()
70 if len(address) > 1:
71 # AF_INET addresses are 2-tuples (host, port) and AF_INET6 are
72 # 4-tuples (host, port, ...), but in each case port is in the second slot.
73 self._port = address[1]
74 finally:
75 self._port_bound.set()
76
77 try:
78 self._client = self._server.accept()
James E. King III3131fe92019-07-02 14:21:05 -040079 if self._client:
bwangelme0ed4a1d2024-04-15 12:17:40 +080080 data = self._client.read(5) # hello/sleep
81 if data == b"sleep":
82 time.sleep(2)
James E. King III3131fe92019-07-02 14:21:05 -040083 self._client.write(b"there")
Nobuaki Sukegawa66f50532016-02-14 21:47:38 +090084 except Exception:
85 logging.exception('error on server side (%s):' % self.name)
86 if not self._expect_failure:
87 raise
John Siroisac067042016-02-12 08:10:13 -070088 finally:
89 self._client_accepted.set()
90
91 def await_listening(self):
92 self._listening.wait()
93
94 @property
95 def port(self):
96 self._port_bound.wait()
97 return self._port
98
99 @property
100 def client(self):
101 self._client_accepted.wait()
102 return self._client
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900103
Aki Sukegawaeb9f65b2018-06-03 19:15:53 +0900104 def close(self):
105 if self._client:
106 self._client.close()
107 self._server.close()
108
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900109
110# Python 2.6 compat
111class AssertRaises(object):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900112 def __init__(self, expected):
113 self._expected = expected
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900114
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900115 def __enter__(self):
116 pass
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900117
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900118 def __exit__(self, exc_type, exc_value, traceback):
119 if not exc_type or not issubclass(exc_type, self._expected):
120 raise Exception('fail')
121 return True
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900122
123
Jiayu Liu6f339002023-04-20 07:39:35 +0800124@unittest.skip("failing SSL test to be fixed in subsequent pull request")
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900125class TSSLSocketTest(unittest.TestCase):
John Siroisac067042016-02-12 08:10:13 -0700126 def _server_socket(self, **kwargs):
127 return TSSLServerSocket(port=0, **kwargs)
128
129 @contextmanager
Nobuaki Sukegawa66f50532016-02-14 21:47:38 +0900130 def _connectable_client(self, server, expect_failure=False, path=None, **client_kwargs):
131 acc = ServerAcceptor(server, expect_failure)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900132 try:
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900133 acc.start()
John Siroisac067042016-02-12 08:10:13 -0700134 acc.await_listening()
135
136 host, port = ('localhost', acc.port) if path is None else (None, None)
Nobuaki Sukegawa66f50532016-02-14 21:47:38 +0900137 client = TSSLSocket(host, port, unix_socket=path, **client_kwargs)
John Siroisac067042016-02-12 08:10:13 -0700138 yield acc, client
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900139 finally:
Aki Sukegawaeb9f65b2018-06-03 19:15:53 +0900140 acc.close()
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900141
John Siroisac067042016-02-12 08:10:13 -0700142 def _assert_connection_failure(self, server, path=None, **client_args):
Nobuaki Sukegawa66f50532016-02-14 21:47:38 +0900143 logging.disable(logging.CRITICAL)
Nobuaki Sukegawad2b4f242016-09-04 18:49:23 +0900144 try:
145 with self._connectable_client(server, True, path=path, **client_args) as (acc, client):
John Siroisac067042016-02-12 08:10:13 -0700146 # We need to wait for a connection failure, but not too long. 20ms is a tunable
147 # compromise between test speed and stability
148 client.setTimeout(20)
149 with self._assert_raises(TTransportException):
150 client.open()
James E. King III3131fe92019-07-02 14:21:05 -0400151 client.write(b"hello")
152 client.read(5) # b"there"
Nobuaki Sukegawad2b4f242016-09-04 18:49:23 +0900153 finally:
154 logging.disable(logging.NOTSET)
John Siroisac067042016-02-12 08:10:13 -0700155
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900156 def _assert_raises(self, exc):
157 if sys.hexversion >= 0x020700F0:
158 return self.assertRaises(exc)
159 else:
160 return AssertRaises(exc)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900161
John Siroisac067042016-02-12 08:10:13 -0700162 def _assert_connection_success(self, server, path=None, **client_args):
163 with self._connectable_client(server, path=path, **client_args) as (acc, client):
John Siroisac067042016-02-12 08:10:13 -0700164 try:
Michael Smithe3eb9af2022-06-08 17:23:27 -0700165 self.assertFalse(client.isOpen())
James E. King III3131fe92019-07-02 14:21:05 -0400166 client.open()
Michael Smithe3eb9af2022-06-08 17:23:27 -0700167 self.assertTrue(client.isOpen())
James E. King III3131fe92019-07-02 14:21:05 -0400168 client.write(b"hello")
169 self.assertEqual(client.read(5), b"there")
John Siroisac067042016-02-12 08:10:13 -0700170 self.assertTrue(acc.client is not None)
171 finally:
172 client.close()
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900173
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900174 # deprecated feature
175 def test_deprecation(self):
176 with warnings.catch_warnings(record=True) as w:
Nobuaki Sukegawa6a0ca7f2016-02-13 03:11:16 +0900177 warnings.filterwarnings('always', category=DeprecationWarning, module=self.__module__)
John Siroisac067042016-02-12 08:10:13 -0700178 TSSLSocket('localhost', 0, validate=True, ca_certs=SERVER_CERT)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900179 self.assertEqual(len(w), 1)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900180
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900181 with warnings.catch_warnings(record=True) as w:
Nobuaki Sukegawa6a0ca7f2016-02-13 03:11:16 +0900182 warnings.filterwarnings('always', category=DeprecationWarning, module=self.__module__)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900183 # Deprecated signature
184 # 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 +0900185 TSSLSocket('localhost', 0, True, SERVER_CERT, CLIENT_KEY, CLIENT_CERT, None, TEST_CIPHERS)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900186 self.assertEqual(len(w), 7)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900187
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900188 with warnings.catch_warnings(record=True) as w:
Nobuaki Sukegawa6a0ca7f2016-02-13 03:11:16 +0900189 warnings.filterwarnings('always', category=DeprecationWarning, module=self.__module__)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900190 # Deprecated signature
191 # def __init__(self, host=None, port=9090, certfile='cert.pem', unix_socket=None, ciphers=None):
Nobuaki Sukegawa6a0ca7f2016-02-13 03:11:16 +0900192 TSSLServerSocket(None, 0, SERVER_PEM, None, TEST_CIPHERS)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900193 self.assertEqual(len(w), 3)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900194
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900195 # deprecated feature
196 def test_set_cert_reqs_by_validate(self):
Nobuaki Sukegawa6a0ca7f2016-02-13 03:11:16 +0900197 with warnings.catch_warnings(record=True) as w:
198 warnings.filterwarnings('always', category=DeprecationWarning, module=self.__module__)
199 c1 = TSSLSocket('localhost', 0, validate=True, ca_certs=SERVER_CERT)
200 self.assertEqual(c1.cert_reqs, ssl.CERT_REQUIRED)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900201
Nobuaki Sukegawa6a0ca7f2016-02-13 03:11:16 +0900202 c1 = TSSLSocket('localhost', 0, validate=False)
203 self.assertEqual(c1.cert_reqs, ssl.CERT_NONE)
204
205 self.assertEqual(len(w), 2)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900206
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900207 # deprecated feature
208 def test_set_validate_by_cert_reqs(self):
Nobuaki Sukegawa6a0ca7f2016-02-13 03:11:16 +0900209 with warnings.catch_warnings(record=True) as w:
210 warnings.filterwarnings('always', category=DeprecationWarning, module=self.__module__)
211 c1 = TSSLSocket('localhost', 0, cert_reqs=ssl.CERT_NONE)
212 self.assertFalse(c1.validate)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900213
Nobuaki Sukegawa6a0ca7f2016-02-13 03:11:16 +0900214 c2 = TSSLSocket('localhost', 0, cert_reqs=ssl.CERT_REQUIRED, ca_certs=SERVER_CERT)
215 self.assertTrue(c2.validate)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900216
Nobuaki Sukegawa6a0ca7f2016-02-13 03:11:16 +0900217 c3 = TSSLSocket('localhost', 0, cert_reqs=ssl.CERT_OPTIONAL, ca_certs=SERVER_CERT)
218 self.assertTrue(c3.validate)
219
220 self.assertEqual(len(w), 3)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900221
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900222 def test_unix_domain_socket(self):
223 if platform.system() == 'Windows':
224 print('skipping test_unix_domain_socket')
225 return
John Siroisac067042016-02-12 08:10:13 -0700226 fd, path = tempfile.mkstemp()
227 os.close(fd)
junnplusfe11c482019-01-12 02:15:05 +0800228 os.unlink(path)
John Siroisac067042016-02-12 08:10:13 -0700229 try:
230 server = self._server_socket(unix_socket=path, keyfile=SERVER_KEY, certfile=SERVER_CERT)
231 self._assert_connection_success(server, path=path, cert_reqs=ssl.CERT_NONE)
232 finally:
233 os.unlink(path)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900234
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900235 def test_server_cert(self):
John Siroisac067042016-02-12 08:10:13 -0700236 server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT)
237 self._assert_connection_success(server, cert_reqs=ssl.CERT_REQUIRED, ca_certs=SERVER_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 # server cert not in ca_certs
241 self._assert_connection_failure(server, cert_reqs=ssl.CERT_REQUIRED, ca_certs=CLIENT_CERT)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900242
John Siroisac067042016-02-12 08:10:13 -0700243 server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT)
244 self._assert_connection_success(server, cert_reqs=ssl.CERT_NONE)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900245
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900246 def test_set_server_cert(self):
John Siroisac067042016-02-12 08:10:13 -0700247 server = self._server_socket(keyfile=SERVER_KEY, certfile=CLIENT_CERT)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900248 with self._assert_raises(Exception):
249 server.certfile = 'foo'
250 with self._assert_raises(Exception):
251 server.certfile = None
252 server.certfile = SERVER_CERT
John Siroisac067042016-02-12 08:10:13 -0700253 self._assert_connection_success(server, cert_reqs=ssl.CERT_REQUIRED, ca_certs=SERVER_CERT)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900254
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900255 def test_client_cert(self):
Nobuaki Sukegawae8ba7872017-02-12 21:14:48 +0900256 if not _match_has_ipaddress:
257 print('skipping test_client_cert')
258 return
John Siroisac067042016-02-12 08:10:13 -0700259 server = self._server_socket(
260 cert_reqs=ssl.CERT_REQUIRED, keyfile=SERVER_KEY,
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900261 certfile=SERVER_CERT, ca_certs=CLIENT_CERT)
John Siroisac067042016-02-12 08:10:13 -0700262 self._assert_connection_failure(server, cert_reqs=ssl.CERT_NONE, certfile=SERVER_CERT, keyfile=SERVER_KEY)
Nobuaki Sukegawaf39f7db2016-02-04 15:09:41 +0900263
John Siroisac067042016-02-12 08:10:13 -0700264 server = self._server_socket(
265 cert_reqs=ssl.CERT_REQUIRED, keyfile=SERVER_KEY,
Nobuaki Sukegawaf39f7db2016-02-04 15:09:41 +0900266 certfile=SERVER_CERT, ca_certs=CLIENT_CA)
John Siroisac067042016-02-12 08:10:13 -0700267 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 +0900268
John Siroisac067042016-02-12 08:10:13 -0700269 server = self._server_socket(
270 cert_reqs=ssl.CERT_REQUIRED, keyfile=SERVER_KEY,
Nobuaki Sukegawaf39f7db2016-02-04 15:09:41 +0900271 certfile=SERVER_CERT, ca_certs=CLIENT_CA)
John Siroisac067042016-02-12 08:10:13 -0700272 self._assert_connection_success(server, cert_reqs=ssl.CERT_NONE, certfile=CLIENT_CERT, keyfile=CLIENT_KEY)
Nobuaki Sukegawaf39f7db2016-02-04 15:09:41 +0900273
John Siroisac067042016-02-12 08:10:13 -0700274 server = self._server_socket(
275 cert_reqs=ssl.CERT_OPTIONAL, keyfile=SERVER_KEY,
Nobuaki Sukegawaf39f7db2016-02-04 15:09:41 +0900276 certfile=SERVER_CERT, ca_certs=CLIENT_CA)
John Siroisac067042016-02-12 08:10:13 -0700277 self._assert_connection_success(server, cert_reqs=ssl.CERT_NONE, certfile=CLIENT_CERT, keyfile=CLIENT_KEY)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900278
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900279 def test_ciphers(self):
John Siroisac067042016-02-12 08:10:13 -0700280 server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT, ciphers=TEST_CIPHERS)
281 self._assert_connection_success(server, ca_certs=SERVER_CERT, ciphers=TEST_CIPHERS)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900282
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900283 if not TSSLSocket._has_ciphers:
284 # unittest.skip is not available for Python 2.6
285 print('skipping test_ciphers')
286 return
John Siroisac067042016-02-12 08:10:13 -0700287 server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT)
288 self._assert_connection_failure(server, ca_certs=SERVER_CERT, ciphers='NULL')
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900289
John Siroisac067042016-02-12 08:10:13 -0700290 server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT, ciphers=TEST_CIPHERS)
291 self._assert_connection_failure(server, ca_certs=SERVER_CERT, ciphers='NULL')
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900292
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900293 def test_ssl2_and_ssl3_disabled(self):
294 if not hasattr(ssl, 'PROTOCOL_SSLv3'):
295 print('PROTOCOL_SSLv3 is not available')
296 else:
John Siroisac067042016-02-12 08:10:13 -0700297 server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT)
298 self._assert_connection_failure(server, ca_certs=SERVER_CERT, ssl_version=ssl.PROTOCOL_SSLv3)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900299
John Siroisac067042016-02-12 08:10:13 -0700300 server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT, ssl_version=ssl.PROTOCOL_SSLv3)
301 self._assert_connection_failure(server, ca_certs=SERVER_CERT)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900302
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900303 if not hasattr(ssl, 'PROTOCOL_SSLv2'):
304 print('PROTOCOL_SSLv2 is not available')
305 else:
John Siroisac067042016-02-12 08:10:13 -0700306 server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT)
307 self._assert_connection_failure(server, ca_certs=SERVER_CERT, ssl_version=ssl.PROTOCOL_SSLv2)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900308
John Siroisac067042016-02-12 08:10:13 -0700309 server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT, ssl_version=ssl.PROTOCOL_SSLv2)
310 self._assert_connection_failure(server, ca_certs=SERVER_CERT)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900311
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900312 def test_newer_tls(self):
313 if not TSSLSocket._has_ssl_context:
314 # unittest.skip is not available for Python 2.6
315 print('skipping test_newer_tls')
316 return
317 if not hasattr(ssl, 'PROTOCOL_TLSv1_2'):
318 print('PROTOCOL_TLSv1_2 is not available')
319 else:
John Siroisac067042016-02-12 08:10:13 -0700320 server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT, ssl_version=ssl.PROTOCOL_TLSv1_2)
321 self._assert_connection_success(server, ca_certs=SERVER_CERT, ssl_version=ssl.PROTOCOL_TLSv1_2)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900322
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900323 if not hasattr(ssl, 'PROTOCOL_TLSv1_1'):
324 print('PROTOCOL_TLSv1_1 is not available')
325 else:
John Siroisac067042016-02-12 08:10:13 -0700326 server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT, ssl_version=ssl.PROTOCOL_TLSv1_1)
327 self._assert_connection_success(server, ca_certs=SERVER_CERT, ssl_version=ssl.PROTOCOL_TLSv1_1)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900328
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900329 if not hasattr(ssl, 'PROTOCOL_TLSv1_1') or not hasattr(ssl, 'PROTOCOL_TLSv1_2'):
330 print('PROTOCOL_TLSv1_1 and/or PROTOCOL_TLSv1_2 is not available')
331 else:
John Siroisac067042016-02-12 08:10:13 -0700332 server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT, ssl_version=ssl.PROTOCOL_TLSv1_2)
333 self._assert_connection_failure(server, ca_certs=SERVER_CERT, ssl_version=ssl.PROTOCOL_TLSv1_1)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900334
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900335 def test_ssl_context(self):
336 if not TSSLSocket._has_ssl_context:
337 # unittest.skip is not available for Python 2.6
338 print('skipping test_ssl_context')
339 return
340 server_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
341 server_context.load_cert_chain(SERVER_CERT, SERVER_KEY)
Nobuaki Sukegawaf39f7db2016-02-04 15:09:41 +0900342 server_context.load_verify_locations(CLIENT_CA)
343 server_context.verify_mode = ssl.CERT_REQUIRED
John Siroisac067042016-02-12 08:10:13 -0700344 server = self._server_socket(ssl_context=server_context)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900345
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900346 client_context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
347 client_context.load_cert_chain(CLIENT_CERT, CLIENT_KEY)
348 client_context.load_verify_locations(SERVER_CERT)
Nobuaki Sukegawaf39f7db2016-02-04 15:09:41 +0900349 client_context.verify_mode = ssl.CERT_REQUIRED
Nobuaki Sukegawaf39f7db2016-02-04 15:09:41 +0900350
John Siroisac067042016-02-12 08:10:13 -0700351 self._assert_connection_success(server, ssl_context=client_context)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900352
James E. King, III0ad20bd2017-09-30 15:44:16 -0700353
Yuxuan 'fishy' Wangbe1c8fd2024-01-02 09:04:19 -0800354# Add a dummy test because starting from python 3.12, if all tests in a test
355# file are skipped that's considered an error.
356class DummyTest(unittest.TestCase):
357 def test_dummy(self):
358 self.assertEqual(0, 0)
359
360
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900361if __name__ == '__main__':
Nobuaki Sukegawad2b4f242016-09-04 18:49:23 +0900362 logging.basicConfig(level=logging.WARN)
Nobuaki Sukegawae8ba7872017-02-12 21:14:48 +0900363 from thrift.transport.TSSLSocket import TSSLSocket, TSSLServerSocket, _match_has_ipaddress
Nobuaki Sukegawad2b4f242016-09-04 18:49:23 +0900364 from thrift.transport.TTransport import TTransportException
365
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900366 unittest.main()