2014-08-16 13:53:07 +00:00
|
|
|
from __future__ import (absolute_import, print_function, division)
|
2016-01-24 22:24:59 +00:00
|
|
|
|
2015-05-27 09:18:54 +00:00
|
|
|
import threading
|
2015-09-15 17:12:15 +00:00
|
|
|
from six.moves import queue
|
|
|
|
from io import StringIO
|
2014-03-05 00:43:52 +00:00
|
|
|
import OpenSSL
|
2016-01-24 22:24:59 +00:00
|
|
|
|
2015-08-10 18:36:47 +00:00
|
|
|
from netlib import tcp
|
|
|
|
from netlib import tutils
|
2013-01-25 02:54:41 +00:00
|
|
|
|
2015-05-27 09:18:54 +00:00
|
|
|
|
2016-02-16 20:31:07 +00:00
|
|
|
class _ServerThread(threading.Thread):
|
2015-05-27 09:18:54 +00:00
|
|
|
|
2013-01-25 02:54:41 +00:00
|
|
|
def __init__(self, server):
|
|
|
|
self.server = server
|
|
|
|
threading.Thread.__init__(self)
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
self.server.serve_forever()
|
|
|
|
|
|
|
|
def shutdown(self):
|
|
|
|
self.server.shutdown()
|
|
|
|
|
|
|
|
|
2016-02-16 20:31:07 +00:00
|
|
|
class _TServer(tcp.TCPServer):
|
2015-05-27 09:18:54 +00:00
|
|
|
|
2016-06-05 11:14:23 +00:00
|
|
|
def __init__(self, ssl, q, handler_klass, addr, **kwargs):
|
2013-01-25 02:54:41 +00:00
|
|
|
"""
|
2014-03-07 03:38:50 +00:00
|
|
|
ssl: A dictionary of SSL parameters:
|
2015-05-27 09:18:54 +00:00
|
|
|
|
2014-03-07 03:38:50 +00:00
|
|
|
cert, key, request_client_cert, cipher_list,
|
|
|
|
dhparams, v3_only
|
2013-01-25 02:54:41 +00:00
|
|
|
"""
|
2014-01-28 16:26:35 +00:00
|
|
|
tcp.TCPServer.__init__(self, addr)
|
2015-06-05 10:44:29 +00:00
|
|
|
|
|
|
|
if ssl is True:
|
|
|
|
self.ssl = dict()
|
|
|
|
elif isinstance(ssl, dict):
|
|
|
|
self.ssl = ssl
|
|
|
|
else:
|
|
|
|
self.ssl = None
|
|
|
|
|
|
|
|
self.q = q
|
2013-01-25 02:54:41 +00:00
|
|
|
self.handler_klass = handler_klass
|
2016-06-05 11:14:23 +00:00
|
|
|
if self.handler_klass is not None:
|
|
|
|
self.handler_klass.kwargs = kwargs
|
2013-01-25 02:54:41 +00:00
|
|
|
self.last_handler = None
|
|
|
|
|
2014-01-09 00:57:37 +00:00
|
|
|
def handle_client_connection(self, request, client_address):
|
2014-01-28 19:30:16 +00:00
|
|
|
h = self.handler_klass(request, client_address, self)
|
2013-01-25 02:54:41 +00:00
|
|
|
self.last_handler = h
|
2015-06-05 10:44:29 +00:00
|
|
|
if self.ssl is not None:
|
2015-06-20 19:54:03 +00:00
|
|
|
cert = self.ssl.get(
|
2015-06-05 10:44:29 +00:00
|
|
|
"cert",
|
|
|
|
tutils.test_data.path("data/server.crt"))
|
|
|
|
raw_key = self.ssl.get(
|
|
|
|
"key",
|
|
|
|
tutils.test_data.path("data/server.key"))
|
2015-05-30 00:02:58 +00:00
|
|
|
key = OpenSSL.crypto.load_privatekey(
|
|
|
|
OpenSSL.crypto.FILETYPE_PEM,
|
2015-06-05 18:52:11 +00:00
|
|
|
open(raw_key, "rb").read())
|
2015-06-05 10:44:29 +00:00
|
|
|
if self.ssl.get("v3_only", False):
|
2015-06-22 18:39:30 +00:00
|
|
|
method = OpenSSL.SSL.SSLv3_METHOD
|
2014-09-28 01:15:26 +00:00
|
|
|
options = OpenSSL.SSL.OP_NO_SSLv2 | OpenSSL.SSL.OP_NO_TLSv1
|
2013-01-25 02:54:41 +00:00
|
|
|
else:
|
2015-06-22 18:39:30 +00:00
|
|
|
method = OpenSSL.SSL.SSLv23_METHOD
|
2013-01-25 02:54:41 +00:00
|
|
|
options = None
|
|
|
|
h.convert_to_ssl(
|
2014-03-05 00:43:52 +00:00
|
|
|
cert, key,
|
2015-05-27 09:18:54 +00:00
|
|
|
method=method,
|
|
|
|
options=options,
|
|
|
|
handle_sni=getattr(h, "handle_sni", None),
|
2015-06-05 10:44:29 +00:00
|
|
|
request_client_cert=self.ssl.get("request_client_cert", None),
|
2015-05-27 09:18:54 +00:00
|
|
|
cipher_list=self.ssl.get("cipher_list", None),
|
|
|
|
dhparams=self.ssl.get("dhparams", None),
|
2015-05-28 15:46:44 +00:00
|
|
|
chain_file=self.ssl.get("chain_file", None),
|
|
|
|
alpn_select=self.ssl.get("alpn_select", None)
|
2013-01-25 02:54:41 +00:00
|
|
|
)
|
|
|
|
h.handle()
|
|
|
|
h.finish()
|
|
|
|
|
2014-09-28 01:15:26 +00:00
|
|
|
def handle_error(self, connection, client_address, fp=None):
|
2015-09-15 17:12:15 +00:00
|
|
|
s = StringIO()
|
2014-09-28 01:15:26 +00:00
|
|
|
tcp.TCPServer.handle_error(self, connection, client_address, s)
|
2013-01-25 02:54:41 +00:00
|
|
|
self.q.put(s.getvalue())
|
2016-02-16 20:31:07 +00:00
|
|
|
|
|
|
|
|
|
|
|
class ServerTestBase(object):
|
|
|
|
ssl = None
|
|
|
|
handler = None
|
|
|
|
addr = ("localhost", 0)
|
|
|
|
|
|
|
|
@classmethod
|
2016-06-05 11:14:23 +00:00
|
|
|
def setup_class(cls, **kwargs):
|
2016-02-16 20:31:07 +00:00
|
|
|
cls.q = queue.Queue()
|
2016-06-05 11:14:23 +00:00
|
|
|
s = cls.makeserver(**kwargs)
|
2016-02-16 20:31:07 +00:00
|
|
|
cls.port = s.address.port
|
|
|
|
cls.server = _ServerThread(s)
|
|
|
|
cls.server.start()
|
|
|
|
|
|
|
|
@classmethod
|
2016-06-05 11:14:23 +00:00
|
|
|
def makeserver(cls, **kwargs):
|
2016-08-18 15:25:55 +00:00
|
|
|
ssl = kwargs.pop('ssl', cls.ssl)
|
|
|
|
return _TServer(ssl, cls.q, cls.handler, cls.addr, **kwargs)
|
2016-02-16 20:31:07 +00:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def teardown_class(cls):
|
|
|
|
cls.server.shutdown()
|
|
|
|
|
2016-06-12 00:15:00 +00:00
|
|
|
def teardown(self):
|
|
|
|
self.server.server.wait_for_silence()
|
|
|
|
|
2016-02-16 20:31:07 +00:00
|
|
|
@property
|
|
|
|
def last_handler(self):
|
|
|
|
return self.server.server.last_handler
|