Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 1 | # |
| 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 Sukegawa | 66f5053 | 2016-02-14 21:47:38 +0900 | [diff] [blame] | 20 | import inspect |
Nobuaki Sukegawa | 355116e | 2016-02-11 18:01:20 +0900 | [diff] [blame] | 21 | import logging |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 22 | import os |
| 23 | import platform |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 24 | import ssl |
| 25 | import sys |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 26 | import tempfile |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 27 | import threading |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 28 | import unittest |
| 29 | import warnings |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 30 | from contextlib import contextmanager |
| 31 | |
Nobuaki Sukegawa | 6a0ca7f | 2016-02-13 03:11:16 +0900 | [diff] [blame] | 32 | import _import_local_thrift # noqa |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 33 | |
| 34 | SCRIPT_DIR = os.path.realpath(os.path.dirname(__file__)) |
| 35 | ROOT_DIR = os.path.dirname(os.path.dirname(os.path.dirname(SCRIPT_DIR))) |
| 36 | SERVER_PEM = os.path.join(ROOT_DIR, 'test', 'keys', 'server.pem') |
| 37 | SERVER_CERT = os.path.join(ROOT_DIR, 'test', 'keys', 'server.crt') |
| 38 | SERVER_KEY = os.path.join(ROOT_DIR, 'test', 'keys', 'server.key') |
Nobuaki Sukegawa | f39f7db | 2016-02-04 15:09:41 +0900 | [diff] [blame] | 39 | CLIENT_CERT_NO_IP = os.path.join(ROOT_DIR, 'test', 'keys', 'client.crt') |
| 40 | CLIENT_KEY_NO_IP = os.path.join(ROOT_DIR, 'test', 'keys', 'client.key') |
| 41 | CLIENT_CERT = os.path.join(ROOT_DIR, 'test', 'keys', 'client_v3.crt') |
| 42 | CLIENT_KEY = os.path.join(ROOT_DIR, 'test', 'keys', 'client_v3.key') |
| 43 | CLIENT_CA = os.path.join(ROOT_DIR, 'test', 'keys', 'CA.pem') |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 44 | |
Aki Sukegawa | eb9f65b | 2018-06-03 19:15:53 +0900 | [diff] [blame] | 45 | TEST_CIPHERS = 'DES-CBC3-SHA:ECDHE-RSA-AES128-GCM-SHA256' |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 46 | |
| 47 | |
| 48 | class ServerAcceptor(threading.Thread): |
Nobuaki Sukegawa | 66f5053 | 2016-02-14 21:47:38 +0900 | [diff] [blame] | 49 | def __init__(self, server, expect_failure=False): |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 50 | super(ServerAcceptor, self).__init__() |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 51 | self.daemon = True |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 52 | self._server = server |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 53 | 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 Sukegawa | 66f5053 | 2016-02-14 21:47:38 +0900 | [diff] [blame] | 58 | self._expect_failure = expect_failure |
| 59 | frame = inspect.stack(3)[2] |
| 60 | self.name = frame[3] |
| 61 | del frame |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 62 | |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 63 | def run(self): |
| 64 | self._server.listen() |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 65 | 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() |
Nobuaki Sukegawa | 66f5053 | 2016-02-14 21:47:38 +0900 | [diff] [blame] | 78 | except Exception: |
| 79 | logging.exception('error on server side (%s):' % self.name) |
| 80 | if not self._expect_failure: |
| 81 | raise |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 82 | finally: |
| 83 | self._client_accepted.set() |
| 84 | |
| 85 | def await_listening(self): |
| 86 | self._listening.wait() |
| 87 | |
| 88 | @property |
| 89 | def port(self): |
| 90 | self._port_bound.wait() |
| 91 | return self._port |
| 92 | |
| 93 | @property |
| 94 | def client(self): |
| 95 | self._client_accepted.wait() |
| 96 | return self._client |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 97 | |
Aki Sukegawa | eb9f65b | 2018-06-03 19:15:53 +0900 | [diff] [blame] | 98 | def close(self): |
| 99 | if self._client: |
| 100 | self._client.close() |
| 101 | self._server.close() |
| 102 | |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 103 | |
| 104 | # Python 2.6 compat |
| 105 | class AssertRaises(object): |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 106 | def __init__(self, expected): |
| 107 | self._expected = expected |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 108 | |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 109 | def __enter__(self): |
| 110 | pass |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 111 | |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 112 | def __exit__(self, exc_type, exc_value, traceback): |
| 113 | if not exc_type or not issubclass(exc_type, self._expected): |
| 114 | raise Exception('fail') |
| 115 | return True |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 116 | |
| 117 | |
| 118 | class TSSLSocketTest(unittest.TestCase): |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 119 | def _server_socket(self, **kwargs): |
| 120 | return TSSLServerSocket(port=0, **kwargs) |
| 121 | |
| 122 | @contextmanager |
Nobuaki Sukegawa | 66f5053 | 2016-02-14 21:47:38 +0900 | [diff] [blame] | 123 | def _connectable_client(self, server, expect_failure=False, path=None, **client_kwargs): |
| 124 | acc = ServerAcceptor(server, expect_failure) |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 125 | try: |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 126 | acc.start() |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 127 | acc.await_listening() |
| 128 | |
| 129 | host, port = ('localhost', acc.port) if path is None else (None, None) |
Nobuaki Sukegawa | 66f5053 | 2016-02-14 21:47:38 +0900 | [diff] [blame] | 130 | client = TSSLSocket(host, port, unix_socket=path, **client_kwargs) |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 131 | yield acc, client |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 132 | finally: |
Aki Sukegawa | eb9f65b | 2018-06-03 19:15:53 +0900 | [diff] [blame] | 133 | acc.close() |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 134 | |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 135 | def _assert_connection_failure(self, server, path=None, **client_args): |
Nobuaki Sukegawa | 66f5053 | 2016-02-14 21:47:38 +0900 | [diff] [blame] | 136 | logging.disable(logging.CRITICAL) |
Nobuaki Sukegawa | d2b4f24 | 2016-09-04 18:49:23 +0900 | [diff] [blame] | 137 | try: |
| 138 | with self._connectable_client(server, True, path=path, **client_args) as (acc, client): |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 139 | # We need to wait for a connection failure, but not too long. 20ms is a tunable |
| 140 | # compromise between test speed and stability |
| 141 | client.setTimeout(20) |
| 142 | with self._assert_raises(TTransportException): |
| 143 | client.open() |
| 144 | self.assertTrue(acc.client is None) |
Nobuaki Sukegawa | d2b4f24 | 2016-09-04 18:49:23 +0900 | [diff] [blame] | 145 | finally: |
| 146 | logging.disable(logging.NOTSET) |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 147 | |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 148 | def _assert_raises(self, exc): |
| 149 | if sys.hexversion >= 0x020700F0: |
| 150 | return self.assertRaises(exc) |
| 151 | else: |
| 152 | return AssertRaises(exc) |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 153 | |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 154 | def _assert_connection_success(self, server, path=None, **client_args): |
| 155 | with self._connectable_client(server, path=path, **client_args) as (acc, client): |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 156 | client.open() |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 157 | try: |
| 158 | self.assertTrue(acc.client is not None) |
| 159 | finally: |
| 160 | client.close() |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 161 | |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 162 | # deprecated feature |
| 163 | def test_deprecation(self): |
| 164 | with warnings.catch_warnings(record=True) as w: |
Nobuaki Sukegawa | 6a0ca7f | 2016-02-13 03:11:16 +0900 | [diff] [blame] | 165 | warnings.filterwarnings('always', category=DeprecationWarning, module=self.__module__) |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 166 | TSSLSocket('localhost', 0, validate=True, ca_certs=SERVER_CERT) |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 167 | self.assertEqual(len(w), 1) |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 168 | |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 169 | with warnings.catch_warnings(record=True) as w: |
Nobuaki Sukegawa | 6a0ca7f | 2016-02-13 03:11:16 +0900 | [diff] [blame] | 170 | warnings.filterwarnings('always', category=DeprecationWarning, module=self.__module__) |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 171 | # Deprecated signature |
| 172 | # def __init__(self, host='localhost', port=9090, validate=True, ca_certs=None, keyfile=None, certfile=None, unix_socket=None, ciphers=None): |
Nobuaki Sukegawa | 6a0ca7f | 2016-02-13 03:11:16 +0900 | [diff] [blame] | 173 | TSSLSocket('localhost', 0, True, SERVER_CERT, CLIENT_KEY, CLIENT_CERT, None, TEST_CIPHERS) |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 174 | self.assertEqual(len(w), 7) |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 175 | |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 176 | with warnings.catch_warnings(record=True) as w: |
Nobuaki Sukegawa | 6a0ca7f | 2016-02-13 03:11:16 +0900 | [diff] [blame] | 177 | warnings.filterwarnings('always', category=DeprecationWarning, module=self.__module__) |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 178 | # Deprecated signature |
| 179 | # def __init__(self, host=None, port=9090, certfile='cert.pem', unix_socket=None, ciphers=None): |
Nobuaki Sukegawa | 6a0ca7f | 2016-02-13 03:11:16 +0900 | [diff] [blame] | 180 | TSSLServerSocket(None, 0, SERVER_PEM, None, TEST_CIPHERS) |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 181 | self.assertEqual(len(w), 3) |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 182 | |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 183 | # deprecated feature |
| 184 | def test_set_cert_reqs_by_validate(self): |
Nobuaki Sukegawa | 6a0ca7f | 2016-02-13 03:11:16 +0900 | [diff] [blame] | 185 | with warnings.catch_warnings(record=True) as w: |
| 186 | warnings.filterwarnings('always', category=DeprecationWarning, module=self.__module__) |
| 187 | c1 = TSSLSocket('localhost', 0, validate=True, ca_certs=SERVER_CERT) |
| 188 | self.assertEqual(c1.cert_reqs, ssl.CERT_REQUIRED) |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 189 | |
Nobuaki Sukegawa | 6a0ca7f | 2016-02-13 03:11:16 +0900 | [diff] [blame] | 190 | c1 = TSSLSocket('localhost', 0, validate=False) |
| 191 | self.assertEqual(c1.cert_reqs, ssl.CERT_NONE) |
| 192 | |
| 193 | self.assertEqual(len(w), 2) |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 194 | |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 195 | # deprecated feature |
| 196 | def test_set_validate_by_cert_reqs(self): |
Nobuaki Sukegawa | 6a0ca7f | 2016-02-13 03:11:16 +0900 | [diff] [blame] | 197 | with warnings.catch_warnings(record=True) as w: |
| 198 | warnings.filterwarnings('always', category=DeprecationWarning, module=self.__module__) |
| 199 | c1 = TSSLSocket('localhost', 0, cert_reqs=ssl.CERT_NONE) |
| 200 | self.assertFalse(c1.validate) |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 201 | |
Nobuaki Sukegawa | 6a0ca7f | 2016-02-13 03:11:16 +0900 | [diff] [blame] | 202 | c2 = TSSLSocket('localhost', 0, cert_reqs=ssl.CERT_REQUIRED, ca_certs=SERVER_CERT) |
| 203 | self.assertTrue(c2.validate) |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 204 | |
Nobuaki Sukegawa | 6a0ca7f | 2016-02-13 03:11:16 +0900 | [diff] [blame] | 205 | c3 = TSSLSocket('localhost', 0, cert_reqs=ssl.CERT_OPTIONAL, ca_certs=SERVER_CERT) |
| 206 | self.assertTrue(c3.validate) |
| 207 | |
| 208 | self.assertEqual(len(w), 3) |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 209 | |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 210 | def test_unix_domain_socket(self): |
| 211 | if platform.system() == 'Windows': |
| 212 | print('skipping test_unix_domain_socket') |
| 213 | return |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 214 | fd, path = tempfile.mkstemp() |
| 215 | os.close(fd) |
junnplus | fe11c48 | 2019-01-12 02:15:05 +0800 | [diff] [blame^] | 216 | os.unlink(path) |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 217 | try: |
| 218 | server = self._server_socket(unix_socket=path, keyfile=SERVER_KEY, certfile=SERVER_CERT) |
| 219 | self._assert_connection_success(server, path=path, cert_reqs=ssl.CERT_NONE) |
| 220 | finally: |
| 221 | os.unlink(path) |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 222 | |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 223 | def test_server_cert(self): |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 224 | server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT) |
| 225 | self._assert_connection_success(server, cert_reqs=ssl.CERT_REQUIRED, ca_certs=SERVER_CERT) |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 226 | |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 227 | server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT) |
| 228 | # server cert not in ca_certs |
| 229 | self._assert_connection_failure(server, cert_reqs=ssl.CERT_REQUIRED, ca_certs=CLIENT_CERT) |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 230 | |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 231 | server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT) |
| 232 | self._assert_connection_success(server, cert_reqs=ssl.CERT_NONE) |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 233 | |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 234 | def test_set_server_cert(self): |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 235 | server = self._server_socket(keyfile=SERVER_KEY, certfile=CLIENT_CERT) |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 236 | with self._assert_raises(Exception): |
| 237 | server.certfile = 'foo' |
| 238 | with self._assert_raises(Exception): |
| 239 | server.certfile = None |
| 240 | server.certfile = SERVER_CERT |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 241 | self._assert_connection_success(server, cert_reqs=ssl.CERT_REQUIRED, ca_certs=SERVER_CERT) |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 242 | |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 243 | def test_client_cert(self): |
Nobuaki Sukegawa | e8ba787 | 2017-02-12 21:14:48 +0900 | [diff] [blame] | 244 | if not _match_has_ipaddress: |
| 245 | print('skipping test_client_cert') |
| 246 | return |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 247 | server = self._server_socket( |
| 248 | cert_reqs=ssl.CERT_REQUIRED, keyfile=SERVER_KEY, |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 249 | certfile=SERVER_CERT, ca_certs=CLIENT_CERT) |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 250 | self._assert_connection_failure(server, cert_reqs=ssl.CERT_NONE, certfile=SERVER_CERT, keyfile=SERVER_KEY) |
Nobuaki Sukegawa | f39f7db | 2016-02-04 15:09:41 +0900 | [diff] [blame] | 251 | |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 252 | server = self._server_socket( |
| 253 | cert_reqs=ssl.CERT_REQUIRED, keyfile=SERVER_KEY, |
Nobuaki Sukegawa | f39f7db | 2016-02-04 15:09:41 +0900 | [diff] [blame] | 254 | certfile=SERVER_CERT, ca_certs=CLIENT_CA) |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 255 | self._assert_connection_failure(server, cert_reqs=ssl.CERT_NONE, certfile=CLIENT_CERT_NO_IP, keyfile=CLIENT_KEY_NO_IP) |
Nobuaki Sukegawa | f39f7db | 2016-02-04 15:09:41 +0900 | [diff] [blame] | 256 | |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 257 | server = self._server_socket( |
| 258 | cert_reqs=ssl.CERT_REQUIRED, keyfile=SERVER_KEY, |
Nobuaki Sukegawa | f39f7db | 2016-02-04 15:09:41 +0900 | [diff] [blame] | 259 | certfile=SERVER_CERT, ca_certs=CLIENT_CA) |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 260 | self._assert_connection_success(server, cert_reqs=ssl.CERT_NONE, certfile=CLIENT_CERT, keyfile=CLIENT_KEY) |
Nobuaki Sukegawa | f39f7db | 2016-02-04 15:09:41 +0900 | [diff] [blame] | 261 | |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 262 | server = self._server_socket( |
| 263 | cert_reqs=ssl.CERT_OPTIONAL, keyfile=SERVER_KEY, |
Nobuaki Sukegawa | f39f7db | 2016-02-04 15:09:41 +0900 | [diff] [blame] | 264 | certfile=SERVER_CERT, ca_certs=CLIENT_CA) |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 265 | self._assert_connection_success(server, cert_reqs=ssl.CERT_NONE, certfile=CLIENT_CERT, keyfile=CLIENT_KEY) |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 266 | |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 267 | def test_ciphers(self): |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 268 | server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT, ciphers=TEST_CIPHERS) |
| 269 | self._assert_connection_success(server, ca_certs=SERVER_CERT, ciphers=TEST_CIPHERS) |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 270 | |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 271 | if not TSSLSocket._has_ciphers: |
| 272 | # unittest.skip is not available for Python 2.6 |
| 273 | print('skipping test_ciphers') |
| 274 | return |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 275 | server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT) |
| 276 | self._assert_connection_failure(server, ca_certs=SERVER_CERT, ciphers='NULL') |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 277 | |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 278 | server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT, ciphers=TEST_CIPHERS) |
| 279 | self._assert_connection_failure(server, ca_certs=SERVER_CERT, ciphers='NULL') |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 280 | |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 281 | def test_ssl2_and_ssl3_disabled(self): |
| 282 | if not hasattr(ssl, 'PROTOCOL_SSLv3'): |
| 283 | print('PROTOCOL_SSLv3 is not available') |
| 284 | else: |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 285 | server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT) |
| 286 | self._assert_connection_failure(server, ca_certs=SERVER_CERT, ssl_version=ssl.PROTOCOL_SSLv3) |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 287 | |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 288 | server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT, ssl_version=ssl.PROTOCOL_SSLv3) |
| 289 | self._assert_connection_failure(server, ca_certs=SERVER_CERT) |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 290 | |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 291 | if not hasattr(ssl, 'PROTOCOL_SSLv2'): |
| 292 | print('PROTOCOL_SSLv2 is not available') |
| 293 | else: |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 294 | server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT) |
| 295 | self._assert_connection_failure(server, ca_certs=SERVER_CERT, ssl_version=ssl.PROTOCOL_SSLv2) |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 296 | |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 297 | server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT, ssl_version=ssl.PROTOCOL_SSLv2) |
| 298 | self._assert_connection_failure(server, ca_certs=SERVER_CERT) |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 299 | |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 300 | def test_newer_tls(self): |
| 301 | if not TSSLSocket._has_ssl_context: |
| 302 | # unittest.skip is not available for Python 2.6 |
| 303 | print('skipping test_newer_tls') |
| 304 | return |
| 305 | if not hasattr(ssl, 'PROTOCOL_TLSv1_2'): |
| 306 | print('PROTOCOL_TLSv1_2 is not available') |
| 307 | else: |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 308 | server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT, ssl_version=ssl.PROTOCOL_TLSv1_2) |
| 309 | self._assert_connection_success(server, ca_certs=SERVER_CERT, ssl_version=ssl.PROTOCOL_TLSv1_2) |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 310 | |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 311 | if not hasattr(ssl, 'PROTOCOL_TLSv1_1'): |
| 312 | print('PROTOCOL_TLSv1_1 is not available') |
| 313 | else: |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 314 | server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT, ssl_version=ssl.PROTOCOL_TLSv1_1) |
| 315 | self._assert_connection_success(server, ca_certs=SERVER_CERT, ssl_version=ssl.PROTOCOL_TLSv1_1) |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 316 | |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 317 | if not hasattr(ssl, 'PROTOCOL_TLSv1_1') or not hasattr(ssl, 'PROTOCOL_TLSv1_2'): |
| 318 | print('PROTOCOL_TLSv1_1 and/or PROTOCOL_TLSv1_2 is not available') |
| 319 | else: |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 320 | server = self._server_socket(keyfile=SERVER_KEY, certfile=SERVER_CERT, ssl_version=ssl.PROTOCOL_TLSv1_2) |
| 321 | self._assert_connection_failure(server, ca_certs=SERVER_CERT, ssl_version=ssl.PROTOCOL_TLSv1_1) |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 322 | |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 323 | def test_ssl_context(self): |
| 324 | if not TSSLSocket._has_ssl_context: |
| 325 | # unittest.skip is not available for Python 2.6 |
| 326 | print('skipping test_ssl_context') |
| 327 | return |
| 328 | server_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) |
| 329 | server_context.load_cert_chain(SERVER_CERT, SERVER_KEY) |
Nobuaki Sukegawa | f39f7db | 2016-02-04 15:09:41 +0900 | [diff] [blame] | 330 | server_context.load_verify_locations(CLIENT_CA) |
| 331 | server_context.verify_mode = ssl.CERT_REQUIRED |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 332 | server = self._server_socket(ssl_context=server_context) |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 333 | |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 334 | client_context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH) |
| 335 | client_context.load_cert_chain(CLIENT_CERT, CLIENT_KEY) |
| 336 | client_context.load_verify_locations(SERVER_CERT) |
Nobuaki Sukegawa | f39f7db | 2016-02-04 15:09:41 +0900 | [diff] [blame] | 337 | client_context.verify_mode = ssl.CERT_REQUIRED |
Nobuaki Sukegawa | f39f7db | 2016-02-04 15:09:41 +0900 | [diff] [blame] | 338 | |
John Sirois | ac06704 | 2016-02-12 08:10:13 -0700 | [diff] [blame] | 339 | self._assert_connection_success(server, ssl_context=client_context) |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 340 | |
James E. King, III | 0ad20bd | 2017-09-30 15:44:16 -0700 | [diff] [blame] | 341 | |
Nobuaki Sukegawa | ad83586 | 2015-12-23 23:32:09 +0900 | [diff] [blame] | 342 | if __name__ == '__main__': |
Nobuaki Sukegawa | d2b4f24 | 2016-09-04 18:49:23 +0900 | [diff] [blame] | 343 | logging.basicConfig(level=logging.WARN) |
Nobuaki Sukegawa | e8ba787 | 2017-02-12 21:14:48 +0900 | [diff] [blame] | 344 | from thrift.transport.TSSLSocket import TSSLSocket, TSSLServerSocket, _match_has_ipaddress |
Nobuaki Sukegawa | d2b4f24 | 2016-09-04 18:49:23 +0900 | [diff] [blame] | 345 | from thrift.transport.TTransport import TTransportException |
| 346 | |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 347 | unittest.main() |