blob: dfaa5dbe82372294d6ed65ffe7f75530396cbf45 [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
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +090026from backports.ssl_match_hostname import match_hostname
Bryan Duxbury2b969ad2011-02-22 18:20:53 +000027
28from 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
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +090043 # For pythoon >= 2.7.9, use latest TLS that both client and server
44 # 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.
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +090046 # For pythoon < 2.7.9, use TLS 1.0 since TLSv1_X nor OP_NO_SSLvX is
47 # 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 Sukegawa25536ad2016-02-04 15:08:55 +090091 '%dth positional argument is deprecated. Use keyward argument insteand.'
92 % real_pos,
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090093 DeprecationWarning)
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 Sukegawa25536ad2016-02-04 15:08:55 +0900110 warnings.warn('Use ssl_version attribute instead.',
111 DeprecationWarning)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900112 return self.ssl_version
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900113
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900114 def __init__(self, server_side, host, ssl_opts):
115 self._server_side = server_side
116 if TSSLBase.SSL_VERSION != self._default_protocol:
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900117 warnings.warn(
118 'SSL_VERSION is deprecated. Use ssl_version keyward argument instead.',
119 DeprecationWarning)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900120 self._context = ssl_opts.pop('ssl_context', None)
121 self._server_hostname = None
122 if not self._server_side:
123 self._server_hostname = ssl_opts.pop('server_hostname', host)
124 if self._context:
125 self._custom_context = True
126 if ssl_opts:
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900127 raise ValueError(
128 'Incompatible arguments: ssl_context and %s'
129 % ' '.join(ssl_opts.keys()))
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900130 if not self._has_ssl_context:
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900131 raise ValueError(
132 'ssl_context is not available for this version of Python')
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900133 else:
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900134 self._custom_context = False
135 ssl_version = ssl_opts.pop('ssl_version', TSSLBase.SSL_VERSION)
136 self._init_context(ssl_version)
137 self.cert_reqs = ssl_opts.pop('cert_reqs', ssl.CERT_REQUIRED)
138 self.ca_certs = ssl_opts.pop('ca_certs', None)
139 self.keyfile = ssl_opts.pop('keyfile', None)
140 self.certfile = ssl_opts.pop('certfile', None)
141 self.ciphers = ssl_opts.pop('ciphers', None)
142
143 if ssl_opts:
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900144 raise ValueError(
145 'Unknown keyword arguments: ', ' '.join(ssl_opts.keys()))
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900146
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900147 if self._should_verify:
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900148 if not self.ca_certs:
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900149 raise ValueError(
150 'ca_certs is needed when cert_reqs is not ssl.CERT_NONE')
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900151 if not os.access(self.ca_certs, os.R_OK):
152 raise IOError('Certificate Authority ca_certs file "%s" '
153 'is not readable, cannot validate SSL '
154 'certificates.' % (self.ca_certs))
155
156 @property
157 def certfile(self):
158 return self._certfile
159
160 @certfile.setter
161 def certfile(self, certfile):
162 if self._server_side and not certfile:
163 raise ValueError('certfile is needed for server-side')
164 if certfile and not os.access(certfile, os.R_OK):
165 raise IOError('No such certfile found: %s' % (certfile))
166 self._certfile = certfile
167
168 def _wrap_socket(self, sock):
169 if self._has_ssl_context:
170 if not self._custom_context:
171 self.ssl_context.verify_mode = self.cert_reqs
172 if self.certfile:
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900173 self.ssl_context.load_cert_chain(self.certfile,
174 self.keyfile)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900175 if self.ciphers:
176 self.ssl_context.set_ciphers(self.ciphers)
177 if self.ca_certs:
178 self.ssl_context.load_verify_locations(self.ca_certs)
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900179 return self.ssl_context.wrap_socket(
180 sock, server_side=self._server_side,
181 server_hostname=self._server_hostname)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900182 else:
183 ssl_opts = {
184 'ssl_version': self._ssl_version,
185 'server_side': self._server_side,
186 'ca_certs': self.ca_certs,
187 'keyfile': self.keyfile,
188 'certfile': self.certfile,
189 'cert_reqs': self.cert_reqs,
190 }
191 if self.ciphers:
192 if self._has_ciphers:
193 ssl_opts['ciphers'] = self.ciphers
194 else:
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900195 logger.warning(
196 'ciphers is specified but ignored due to old Python version')
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900197 return ssl.wrap_socket(sock, **ssl_opts)
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900198
199
200class TSSLSocket(TSocket.TSocket, TSSLBase):
Bryan Duxbury50409112011-03-21 17:59:49 +0000201 """
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900202 SSL implementation of TSocket
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900203
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900204 This class creates outbound sockets wrapped using the
205 python standard ssl module for encrypted connections.
206 """
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900207
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900208 # New signature
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900209 # def __init__(self, host='localhost', port=9090, unix_socket=None,
210 # **ssl_args):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900211 # Deprecated signature
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900212 # def __init__(self, host='localhost', port=9090, validate=True,
213 # ca_certs=None, keyfile=None, certfile=None,
214 # unix_socket=None, ciphers=None):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900215 def __init__(self, host='localhost', port=9090, *args, **kwargs):
216 """Positional arguments: ``host``, ``port``, ``unix_socket``
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900217
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900218 Keyword arguments: ``keyfile``, ``certfile``, ``cert_reqs``,
219 ``ssl_version``, ``ca_certs``,
220 ``ciphers`` (Python 2.7.0 or later),
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900221 ``server_hostname`` (Python 2.7.9 or later)
222 Passed to ssl.wrap_socket. See ssl.wrap_socket documentation.
Bryan Duxbury50409112011-03-21 17:59:49 +0000223
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900224 Alternative keyword arguments: (Python 2.7.9 or later)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900225 ``ssl_context``: ssl.SSLContext to be used for SSLContext.wrap_socket
226 ``server_hostname``: Passed to SSLContext.wrap_socket
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900227
228 Common keyword argument:
229 ``validate_callback`` (cert, hostname) -> None:
230 Called after SSL handshake. Can raise when hostname does not
231 match the cert.
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900232 """
233 self.is_valid = False
234 self.peercert = None
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900235
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900236 if args:
237 if len(args) > 6:
238 raise TypeError('Too many positional argument')
239 if not self._unix_socket_arg(host, port, args, kwargs):
240 self._deprecated_arg(args, kwargs, 0, 'validate')
241 self._deprecated_arg(args, kwargs, 1, 'ca_certs')
242 self._deprecated_arg(args, kwargs, 2, 'keyfile')
243 self._deprecated_arg(args, kwargs, 3, 'certfile')
244 self._deprecated_arg(args, kwargs, 4, 'unix_socket')
245 self._deprecated_arg(args, kwargs, 5, 'ciphers')
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900246
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900247 validate = kwargs.pop('validate', None)
248 if validate is not None:
249 cert_reqs_name = 'CERT_REQUIRED' if validate else 'CERT_NONE'
250 warnings.warn(
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900251 'validate is deprecated. Use cert_reqs=ssl.%s instead'
252 % cert_reqs_name,
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900253 DeprecationWarning)
254 if 'cert_reqs' in kwargs:
255 raise TypeError('Cannot specify both validate and cert_reqs')
256 kwargs['cert_reqs'] = ssl.CERT_REQUIRED if validate else ssl.CERT_NONE
257
258 unix_socket = kwargs.pop('unix_socket', None)
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900259 self._validate_callback = kwargs.pop('validate_callback', match_hostname)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900260 TSSLBase.__init__(self, False, host, kwargs)
261 TSocket.TSocket.__init__(self, host, port, unix_socket)
262
263 @property
264 def validate(self):
265 warnings.warn('Use cert_reqs instead', DeprecationWarning)
266 return self.cert_reqs != ssl.CERT_NONE
267
268 @validate.setter
269 def validate(self, value):
270 warnings.warn('Use cert_reqs instead', DeprecationWarning)
271 self.cert_reqs = ssl.CERT_REQUIRED if value else ssl.CERT_NONE
272
273 def open(self):
Bryan Duxbury2b969ad2011-02-22 18:20:53 +0000274 try:
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900275 res0 = self._resolveAddr()
276 for res in res0:
277 sock_family, sock_type = res[0:2]
278 ip_port = res[4]
279 plain_sock = socket.socket(sock_family, sock_type)
280 self.handle = self._wrap_socket(plain_sock)
281 self.handle.settimeout(self._timeout)
282 try:
283 self.handle.connect(ip_port)
284 except socket.error as e:
285 if res is not res0[-1]:
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900286 logger.warning(
287 'Error while connecting with %s. Trying next one.',
288 ip_port, exc_info=True)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900289 continue
290 else:
291 raise
292 break
jfarrelld565e2f2015-03-18 21:02:47 -0400293 except socket.error as e:
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900294 if self._unix_socket:
295 message = 'Could not connect to secure socket %s: %s' \
296 % (self._unix_socket, e)
297 else:
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900298 message = 'Could not connect to %s:%d: %s' \
299 % (self.host, self.port, e)
300 logger.error(
301 'Error while connecting with %s.', ip_port, exc_info=True)
302 raise TTransportException(TTransportException.NOT_OPEN, message)
Bryan Duxbury50409112011-03-21 17:59:49 +0000303
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900304 if self._should_verify:
305 self.peercert = self.handle.getpeercert()
306 try:
307 self._validate_callback(self.peercert, self._server_hostname)
308 self.is_valid = True
309 except TTransportException:
310 raise
311 except Exception as ex:
312 raise TTransportException(TTransportException.UNKNOWN, str(ex))
313
314 @staticmethod
315 def legacy_validate_callback(self, cert, hostname):
316 """legacy method to validate the peer's SSL certificate, and to check
317 the commonName of the certificate to ensure it matches the hostname we
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900318 used to make this connection. Does not support subjectAltName records
319 in certificates.
Bryan Duxbury69720412012-01-03 17:32:30 +0000320
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900321 raises TTransportException if the certificate fails validation.
322 """
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900323 if 'subject' not in cert:
324 raise TTransportException(
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900325 TTransportException.NOT_OPEN,
326 'No SSL certificate found from %s:%s' % (self.host, self.port))
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900327 fields = cert['subject']
328 for field in fields:
329 # ensure structure we get back is what we expect
330 if not isinstance(field, tuple):
331 continue
332 cert_pair = field[0]
333 if len(cert_pair) < 2:
334 continue
335 cert_key, cert_value = cert_pair[0:2]
336 if cert_key != 'commonName':
337 continue
338 certhost = cert_value
339 # this check should be performed by some sort of Access Manager
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900340 if certhost == hostname:
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900341 # success, cert commonName matches desired hostname
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900342 return
343 else:
344 raise TTransportException(
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900345 TTransportException.UNKNOWN,
346 'Hostname we connected to "%s" doesn\'t match certificate '
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900347 'provided commonName "%s"' % (self.host, certhost))
Bryan Duxbury69720412012-01-03 17:32:30 +0000348 raise TTransportException(
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900349 TTransportException.UNKNOWN,
350 'Could not validate SSL certificate from host "%s". Cert=%s'
351 % (hostname, cert))
Bryan Duxbury69720412012-01-03 17:32:30 +0000352
Bryan Duxbury2b969ad2011-02-22 18:20:53 +0000353
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900354class TSSLServerSocket(TSocket.TServerSocket, TSSLBase):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900355 """SSL implementation of TServerSocket
Bryan Duxbury50409112011-03-21 17:59:49 +0000356
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900357 This uses the ssl module's wrap_socket() method to provide SSL
358 negotiated encryption.
Bryan Duxbury50409112011-03-21 17:59:49 +0000359 """
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900360
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900361 # New signature
362 # def __init__(self, host='localhost', port=9090, unix_socket=None, **ssl_args):
363 # Deprecated signature
364 # def __init__(self, host=None, port=9090, certfile='cert.pem', unix_socket=None, ciphers=None):
365 def __init__(self, host=None, port=9090, *args, **kwargs):
366 """Positional arguments: ``host``, ``port``, ``unix_socket``
Nobuaki Sukegawaad835862015-12-23 23:32:09 +0900367
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900368 Keyword arguments: ``keyfile``, ``certfile``, ``cert_reqs``, ``ssl_version``,
369 ``ca_certs``, ``ciphers`` (Python 2.7.0 or later)
370 See ssl.wrap_socket documentation.
Bryan Duxbury50409112011-03-21 17:59:49 +0000371
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900372 Alternative keyword arguments: (Python 2.7.9 or later)
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900373 ``ssl_context``: ssl.SSLContext to be used for SSLContext.wrap_socket
374 ``server_hostname``: Passed to SSLContext.wrap_socket
375 """
376 if args:
377 if len(args) > 3:
378 raise TypeError('Too many positional argument')
379 if not self._unix_socket_arg(host, port, args, kwargs):
380 self._deprecated_arg(args, kwargs, 0, 'certfile')
381 self._deprecated_arg(args, kwargs, 1, 'unix_socket')
382 self._deprecated_arg(args, kwargs, 2, 'ciphers')
Bryan Duxbury69720412012-01-03 17:32:30 +0000383
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900384 if 'ssl_context' not in kwargs:
385 # Preserve existing behaviors for default values
386 if 'cert_reqs' not in kwargs:
387 kwargs['cert_reqs'] = ssl.CERT_NONE
388 if'certfile' not in kwargs:
389 kwargs['certfile'] = 'cert.pem'
Bryan Duxbury69720412012-01-03 17:32:30 +0000390
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900391 unix_socket = kwargs.pop('unix_socket', None)
392 TSSLBase.__init__(self, True, None, kwargs)
393 TSocket.TServerSocket.__init__(self, host, port, unix_socket)
Bryan Duxbury50409112011-03-21 17:59:49 +0000394
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900395 def setCertfile(self, certfile):
Nobuaki Sukegawa25536ad2016-02-04 15:08:55 +0900396 """Set or change the server certificate file used to wrap new
397 connections.
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900398
399 @param certfile: The filename of the server certificate,
400 i.e. '/etc/certs/server.pem'
401 @type certfile: str
402
403 Raises an IOError exception if the certfile is not present or unreadable.
404 """
405 warnings.warn('Use certfile property instead.', DeprecationWarning)
406 self.certfile = certfile
407
408 def accept(self):
409 plain_client, addr = self.handle.accept()
410 try:
411 client = self._wrap_socket(plain_client)
412 except ssl.SSLError:
413 logger.error('Error while accepting from %s', addr, exc_info=True)
414 # failed handshake/ssl wrap, close socket to client
415 plain_client.close()
416 # raise
417 # We can't raise the exception, because it kills most TServer derived
418 # serve() methods.
419 # Instead, return None, and let the TServer instance deal with it in
420 # other exception handling. (but TSimpleServer dies anyway)
421 return None
422 result = TSocket.TSocket()
423 result.setHandle(client)
424 return result