blob: b54ca5dd9c294257c45e19cb41b1f8d3fb37a62a [file] [log] [blame]
Bryan Duxbury50409112011-03-21 17:59:49 +00001#
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#
Bryan Duxbury69720412012-01-03 17:32:30 +000019
Nobuaki Sukegawaad835862015-12-23 23:32:09 +090020import logging
Bryan Duxbury50409112011-03-21 17:59:49 +000021import os
22import socket
23import ssl
Nobuaki Sukegawaad835862015-12-23 23:32:09 +090024import sys
25import warnings
Bryan Duxbury2b969ad2011-02-22 18:20:53 +000026
Nobuaki Sukegawaf32bae72016-02-20 08:51:33 +090027from .sslcompat import _match_hostname, _match_has_ipaddress
Bryan Duxbury2b969ad2011-02-22 18:20:53 +000028from thrift.transport import TSocket
Bryan Duxbury50409112011-03-21 17:59:49 +000029from thrift.transport.TTransport import TTransportException
Bryan Duxbury2b969ad2011-02-22 18:20:53 +000030
Nobuaki Sukegawaad835862015-12-23 23:32:09 +090031logger = logging.getLogger(__name__)
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +090032warnings.filterwarnings(
33 'default', category=DeprecationWarning, module=__name__)
Bryan Duxbury69720412012-01-03 17:32:30 +000034
Nobuaki Sukegawaad835862015-12-23 23:32:09 +090035
36class TSSLBase(object):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090037 # SSLContext is not available for Python < 2.7.9
38 _has_ssl_context = sys.hexversion >= 0x020709F0
Nobuaki Sukegawaad835862015-12-23 23:32:09 +090039
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090040 # ciphers argument is not available for Python < 2.7.0
41 _has_ciphers = sys.hexversion >= 0x020700F0
Nobuaki Sukegawaad835862015-12-23 23:32:09 +090042
James E. King, III36628a22017-02-13 15:25:41 -050043 # For python >= 2.7.9, use latest TLS that both client and server
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +090044 # supports.
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090045 # SSL 2.0 and 3.0 are disabled via ssl.OP_NO_SSLv2 and ssl.OP_NO_SSLv3.
James E. King, III36628a22017-02-13 15:25:41 -050046 # For python < 2.7.9, use TLS 1.0 since TLSv1_X nor OP_NO_SSLvX is
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +090047 # unavailable.
48 _default_protocol = ssl.PROTOCOL_SSLv23 if _has_ssl_context else \
49 ssl.PROTOCOL_TLSv1
Nobuaki Sukegawaad835862015-12-23 23:32:09 +090050
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090051 def _init_context(self, ssl_version):
52 if self._has_ssl_context:
53 self._context = ssl.SSLContext(ssl_version)
54 if self._context.protocol == ssl.PROTOCOL_SSLv23:
55 self._context.options |= ssl.OP_NO_SSLv2
56 self._context.options |= ssl.OP_NO_SSLv3
57 else:
58 self._context = None
59 self._ssl_version = ssl_version
Nobuaki Sukegawaad835862015-12-23 23:32:09 +090060
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090061 @property
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +090062 def _should_verify(self):
63 if self._has_ssl_context:
64 return self._context.verify_mode != ssl.CERT_NONE
65 else:
66 return self.cert_reqs != ssl.CERT_NONE
67
68 @property
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090069 def ssl_version(self):
70 if self._has_ssl_context:
71 return self.ssl_context.protocol
72 else:
73 return self._ssl_version
Nobuaki Sukegawaad835862015-12-23 23:32:09 +090074
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090075 @property
76 def ssl_context(self):
77 return self._context
Nobuaki Sukegawaad835862015-12-23 23:32:09 +090078
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090079 SSL_VERSION = _default_protocol
80 """
Nobuaki Sukegawaad835862015-12-23 23:32:09 +090081 Default SSL version.
82 For backword compatibility, it can be modified.
83 Use __init__ keywoard argument "ssl_version" instead.
84 """
85
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090086 def _deprecated_arg(self, args, kwargs, pos, key):
87 if len(args) <= pos:
88 return
89 real_pos = pos + 3
90 warnings.warn(
Nobuaki Sukegawa6a0ca7f2016-02-13 03:11:16 +090091 '%dth positional argument is deprecated.'
92 'please use keyward argument insteand.'
93 % real_pos, DeprecationWarning, stacklevel=3)
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +090094
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090095 if key in kwargs:
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +090096 raise TypeError(
97 'Duplicate argument: %dth argument and %s keyward argument.'
98 % (real_pos, key))
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090099 kwargs[key] = args[pos]
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900100
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900101 def _unix_socket_arg(self, host, port, args, kwargs):
102 key = 'unix_socket'
103 if host is None and port is None and len(args) == 1 and key not in kwargs:
104 kwargs[key] = args[0]
105 return True
106 return False
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900107
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900108 def __getattr__(self, key):
109 if key == 'SSL_VERSION':
Nobuaki Sukegawa6a0ca7f2016-02-13 03:11:16 +0900110 warnings.warn(
111 'SSL_VERSION is deprecated.'
112 'please use ssl_version attribute instead.',
113 DeprecationWarning, stacklevel=2)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900114 return self.ssl_version
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900115
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900116 def __init__(self, server_side, host, ssl_opts):
117 self._server_side = server_side
118 if TSSLBase.SSL_VERSION != self._default_protocol:
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900119 warnings.warn(
Nobuaki Sukegawa6a0ca7f2016-02-13 03:11:16 +0900120 'SSL_VERSION is deprecated.'
121 'please use ssl_version keyward argument instead.',
122 DeprecationWarning, stacklevel=2)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900123 self._context = ssl_opts.pop('ssl_context', None)
124 self._server_hostname = None
125 if not self._server_side:
126 self._server_hostname = ssl_opts.pop('server_hostname', host)
127 if self._context:
128 self._custom_context = True
129 if ssl_opts:
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900130 raise ValueError(
131 'Incompatible arguments: ssl_context and %s'
132 % ' '.join(ssl_opts.keys()))
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900133 if not self._has_ssl_context:
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900134 raise ValueError(
135 'ssl_context is not available for this version of Python')
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900136 else:
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900137 self._custom_context = False
138 ssl_version = ssl_opts.pop('ssl_version', TSSLBase.SSL_VERSION)
139 self._init_context(ssl_version)
140 self.cert_reqs = ssl_opts.pop('cert_reqs', ssl.CERT_REQUIRED)
141 self.ca_certs = ssl_opts.pop('ca_certs', None)
142 self.keyfile = ssl_opts.pop('keyfile', None)
143 self.certfile = ssl_opts.pop('certfile', None)
144 self.ciphers = ssl_opts.pop('ciphers', None)
145
146 if ssl_opts:
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900147 raise ValueError(
148 'Unknown keyword arguments: ', ' '.join(ssl_opts.keys()))
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900149
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900150 if self._should_verify:
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900151 if not self.ca_certs:
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900152 raise ValueError(
153 'ca_certs is needed when cert_reqs is not ssl.CERT_NONE')
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900154 if not os.access(self.ca_certs, os.R_OK):
155 raise IOError('Certificate Authority ca_certs file "%s" '
156 'is not readable, cannot validate SSL '
157 'certificates.' % (self.ca_certs))
158
159 @property
160 def certfile(self):
161 return self._certfile
162
163 @certfile.setter
164 def certfile(self, certfile):
165 if self._server_side and not certfile:
166 raise ValueError('certfile is needed for server-side')
167 if certfile and not os.access(certfile, os.R_OK):
168 raise IOError('No such certfile found: %s' % (certfile))
169 self._certfile = certfile
170
171 def _wrap_socket(self, sock):
172 if self._has_ssl_context:
173 if not self._custom_context:
174 self.ssl_context.verify_mode = self.cert_reqs
175 if self.certfile:
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900176 self.ssl_context.load_cert_chain(self.certfile,
177 self.keyfile)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900178 if self.ciphers:
179 self.ssl_context.set_ciphers(self.ciphers)
180 if self.ca_certs:
181 self.ssl_context.load_verify_locations(self.ca_certs)
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900182 return self.ssl_context.wrap_socket(
183 sock, server_side=self._server_side,
184 server_hostname=self._server_hostname)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900185 else:
186 ssl_opts = {
187 'ssl_version': self._ssl_version,
188 'server_side': self._server_side,
189 'ca_certs': self.ca_certs,
190 'keyfile': self.keyfile,
191 'certfile': self.certfile,
192 'cert_reqs': self.cert_reqs,
193 }
194 if self.ciphers:
195 if self._has_ciphers:
196 ssl_opts['ciphers'] = self.ciphers
197 else:
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900198 logger.warning(
199 'ciphers is specified but ignored due to old Python version')
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900200 return ssl.wrap_socket(sock, **ssl_opts)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900201
202
203class TSSLSocket(TSocket.TSocket, TSSLBase):
Bryan Duxbury50409112011-03-21 17:59:49 +0000204 """
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900205 SSL implementation of TSocket
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900206
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900207 This class creates outbound sockets wrapped using the
208 python standard ssl module for encrypted connections.
209 """
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900210
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900211 # New signature
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900212 # def __init__(self, host='localhost', port=9090, unix_socket=None,
213 # **ssl_args):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900214 # Deprecated signature
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900215 # def __init__(self, host='localhost', port=9090, validate=True,
216 # ca_certs=None, keyfile=None, certfile=None,
217 # unix_socket=None, ciphers=None):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900218 def __init__(self, host='localhost', port=9090, *args, **kwargs):
219 """Positional arguments: ``host``, ``port``, ``unix_socket``
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900220
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900221 Keyword arguments: ``keyfile``, ``certfile``, ``cert_reqs``,
222 ``ssl_version``, ``ca_certs``,
223 ``ciphers`` (Python 2.7.0 or later),
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900224 ``server_hostname`` (Python 2.7.9 or later)
225 Passed to ssl.wrap_socket. See ssl.wrap_socket documentation.
Bryan Duxbury50409112011-03-21 17:59:49 +0000226
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900227 Alternative keyword arguments: (Python 2.7.9 or later)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900228 ``ssl_context``: ssl.SSLContext to be used for SSLContext.wrap_socket
229 ``server_hostname``: Passed to SSLContext.wrap_socket
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900230
231 Common keyword argument:
232 ``validate_callback`` (cert, hostname) -> None:
233 Called after SSL handshake. Can raise when hostname does not
234 match the cert.
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900235 """
236 self.is_valid = False
237 self.peercert = None
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900238
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900239 if args:
240 if len(args) > 6:
241 raise TypeError('Too many positional argument')
242 if not self._unix_socket_arg(host, port, args, kwargs):
243 self._deprecated_arg(args, kwargs, 0, 'validate')
244 self._deprecated_arg(args, kwargs, 1, 'ca_certs')
245 self._deprecated_arg(args, kwargs, 2, 'keyfile')
246 self._deprecated_arg(args, kwargs, 3, 'certfile')
247 self._deprecated_arg(args, kwargs, 4, 'unix_socket')
248 self._deprecated_arg(args, kwargs, 5, 'ciphers')
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900249
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900250 validate = kwargs.pop('validate', None)
251 if validate is not None:
252 cert_reqs_name = 'CERT_REQUIRED' if validate else 'CERT_NONE'
253 warnings.warn(
Nobuaki Sukegawa6a0ca7f2016-02-13 03:11:16 +0900254 'validate is deprecated. please use cert_reqs=ssl.%s instead'
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900255 % cert_reqs_name,
Nobuaki Sukegawa6a0ca7f2016-02-13 03:11:16 +0900256 DeprecationWarning, stacklevel=2)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900257 if 'cert_reqs' in kwargs:
258 raise TypeError('Cannot specify both validate and cert_reqs')
259 kwargs['cert_reqs'] = ssl.CERT_REQUIRED if validate else ssl.CERT_NONE
260
261 unix_socket = kwargs.pop('unix_socket', None)
Nobuaki Sukegawaf32bae72016-02-20 08:51:33 +0900262 self._validate_callback = kwargs.pop('validate_callback', _match_hostname)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900263 TSSLBase.__init__(self, False, host, kwargs)
264 TSocket.TSocket.__init__(self, host, port, unix_socket)
265
266 @property
267 def validate(self):
Nobuaki Sukegawa6a0ca7f2016-02-13 03:11:16 +0900268 warnings.warn('validate is deprecated. please use cert_reqs instead',
269 DeprecationWarning, stacklevel=2)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900270 return self.cert_reqs != ssl.CERT_NONE
271
272 @validate.setter
273 def validate(self, value):
Nobuaki Sukegawa6a0ca7f2016-02-13 03:11:16 +0900274 warnings.warn('validate is deprecated. please use cert_reqs instead',
275 DeprecationWarning, stacklevel=2)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900276 self.cert_reqs = ssl.CERT_REQUIRED if value else ssl.CERT_NONE
277
Nobuaki Sukegawa1c8b5cb2016-02-14 22:04:38 +0900278 def _do_open(self, family, socktype):
279 plain_sock = socket.socket(family, socktype)
Bryan Duxbury2b969ad2011-02-22 18:20:53 +0000280 try:
Nobuaki Sukegawa1c8b5cb2016-02-14 22:04:38 +0900281 return self._wrap_socket(plain_sock)
282 except Exception:
283 plain_sock.close()
284 msg = 'failed to initialize SSL'
285 logger.exception(msg)
286 raise TTransportException(TTransportException.NOT_OPEN, msg)
Bryan Duxbury50409112011-03-21 17:59:49 +0000287
Nobuaki Sukegawa1c8b5cb2016-02-14 22:04:38 +0900288 def open(self):
289 super(TSSLSocket, self).open()
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900290 if self._should_verify:
291 self.peercert = self.handle.getpeercert()
292 try:
293 self._validate_callback(self.peercert, self._server_hostname)
294 self.is_valid = True
295 except TTransportException:
296 raise
297 except Exception as ex:
298 raise TTransportException(TTransportException.UNKNOWN, str(ex))
299
Bryan Duxbury2b969ad2011-02-22 18:20:53 +0000300
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900301class TSSLServerSocket(TSocket.TServerSocket, TSSLBase):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900302 """SSL implementation of TServerSocket
Bryan Duxbury50409112011-03-21 17:59:49 +0000303
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900304 This uses the ssl module's wrap_socket() method to provide SSL
305 negotiated encryption.
Bryan Duxbury50409112011-03-21 17:59:49 +0000306 """
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900307
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900308 # New signature
309 # def __init__(self, host='localhost', port=9090, unix_socket=None, **ssl_args):
310 # Deprecated signature
311 # def __init__(self, host=None, port=9090, certfile='cert.pem', unix_socket=None, ciphers=None):
312 def __init__(self, host=None, port=9090, *args, **kwargs):
313 """Positional arguments: ``host``, ``port``, ``unix_socket``
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900314
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900315 Keyword arguments: ``keyfile``, ``certfile``, ``cert_reqs``, ``ssl_version``,
316 ``ca_certs``, ``ciphers`` (Python 2.7.0 or later)
317 See ssl.wrap_socket documentation.
Bryan Duxbury50409112011-03-21 17:59:49 +0000318
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900319 Alternative keyword arguments: (Python 2.7.9 or later)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900320 ``ssl_context``: ssl.SSLContext to be used for SSLContext.wrap_socket
321 ``server_hostname``: Passed to SSLContext.wrap_socket
Nobuaki Sukegawaf39f7db2016-02-04 15:09:41 +0900322
323 Common keyword argument:
324 ``validate_callback`` (cert, hostname) -> None:
325 Called after SSL handshake. Can raise when hostname does not
326 match the cert.
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900327 """
328 if args:
329 if len(args) > 3:
330 raise TypeError('Too many positional argument')
331 if not self._unix_socket_arg(host, port, args, kwargs):
332 self._deprecated_arg(args, kwargs, 0, 'certfile')
333 self._deprecated_arg(args, kwargs, 1, 'unix_socket')
334 self._deprecated_arg(args, kwargs, 2, 'ciphers')
Bryan Duxbury69720412012-01-03 17:32:30 +0000335
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900336 if 'ssl_context' not in kwargs:
337 # Preserve existing behaviors for default values
338 if 'cert_reqs' not in kwargs:
339 kwargs['cert_reqs'] = ssl.CERT_NONE
340 if'certfile' not in kwargs:
341 kwargs['certfile'] = 'cert.pem'
Bryan Duxbury69720412012-01-03 17:32:30 +0000342
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900343 unix_socket = kwargs.pop('unix_socket', None)
Nobuaki Sukegawaf39f7db2016-02-04 15:09:41 +0900344 self._validate_callback = \
Nobuaki Sukegawaf32bae72016-02-20 08:51:33 +0900345 kwargs.pop('validate_callback', _match_hostname)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900346 TSSLBase.__init__(self, True, None, kwargs)
347 TSocket.TServerSocket.__init__(self, host, port, unix_socket)
Nobuaki Sukegawaf32bae72016-02-20 08:51:33 +0900348 if self._should_verify and not _match_has_ipaddress:
Nobuaki Sukegawabf9fa902016-09-04 18:49:21 +0900349 raise ValueError('Need ipaddress and backports.ssl_match_hostname '
Nobuaki Sukegawaf32bae72016-02-20 08:51:33 +0900350 'module to verify client certificate')
Bryan Duxbury50409112011-03-21 17:59:49 +0000351
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900352 def setCertfile(self, certfile):
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900353 """Set or change the server certificate file used to wrap new
354 connections.
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900355
356 @param certfile: The filename of the server certificate,
357 i.e. '/etc/certs/server.pem'
358 @type certfile: str
359
360 Raises an IOError exception if the certfile is not present or unreadable.
361 """
Nobuaki Sukegawa6a0ca7f2016-02-13 03:11:16 +0900362 warnings.warn(
363 'setCertfile is deprecated. please use certfile property instead.',
364 DeprecationWarning, stacklevel=2)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900365 self.certfile = certfile
366
367 def accept(self):
368 plain_client, addr = self.handle.accept()
369 try:
370 client = self._wrap_socket(plain_client)
James E. King IIIf5f430d2018-06-08 03:37:55 +0000371 except (ssl.SSLError, socket.error, OSError):
Nobuaki Sukegawace1c8ab2016-02-11 18:21:39 +0900372 logger.exception('Error while accepting from %s', addr)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900373 # failed handshake/ssl wrap, close socket to client
374 plain_client.close()
375 # raise
376 # We can't raise the exception, because it kills most TServer derived
377 # serve() methods.
378 # Instead, return None, and let the TServer instance deal with it in
379 # other exception handling. (but TSimpleServer dies anyway)
380 return None
Nobuaki Sukegawaf39f7db2016-02-04 15:09:41 +0900381
382 if self._should_verify:
383 client.peercert = client.getpeercert()
384 try:
385 self._validate_callback(client.peercert, addr[0])
386 client.is_valid = True
387 except Exception:
Nobuaki Sukegawad9b44252016-03-01 02:09:11 +0900388 logger.warn('Failed to validate client certificate address: %s',
389 addr[0], exc_info=True)
Nobuaki Sukegawaf39f7db2016-02-04 15:09:41 +0900390 client.close()
391 plain_client.close()
392 return None
393
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900394 result = TSocket.TSocket()
Nobuaki Sukegawa6a0ca7f2016-02-13 03:11:16 +0900395 result.handle = client
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900396 return result