summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Paul Calderone <exarkun@twistedmatrix.com>2013-03-19 22:10:37 -0700
committerJean-Paul Calderone <exarkun@twistedmatrix.com>2013-03-19 22:10:37 -0700
commitd899af0ab4abde552fdca22c8b1401edd1a24446 (patch)
tree2e65e3514a095edfcfa0d88bbe0311f4c134f2ee
parent7e166fe9cbd810ea7441e1e4fed0d600f47950dd (diff)
downloadpyopenssl-d899af0ab4abde552fdca22c8b1401edd1a24446.tar.gz
A few more tests, still incomplete
-rw-r--r--OpenSSL/SSL.py44
-rw-r--r--OpenSSL/crypto.py7
-rw-r--r--OpenSSL/test/test_ssl.py66
3 files changed, 104 insertions, 13 deletions
diff --git a/OpenSSL/SSL.py b/OpenSSL/SSL.py
index 35ecf7c..e4116e2 100644
--- a/OpenSSL/SSL.py
+++ b/OpenSSL/SSL.py
@@ -143,6 +143,16 @@ class WantReadError(Error):
+class WantWriteError(Error):
+ pass
+
+
+
+class WantX509LookupError(Error):
+ pass
+
+
+
class ZeroReturnError(Error):
pass
@@ -777,21 +787,27 @@ class Connection(object):
error = _api.SSL_get_error(ssl, result)
if error == _api.SSL_ERROR_WANT_READ:
raise WantReadError()
+ elif error == _api.SSL_ERROR_WANT_WRITE:
+ raise WantWriteError()
elif error == _api.SSL_ERROR_ZERO_RETURN:
raise ZeroReturnError()
- elif error == _api.SSL_ERROR_NONE:
- pass
+ elif error == _api.SSL_ERROR_WANT_X509_LOOKUP:
+ # TODO Untested
+ 1/0
+ raise WantX509LookupError()
elif error == _api.SSL_ERROR_SYSCALL:
if _api.ERR_peek_error() == 0:
if result < 0:
raise SysCallError(
_api.ffi.errno, errorcode[_api.ffi.errno])
else:
- # TODO
- raise Exception("unknown syscall error")
+ raise SysCallError(-1, "Unexpected EOF")
else:
- # TODO
+ # TODO Untested
+ 1/0
_raise_current_error(Error)
+ elif error == _api.SSL_ERROR_NONE:
+ pass
else:
_raise_current_error(Error)
@@ -930,7 +946,23 @@ class Connection(object):
if _api.BIO_should_retry(bio):
if _api.BIO_should_read(bio):
raise WantReadError()
- 1/0
+ elif _api.BIO_should_write(bio):
+ # TODO Untested
+ 1/0
+ raise WantWriteError()
+ elif _api.BIO_should_io_special(bio):
+ 1/0
+ # TODO Untested. I think io_special means the socket BIO has a
+ # not-yet connected socket.
+ raise ValueError("BIO_should_io_special")
+ else:
+ 1/0
+ # TODO Untested
+ raise ValueError("unknown bio failure")
+ else:
+ 1/0
+ # TODO Untested
+ _raise_current_error(Error)
def bio_read(self, bufsiz):
diff --git a/OpenSSL/crypto.py b/OpenSSL/crypto.py
index 23c533c..2fed4b8 100644
--- a/OpenSSL/crypto.py
+++ b/OpenSSL/crypto.py
@@ -286,8 +286,11 @@ class X509Name(object):
if data_length < 0:
1/0
- result = _api.buffer(result_buffer[0], data_length)[:].decode('utf-8')
- _api.OPENSSL_free(result_buffer[0])
+ try:
+ result = _api.buffer(result_buffer[0], data_length)[:].decode('utf-8')
+ finally:
+ # XXX untested
+ _api.OPENSSL_free(result_buffer[0])
return result
diff --git a/OpenSSL/test/test_ssl.py b/OpenSSL/test/test_ssl.py
index 8fc17a2..1b2f213 100644
--- a/OpenSSL/test/test_ssl.py
+++ b/OpenSSL/test/test_ssl.py
@@ -8,7 +8,7 @@ Unit tests for :py:obj:`OpenSSL.SSL`.
from gc import collect
from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK, EPIPE
from sys import platform, version_info
-from socket import error, socket
+from socket import SHUT_RDWR, error, socket
from os import makedirs
from os.path import join, dirname
from unittest import main
@@ -33,9 +33,9 @@ from OpenSSL.SSL import (
SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
from OpenSSL.SSL import (
- Error, SysCallError, WantReadError, ZeroReturnError, SSLeay_version)
+ Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
from OpenSSL.SSL import (
- Context, ContextType, Session, Connection, ConnectionType)
+ Context, ContextType, Session, Connection, ConnectionType, SSLeay_version)
from OpenSSL.test.util import TestCase, bytes, b
from OpenSSL.test.test_crypto import (
@@ -1239,8 +1239,6 @@ class ConnectionTests(TestCase, _LoopbackMixin):
"""
Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
"""
- # XXX want_write
- # XXX want_read
# XXX get_peer_certificate -> None
# XXX sock_shutdown
# XXX master_key -> TypeError
@@ -1729,6 +1727,36 @@ class ConnectionTests(TestCase, _LoopbackMixin):
self._loopback, clientFactory=makeClient, serverFactory=makeServer)
+ def test_wantWriteError(self):
+ """
+ :py:obj:`Connection` methods which generate output raise
+ :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
+ fail indicating a should-write state.
+ """
+ client_socket, server_socket = socket_pair()
+ # Fill up the client's send buffer so Connection won't be able to write
+ # anything.
+ msg = 'x' * 1024
+ for i in range(1024):
+ try:
+ client_socket.send(msg)
+ except error as e:
+ if e.errno == EWOULDBLOCK:
+ break
+ raise
+ else:
+ self.fail(
+ "Failed to fill socket buffer, cannot test BIO want write")
+
+ ctx = Context(TLSv1_METHOD)
+ conn = Connection(ctx, client_socket)
+ # Client's speak first, so make it an SSL client
+ conn.set_connect_state()
+ self.assertRaises(WantWriteError, conn.do_handshake)
+
+ # XXX want_read
+
+
class ConnectionGetCipherListTests(TestCase):
"""
@@ -2224,6 +2252,18 @@ class MemoryBIOTests(TestCase, _LoopbackMixin):
self.assertEquals(e.__class__, Error)
+ def test_unexpectedEndOfFile(self):
+ """
+ If the connection is lost before an orderly SSL shutdown occurs,
+ :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
+ "Unexpected EOF".
+ """
+ server_conn, client_conn = self._loopback()
+ client_conn.sock_shutdown(SHUT_RDWR)
+ exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
+ self.assertEqual(exc.args, (-1, "Unexpected EOF"))
+
+
def _check_client_ca_list(self, func):
"""
Verify the return value of the :py:obj:`get_client_ca_list` method for server and client connections.
@@ -2435,6 +2475,22 @@ class MemoryBIOTests(TestCase, _LoopbackMixin):
self._check_client_ca_list(set_replaces_add_ca)
+
+class ConnectionBIOTests(TestCase):
+ """
+ Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
+ """
+ def test_wantReadError(self):
+ """
+ :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
+ if there are no bytes available to be read from the BIO.
+ """
+ ctx = Context(TLSv1_METHOD)
+ conn = Connection(ctx, None)
+ self.assertRaises(WantReadError, conn.bio_read, 1024)
+
+
+
class InfoConstantTests(TestCase):
"""
Tests for assorted constants exposed for use in info callbacks.