async def test_tls_reject_certificate():
    cli_ctx = get_client_ssl_context()
    serv_ctx = get_server_ssl_context()

    # These certs are not signed by our test CA
    bad_cert_key = ("tls-self-signed-cert.pem", "tls-self-signed-key.pem")
    bad_cli_ctx = get_client_ssl_context(*bad_cert_key)
    bad_serv_ctx = get_server_ssl_context(*bad_cert_key)

    async def handle_comm(comm):
        scheme, loc = parse_address(comm.peer_address)
        assert scheme == "tls"
        await comm.close()

    # Listener refuses a connector not signed by the CA
    listener = await listen(
        "tls://", handle_comm, connection_args={"ssl_context": serv_ctx}
    )

    with pytest.raises(EnvironmentError) as excinfo:
        comm = await connect(
            listener.contact_address,
            timeout=0.5,
            connection_args={"ssl_context": bad_cli_ctx},
        )
        await comm.write({"x": "foo"})  # TODO: why is this necessary in Tornado 6 ?

    # The wrong error is reported on Python 2, see https://github.com/tornadoweb/tornado/pull/2028
    if sys.version_info >= (3,) and os.name != "nt":
        try:
            # See https://serverfault.com/questions/793260/what-does-tlsv1-alert-unknown-ca-mean
            assert "unknown ca" in str(excinfo.value)
        except AssertionError:
            if os.name == "nt":
                assert "An existing connection was forcibly closed" in str(
                    excinfo.value
                )
            else:
                raise

    # Sanity check
    comm = await connect(
        listener.contact_address, timeout=2, connection_args={"ssl_context": cli_ctx}
    )
    await comm.close()

    # Connector refuses a listener not signed by the CA
    listener = await listen(
        "tls://", handle_comm, connection_args={"ssl_context": bad_serv_ctx}
    )

    with pytest.raises(EnvironmentError) as excinfo:
        await connect(
            listener.contact_address,
            timeout=2,
            connection_args={"ssl_context": cli_ctx},
        )
    # The wrong error is reported on Python 2, see https://github.com/tornadoweb/tornado/pull/2028
    if sys.version_info >= (3,):
        assert "certificate verify failed" in str(excinfo.value)
Exemple #2
0
def test_tls_reject_certificate():
    cli_ctx = get_client_ssl_context()
    serv_ctx = get_server_ssl_context()

    # These certs are not signed by our test CA
    bad_cert_key = ('tls-self-signed-cert.pem', 'tls-self-signed-key.pem')
    bad_cli_ctx = get_client_ssl_context(*bad_cert_key)
    bad_serv_ctx = get_server_ssl_context(*bad_cert_key)

    @gen.coroutine
    def handle_comm(comm):
        scheme, loc = parse_address(comm.peer_address)
        assert scheme == 'tls'
        yield comm.close()

    # Listener refuses a connector not signed by the CA
    listener = listen('tls://',
                      handle_comm,
                      connection_args={'ssl_context': serv_ctx})
    listener.start()

    with pytest.raises(EnvironmentError) as excinfo:
        yield connect(listener.contact_address,
                      timeout=0.5,
                      connection_args={'ssl_context': bad_cli_ctx})

    # The wrong error is reported on Python 2, see https://github.com/tornadoweb/tornado/pull/2028
    if sys.version_info >= (3, ) and os.name != 'nt':
        try:
            # See https://serverfault.com/questions/793260/what-does-tlsv1-alert-unknown-ca-mean
            assert "unknown ca" in str(excinfo.value)
        except AssertionError:
            if os.name == 'nt':
                assert "An existing connection was forcibly closed" in str(
                    excinfo.value)
            else:
                raise

    # Sanity check
    comm = yield connect(listener.contact_address,
                         timeout=0.5,
                         connection_args={'ssl_context': cli_ctx})
    yield comm.close()

    # Connector refuses a listener not signed by the CA
    listener = listen('tls://',
                      handle_comm,
                      connection_args={'ssl_context': bad_serv_ctx})
    listener.start()

    with pytest.raises(EnvironmentError) as excinfo:
        yield connect(listener.contact_address,
                      timeout=0.5,
                      connection_args={'ssl_context': cli_ctx})
    # The wrong error is reported on Python 2, see https://github.com/tornadoweb/tornado/pull/2028
    if sys.version_info >= (3, ):
        assert "certificate verify failed" in str(excinfo.value)
Exemple #3
0
def test_tls_reject_certificate():
    cli_ctx = get_client_ssl_context()
    serv_ctx = get_server_ssl_context()

    # These certs are not signed by our test CA
    bad_cert_key = ('tls-self-signed-cert.pem', 'tls-self-signed-key.pem')
    bad_cli_ctx = get_client_ssl_context(*bad_cert_key)
    bad_serv_ctx = get_server_ssl_context(*bad_cert_key)

    @gen.coroutine
    def handle_comm(comm):
        scheme, loc = parse_address(comm.peer_address)
        assert scheme == 'tls'
        yield comm.close()

    # Listener refuses a connector not signed by the CA
    listener = listen('tls://', handle_comm,
                      connection_args={'ssl_context': serv_ctx})
    listener.start()

    with pytest.raises(EnvironmentError) as excinfo:
        yield connect(listener.contact_address, timeout=0.5,
                      connection_args={'ssl_context': bad_cli_ctx})

    # The wrong error is reported on Python 2, see https://github.com/tornadoweb/tornado/pull/2028
    if sys.version_info >= (3,) and os.name != 'nt':
        try:
            # See https://serverfault.com/questions/793260/what-does-tlsv1-alert-unknown-ca-mean
            assert "unknown ca" in str(excinfo.value)
        except AssertionError:
            if os.name == 'nt':
                assert "An existing connection was forcibly closed" in str(excinfo.value)
            else:
                raise

    # Sanity check
    comm = yield connect(listener.contact_address, timeout=0.5,
                         connection_args={'ssl_context': cli_ctx})
    yield comm.close()

    # Connector refuses a listener not signed by the CA
    listener = listen('tls://', handle_comm,
                      connection_args={'ssl_context': bad_serv_ctx})
    listener.start()

    with pytest.raises(EnvironmentError) as excinfo:
        yield connect(listener.contact_address, timeout=0.5,
                      connection_args={'ssl_context': cli_ctx})
    # The wrong error is reported on Python 2, see https://github.com/tornadoweb/tornado/pull/2028
    if sys.version_info >= (3,):
        assert "certificate verify failed" in str(excinfo.value)
Exemple #4
0
async def test_comm_failure_threading():
    """
    When we fail to connect, make sure we don't make a lot
    of threads.

    We only assert for PY3, because the thread limit only is
    set for python 3.  See github PR #2403 discussion for info.
    """
    async def sleep_for_60ms():
        max_thread_count = 0
        for x in range(60):
            await asyncio.sleep(0.001)
            thread_count = threading.active_count()
            if thread_count > max_thread_count:
                max_thread_count = thread_count
        return max_thread_count

    original_thread_count = threading.active_count()

    # tcp.TCPConnector()
    sleep_future = sleep_for_60ms()
    with pytest.raises(IOError):
        await connect("tcp://localhost:28400", 0.052)
    max_thread_count = await sleep_future
    # 2 is the number set by BaseTCPConnector.executor (ThreadPoolExecutor)
    assert max_thread_count <= 2 + original_thread_count

    # tcp.TLSConnector()
    sleep_future = sleep_for_60ms()
    with pytest.raises(IOError):
        await connect("tls://localhost:28400",
                      0.052,
                      ssl_context=get_client_ssl_context())
    max_thread_count = await sleep_future
    assert max_thread_count <= 2 + original_thread_count
Exemple #5
0
async def test_tls_reject_certificate(tcp):
    cli_ctx = get_client_ssl_context()
    serv_ctx = get_server_ssl_context()

    # These certs are not signed by our test CA
    bad_cert_key = ("tls-self-signed-cert.pem", "tls-self-signed-key.pem")
    bad_cli_ctx = get_client_ssl_context(*bad_cert_key)
    bad_serv_ctx = get_server_ssl_context(*bad_cert_key)

    async def handle_comm(comm):
        scheme, loc = parse_address(comm.peer_address)
        assert scheme == "tls"
        await comm.close()

    # Listener refuses a connector not signed by the CA
    listener = await listen("tls://", handle_comm, ssl_context=serv_ctx)

    with pytest.raises(EnvironmentError) as excinfo:
        comm = await connect(listener.contact_address,
                             timeout=0.5,
                             ssl_context=bad_cli_ctx)
        await comm.write({"x":
                          "foo"})  # TODO: why is this necessary in Tornado 6 ?

    if os.name != "nt":
        try:
            # See https://serverfault.com/questions/793260/what-does-tlsv1-alert-unknown-ca-mean
            # assert "unknown ca" in str(excinfo.value)
            pass
        except AssertionError:
            if os.name == "nt":
                assert "An existing connection was forcibly closed" in str(
                    excinfo.value)
            else:
                raise

    # Sanity check
    comm = await connect(listener.contact_address,
                         timeout=2,
                         ssl_context=cli_ctx)
    await comm.close()

    # Connector refuses a listener not signed by the CA
    listener = await listen("tls://", handle_comm, ssl_context=bad_serv_ctx)

    with pytest.raises(EnvironmentError) as excinfo:
        await connect(listener.contact_address, timeout=2, ssl_context=cli_ctx)
Exemple #6
0
def test_tls_specific():
    """
    Test concrete TLS API.
    """
    @gen.coroutine
    def handle_comm(comm):
        assert comm.peer_address.startswith("tls://" + host)
        check_tls_extra(comm.extra_info)
        msg = yield comm.read()
        msg["op"] = "pong"
        yield comm.write(msg)
        yield comm.close()

    server_ctx = get_server_ssl_context()
    client_ctx = get_client_ssl_context()

    listener = tcp.TLSListener("localhost",
                               handle_comm,
                               ssl_context=server_ctx)
    listener.start()
    host, port = listener.get_host_port()
    assert host in ("localhost", "127.0.0.1", "::1")
    assert port > 0

    connector = tcp.TLSConnector()
    l = []

    @gen.coroutine
    def client_communicate(key, delay=0):
        addr = "%s:%d" % (host, port)
        comm = yield connector.connect(addr, ssl_context=client_ctx)
        assert comm.peer_address == "tls://" + addr
        check_tls_extra(comm.extra_info)
        yield comm.write({"op": "ping", "data": key})
        if delay:
            yield gen.sleep(delay)
        msg = yield comm.read()
        assert msg == {"op": "pong", "data": key}
        l.append(key)
        yield comm.close()

    yield client_communicate(key=1234)

    # Many clients at once
    N = 100
    futures = [client_communicate(key=i, delay=0.05) for i in range(N)]
    yield futures
    assert set(l) == {1234} | set(range(N))
Exemple #7
0
def test_tls_specific():
    """
    Test concrete TLS API.
    """
    @gen.coroutine
    def handle_comm(comm):
        assert comm.peer_address.startswith('tls://' + host)
        check_tls_extra(comm.extra_info)
        msg = yield comm.read()
        msg['op'] = 'pong'
        yield comm.write(msg)
        yield comm.close()

    server_ctx = get_server_ssl_context()
    client_ctx = get_client_ssl_context()

    listener = tcp.TLSListener('localhost', handle_comm,
                               ssl_context=server_ctx)
    listener.start()
    host, port = listener.get_host_port()
    assert host in ('localhost', '127.0.0.1', '::1')
    assert port > 0

    connector = tcp.TLSConnector()
    l = []

    @gen.coroutine
    def client_communicate(key, delay=0):
        addr = '%s:%d' % (host, port)
        comm = yield connector.connect(addr, ssl_context=client_ctx)
        assert comm.peer_address == 'tls://' + addr
        check_tls_extra(comm.extra_info)
        yield comm.write({'op': 'ping', 'data': key})
        if delay:
            yield gen.sleep(delay)
        msg = yield comm.read()
        assert msg == {'op': 'pong', 'data': key}
        l.append(key)
        yield comm.close()

    yield client_communicate(key=1234)

    # Many clients at once
    N = 100
    futures = [client_communicate(key=i, delay=0.05) for i in range(N)]
    yield futures
    assert set(l) == {1234} | set(range(N))
Exemple #8
0
async def test_listen_connect_wss():
    async def handle_comm(comm):
        while True:
            msg = await comm.read()
            await comm.write(msg)

    server_ctx = get_server_ssl_context()
    client_ctx = get_client_ssl_context()

    async with listen("wss://", handle_comm, ssl_context=server_ctx) as listener:
        comm = await connect(listener.contact_address, ssl_context=client_ctx)
        assert comm.peer_address.startswith("wss://")
        check_tls_extra(comm.extra_info)
        await comm.write(b"Hello!")
        result = await comm.read()
        assert result == b"Hello!"
        await comm.close()
Exemple #9
0
async def test_tls_specific(tcp):
    """
    Test concrete TLS API.
    """
    async def handle_comm(comm):
        assert comm.peer_address.startswith("tls://" + host)
        check_tls_extra(comm.extra_info)
        msg = await comm.read()
        msg["op"] = "pong"
        await comm.write(msg)
        await comm.close()

    server_ctx = get_server_ssl_context()
    client_ctx = get_client_ssl_context()

    listener = await tcp.TLSListener("127.0.0.1",
                                     handle_comm,
                                     ssl_context=server_ctx)
    host, port = listener.get_host_port()
    assert host in ("localhost", "127.0.0.1", "::1")
    assert port > 0

    l = []

    async def client_communicate(key, delay=0):
        addr = "%s:%d" % (host, port)
        comm = await connect(listener.contact_address, ssl_context=client_ctx)
        assert comm.peer_address == "tls://" + addr
        check_tls_extra(comm.extra_info)
        await comm.write({"op": "ping", "data": key})
        if delay:
            await asyncio.sleep(delay)
        msg = await comm.read()
        assert msg == {"op": "pong", "data": key}
        l.append(key)
        await comm.close()

    await client_communicate(key=1234)

    # Many clients at once
    N = 100
    futures = [client_communicate(key=i, delay=0.05) for i in range(N)]
    await asyncio.gather(*futures)
    assert set(l) == {1234} | set(range(N))
Exemple #10
0
def test_comm_failure_threading():
    """
    When we fail to connect, make sure we don't make a lot
    of threads.

    We only assert for PY3, because the thread limit only is
    set for python 3.  See github PR #2403 discussion for info.
    """

    @gen.coroutine
    def sleep_for_60ms():
        max_thread_count = 0
        for x in range(60):
            yield gen.sleep(0.001)
            thread_count = threading.active_count()
            if thread_count > max_thread_count:
                max_thread_count = thread_count
        raise gen.Return(max_thread_count)

    original_thread_count = threading.active_count()

    # tcp.TCPConnector()
    sleep_future = sleep_for_60ms()
    with pytest.raises(IOError):
        yield connect("tcp://localhost:28400", 0.052)
    max_thread_count = yield sleep_future
    # 2 is the number set by BaseTCPConnector.executor (ThreadPoolExecutor)
    if PY3:
        assert max_thread_count <= 2 + original_thread_count

    # tcp.TLSConnector()
    sleep_future = sleep_for_60ms()
    with pytest.raises(IOError):
        yield connect(
            "tls://localhost:28400",
            0.052,
            connection_args={"ssl_context": get_client_ssl_context()},
        )
    max_thread_count = yield sleep_future
    if PY3:
        assert max_thread_count <= 2 + original_thread_count
Exemple #11
0
)


def check_tls_extra(info):
    assert isinstance(info, dict)
    assert info['peercert']['subject'] == cert_subject
    assert 'cipher' in info
    cipher_name, proto_name, secret_bits = info['cipher']
    # Most likely
    assert 'AES' in cipher_name
    assert 'TLS' in proto_name
    assert secret_bits >= 128


tls_kwargs = dict(listen_args={'ssl_context': get_server_ssl_context()},
                  connect_args={'ssl_context': get_client_ssl_context()})


@gen.coroutine
def get_comm_pair(listen_addr, listen_args=None, connect_args=None,
                  **kwargs):
    q = queues.Queue()

    def handle_comm(comm):
        q.put(comm)

    listener = listen(listen_addr, handle_comm,
                      connection_args=listen_args, **kwargs)
    listener.start()

    comm = yield connect(listener.contact_address,
Exemple #12
0

def check_tls_extra(info):
    assert isinstance(info, dict)
    assert info["peercert"]["subject"] == cert_subject
    assert "cipher" in info
    cipher_name, proto_name, secret_bits = info["cipher"]
    # Most likely
    assert "AES" in cipher_name
    assert "TLS" in proto_name
    assert secret_bits >= 128


tls_kwargs = dict(
    listen_args={"ssl_context": get_server_ssl_context()},
    connect_args={"ssl_context": get_client_ssl_context()},
)


@gen.coroutine
def get_comm_pair(listen_addr, listen_args=None, connect_args=None, **kwargs):
    q = queues.Queue()

    def handle_comm(comm):
        q.put(comm)

    listener = listen(listen_addr,
                      handle_comm,
                      connection_args=listen_args,
                      **kwargs)
    listener.start()
Exemple #13
0
                                                    'localhost'), ))


def check_tls_extra(info):
    assert isinstance(info, dict)
    assert info['peercert']['subject'] == cert_subject
    assert 'cipher' in info
    cipher_name, proto_name, secret_bits = info['cipher']
    # Most likely
    assert 'AES' in cipher_name
    assert 'TLS' in proto_name
    assert secret_bits >= 128


tls_kwargs = dict(listen_args={'ssl_context': get_server_ssl_context()},
                  connect_args={'ssl_context': get_client_ssl_context()})


@gen.coroutine
def get_comm_pair(listen_addr, listen_args=None, connect_args=None, **kwargs):
    q = queues.Queue()

    def handle_comm(comm):
        q.put(comm)

    listener = listen(listen_addr,
                      handle_comm,
                      connection_args=listen_args,
                      **kwargs)
    listener.start()