Merge remote-tracking branch 'upstream/master'
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..867434b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+build
+dist
+*.egg-info
\ No newline at end of file
diff --git a/OpenSSL/SSL.py b/OpenSSL/SSL.py
index ce2cc29..a257f16 100644
--- a/OpenSSL/SSL.py
+++ b/OpenSSL/SSL.py
@@ -1,11 +1,11 @@
-
+from sys import platform
from functools import wraps, partial
from itertools import count
from weakref import WeakValueDictionary
from errno import errorcode
from six import text_type as _text_type
-
+from six import integer_types as integer_types
from OpenSSL._util import (
ffi as _ffi,
@@ -196,16 +196,15 @@
def _asFileDescriptor(obj):
fd = None
-
- if not isinstance(obj, int):
+ if not isinstance(obj, integer_types):
meth = getattr(obj, "fileno", None)
if meth is not None:
obj = meth()
- if isinstance(obj, int):
+ if isinstance(obj, integer_types):
fd = obj
- if not isinstance(fd, int):
+ if not isinstance(fd, integer_types):
raise TypeError("argument must be an int, or have a fileno() method.")
elif fd < 0:
raise ValueError(
@@ -253,7 +252,7 @@
:param method: One of SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, or
TLSv1_METHOD.
"""
- if not isinstance(method, int):
+ if not isinstance(method, integer_types):
raise TypeError("method must be an integer")
try:
@@ -384,7 +383,7 @@
certfile = certfile.encode("utf-8")
if not isinstance(certfile, bytes):
raise TypeError("certfile must be bytes or unicode")
- if not isinstance(filetype, int):
+ if not isinstance(filetype, integer_types):
raise TypeError("filetype must be an integer")
use_result = _lib.SSL_CTX_use_certificate_file(self._context, certfile, filetype)
@@ -450,7 +449,7 @@
if filetype is _unspecified:
filetype = FILETYPE_PEM
- elif not isinstance(filetype, int):
+ elif not isinstance(filetype, integer_types):
raise TypeError("filetype must be an integer")
use_result = _lib.SSL_CTX_use_PrivateKey_file(
@@ -509,7 +508,7 @@
bitwise or)
:returns: The previously set caching mode.
"""
- if not isinstance(mode, int):
+ if not isinstance(mode, integer_types):
raise TypeError("mode must be an integer")
return _lib.SSL_CTX_set_session_cache_mode(self._context, mode)
@@ -533,7 +532,7 @@
See SSL_CTX_set_verify(3SSL) for further details.
"""
- if not isinstance(mode, int):
+ if not isinstance(mode, integer_types):
raise TypeError("mode must be an integer")
if not callable(callback):
@@ -551,7 +550,7 @@
:param depth: An integer specifying the verify depth
:return: None
"""
- if not isinstance(depth, int):
+ if not isinstance(depth, integer_types):
raise TypeError("depth must be an integer")
_lib.SSL_CTX_set_verify_depth(self._context, depth)
@@ -676,7 +675,7 @@
:param timeout: The timeout in seconds
:return: The previous session timeout
"""
- if not isinstance(timeout, int):
+ if not isinstance(timeout, integer_types):
raise TypeError("timeout must be an integer")
return _lib.SSL_CTX_set_timeout(self._context, timeout)
@@ -700,7 +699,7 @@
"""
@wraps(callback)
def wrapper(ssl, where, return_code):
- callback(self, where, return_code)
+ callback(Connection._reverse_mapping[ssl], where, return_code)
self._info_callback = _ffi.callback(
"void (*)(const SSL *, int, int)", wrapper)
_lib.SSL_CTX_set_info_callback(self._context, self._info_callback)
@@ -748,7 +747,7 @@
:param options: The options to add.
:return: The new option bitmask.
"""
- if not isinstance(options, int):
+ if not isinstance(options, integer_types):
raise TypeError("options must be an integer")
return _lib.SSL_CTX_set_options(self._context, options)
@@ -761,7 +760,7 @@
:param mode: The mode to add.
:return: The new mode bitmask.
"""
- if not isinstance(mode, int):
+ if not isinstance(mode, integer_types):
raise TypeError("mode must be an integer")
return _lib.SSL_CTX_set_mode(self._context, mode)
@@ -856,8 +855,11 @@
elif error == _lib.SSL_ERROR_SYSCALL:
if _lib.ERR_peek_error() == 0:
if result < 0:
- raise SysCallError(
- _ffi.errno, errorcode[_ffi.errno])
+ if platform == "win32":
+ errno = _ffi.getwinerror()[0]
+ else:
+ errno = _ffi.errno
+ raise SysCallError(errno, errorcode[errno])
else:
raise SysCallError(-1, "Unexpected EOF")
else:
@@ -943,8 +945,6 @@
buf = buf.tobytes()
if not isinstance(buf, bytes):
raise TypeError("data must be a byte string")
- if not isinstance(flags, int):
- raise TypeError("flags must be an integer")
result = _lib.SSL_write(self._ssl, buf, len(buf))
self._raise_ssl_error(self._ssl, result)
@@ -967,8 +967,6 @@
buf = buf.tobytes()
if not isinstance(buf, bytes):
raise TypeError("buf must be a byte string")
- if not isinstance(flags, int):
- raise TypeError("flags must be an integer")
left_to_send = len(buf)
total_sent = 0
@@ -1029,7 +1027,7 @@
if self._from_ssl is None:
raise TypeError("Connection sock was not None")
- if not isinstance(bufsiz, int):
+ if not isinstance(bufsiz, integer_types):
raise TypeError("bufsiz must be an integer")
buf = _ffi.new("char[]", bufsiz)
@@ -1252,7 +1250,7 @@
:param state - bitvector of SENT_SHUTDOWN, RECEIVED_SHUTDOWN.
:return: None
"""
- if not isinstance(state, int):
+ if not isinstance(state, integer_types):
raise TypeError("state must be an integer")
_lib.SSL_set_shutdown(self._ssl, state)
diff --git a/OpenSSL/test/test_ssl.py b/OpenSSL/test/test_ssl.py
index e366b47..a6f0127 100644
--- a/OpenSSL/test/test_ssl.py
+++ b/OpenSSL/test/test_ssl.py
@@ -6,7 +6,7 @@
"""
from gc import collect, get_referrers
-from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK, EPIPE
+from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK, EPIPE, ESHUTDOWN
from sys import platform, version_info
from socket import SHUT_RDWR, error, socket
from os import makedirs
@@ -14,7 +14,7 @@
from unittest import main
from weakref import ref
-from six import u
+from six import PY3, u
from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
@@ -337,6 +337,16 @@
self.assertRaises(ValueError, Context, 10)
+ if not PY3:
+ def test_method_long(self):
+ """
+ On Python 2 :py:class:`Context` accepts values of type
+ :py:obj:`long` as well as :py:obj:`int`.
+ """
+ Context(long(TLSv1_METHOD))
+
+
+
def test_type(self):
"""
:py:obj:`Context` and :py:obj:`ContextType` refer to the same type object and can be
@@ -366,6 +376,25 @@
self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
+ if not PY3:
+ def test_use_privatekey_file_long(self):
+ """
+ On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
+ filetype of type :py:obj:`long` as well as :py:obj:`int`.
+ """
+ pemfile = self.mktemp()
+
+ key = PKey()
+ key.generate_key(TYPE_RSA, 128)
+
+ with open(pemfile, "wt") as pem:
+ pem.write(
+ dump_privatekey(FILETYPE_PEM, key).decode("ascii"))
+
+ ctx = Context(TLSv1_METHOD)
+ ctx.use_privatekey_file(pemfile, long(FILETYPE_PEM))
+
+
def test_use_certificate_wrong_args(self):
"""
:py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
@@ -445,6 +474,20 @@
ctx.use_certificate_file(pem_filename)
+ if not PY3:
+ def test_use_certificate_file_long(self):
+ """
+ On Python 2 :py:obj:`Context.use_certificate_file` accepts a
+ filetype of type :py:obj:`long` as well as :py:obj:`int`.
+ """
+ pem_filename = self.mktemp()
+ with open(pem_filename, "wb") as pem_file:
+ pem_file.write(cleartextCertificatePEM)
+
+ ctx = Context(TLSv1_METHOD)
+ ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
+
+
def test_set_app_data_wrong_args(self):
"""
:py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called with other than
@@ -486,6 +529,26 @@
self.assertRaises(TypeError, context.set_options, 1, None)
+ def test_set_options(self):
+ """
+ :py:obj:`Context.set_options` returns the new options value.
+ """
+ context = Context(TLSv1_METHOD)
+ options = context.set_options(OP_NO_SSLv2)
+ self.assertTrue(OP_NO_SSLv2 & options)
+
+
+ if not PY3:
+ def test_set_options_long(self):
+ """
+ On Python 2 :py:obj:`Context.set_options` accepts values of type
+ :py:obj:`long` as well as :py:obj:`int`.
+ """
+ context = Context(TLSv1_METHOD)
+ options = context.set_options(long(OP_NO_SSLv2))
+ self.assertTrue(OP_NO_SSLv2 & options)
+
+
def test_set_mode_wrong_args(self):
"""
:py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with the wrong
@@ -506,6 +569,16 @@
context = Context(TLSv1_METHOD)
self.assertTrue(
MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
+
+ if not PY3:
+ def test_set_mode_long(self):
+ """
+ On Python 2 :py:obj:`Context.set_mode` accepts values of type
+ :py:obj:`long` as well as :py:obj:`int`.
+ """
+ context = Context(TLSv1_METHOD)
+ mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
+ self.assertTrue(MODE_RELEASE_BUFFERS & mode)
else:
"MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
@@ -540,6 +613,17 @@
self.assertEquals(context.get_timeout(), 1234)
+ if not PY3:
+ def test_timeout_long(self):
+ """
+ On Python 2 :py:obj:`Context.set_timeout` accepts values of type
+ `long` as well as int.
+ """
+ context = Context(TLSv1_METHOD)
+ context.set_timeout(long(1234))
+ self.assertEquals(context.get_timeout(), 1234)
+
+
def test_set_verify_depth_wrong_args(self):
"""
:py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called with the wrong
@@ -570,6 +654,17 @@
self.assertEquals(context.get_verify_depth(), 11)
+ if not PY3:
+ def test_verify_depth_long(self):
+ """
+ On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
+ type `long` as well as int.
+ """
+ context = Context(TLSv1_METHOD)
+ context.set_verify_depth(long(11))
+ self.assertEquals(context.get_verify_depth(), 11)
+
+
def _write_encrypted_pem(self, passphrase):
"""
Write a new private key out to a new file, encrypted using the given
@@ -700,15 +795,19 @@
serverSSL = Connection(context, server)
serverSSL.set_accept_state()
- while not called:
- for ssl in clientSSL, serverSSL:
- try:
- ssl.do_handshake()
- except WantReadError:
- pass
+ handshake(clientSSL, serverSSL)
- # Kind of lame. Just make sure it got called somehow.
- self.assertTrue(called)
+ # The callback must always be called with a Connection instance as the
+ # first argument. It would probably be better to split this into
+ # separate tests for client and server side info callbacks so we could
+ # assert it is called with the right Connection instance. It would
+ # also be good to assert *something* about `where` and `ret`.
+ notConnections = [
+ conn for (conn, where, ret) in called
+ if not isinstance(conn, Connection)]
+ self.assertEqual(
+ [], notConnections,
+ "Some info callback arguments were not Connection instaces.")
def _load_verify_locations_test(self, *args):
@@ -1012,7 +1111,7 @@
self.assertRaises(TypeError, context.get_verify_mode, None)
- def test_get_verify_mode(self):
+ def test_set_verify_mode(self):
"""
:py:obj:`Context.get_verify_mode` returns the verify mode flags previously
passed to :py:obj:`Context.set_verify`.
@@ -1025,6 +1124,20 @@
context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
+ if not PY3:
+ def test_set_verify_mode_long(self):
+ """
+ On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
+ type :py:obj:`long` as well as :py:obj:`int`.
+ """
+ context = Context(TLSv1_METHOD)
+ self.assertEquals(context.get_verify_mode(), 0)
+ context.set_verify(
+ long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None)
+ self.assertEquals(
+ context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
+
+
def test_load_tmp_dh_wrong_args(self):
"""
:py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with the wrong
@@ -1100,8 +1213,8 @@
def test_set_session_cache_mode_wrong_args(self):
"""
- L{Context.set_session_cache_mode} raises L{TypeError} if called with
- other than one integer argument.
+ :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
+ called with other than one integer argument.
"""
context = Context(TLSv1_METHOD)
self.assertRaises(TypeError, context.set_session_cache_mode)
@@ -1110,8 +1223,8 @@
def test_get_session_cache_mode_wrong_args(self):
"""
- L{Context.get_session_cache_mode} raises L{TypeError} if called with any
- arguments.
+ :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
+ called with any arguments.
"""
context = Context(TLSv1_METHOD)
self.assertRaises(TypeError, context.get_session_cache_mode, 1)
@@ -1119,15 +1232,27 @@
def test_session_cache_mode(self):
"""
- L{Context.set_session_cache_mode} specifies how sessions are cached.
- The setting can be retrieved via L{Context.get_session_cache_mode}.
+ :py:obj:`Context.set_session_cache_mode` specifies how sessions are
+ cached. The setting can be retrieved via
+ :py:obj:`Context.get_session_cache_mode`.
"""
context = Context(TLSv1_METHOD)
- old = context.set_session_cache_mode(SESS_CACHE_OFF)
+ context.set_session_cache_mode(SESS_CACHE_OFF)
off = context.set_session_cache_mode(SESS_CACHE_BOTH)
self.assertEqual(SESS_CACHE_OFF, off)
self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
+ if not PY3:
+ def test_session_cache_mode_long(self):
+ """
+ On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
+ of type :py:obj:`long` as well as :py:obj:`int`.
+ """
+ context = Context(TLSv1_METHOD)
+ context.set_session_cache_mode(long(SESS_CACHE_BOTH))
+ self.assertEqual(
+ SESS_CACHE_BOTH, context.get_session_cache_mode())
+
def test_get_cert_store(self):
"""
@@ -1535,6 +1660,17 @@
self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
+ if not PY3:
+ def test_set_shutdown_long(self):
+ """
+ On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
+ of type :py:obj:`long` as well as :py:obj:`int`.
+ """
+ connection = Connection(Context(TLSv1_METHOD), socket())
+ connection.set_shutdown(long(RECEIVED_SHUTDOWN))
+ self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
+
+
def test_app_data_wrong_args(self):
"""
:py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
@@ -1776,8 +1912,8 @@
client_socket, server_socket = socket_pair()
# Fill up the client's send buffer so Connection won't be able to write
# anything.
- msg = b"x" * 1024
- for i in range(1024):
+ msg = b"x" * 512
+ for i in range(2048):
try:
client_socket.send(msg)
except error as e:
@@ -1830,13 +1966,14 @@
"""
def test_wrong_args(self):
"""
- When called with arguments other than a single string,
- :py:obj:`Connection.send` raises :py:obj:`TypeError`.
+ When called with arguments other than string argument for its first
+ parameter or more than two arguments, :py:obj:`Connection.send` raises
+ :py:obj:`TypeError`.
"""
connection = Connection(Context(TLSv1_METHOD), None)
self.assertRaises(TypeError, connection.send)
self.assertRaises(TypeError, connection.send, object())
- self.assertRaises(TypeError, connection.send, "foo", "bar")
+ self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
def test_short_bytes(self):
@@ -1873,13 +2010,15 @@
"""
def test_wrong_args(self):
"""
- When called with arguments other than a single string,
- :py:obj:`Connection.sendall` raises :py:obj:`TypeError`.
+ When called with arguments other than a string argument for its first
+ parameter or with more than two arguments, :py:obj:`Connection.sendall`
+ raises :py:obj:`TypeError`.
"""
connection = Connection(Context(TLSv1_METHOD), None)
self.assertRaises(TypeError, connection.sendall)
self.assertRaises(TypeError, connection.sendall, object())
- self.assertRaises(TypeError, connection.sendall, "foo", "bar")
+ self.assertRaises(
+ TypeError, connection.sendall, "foo", object(), "bar")
def test_short(self):
@@ -1935,7 +2074,10 @@
server, client = self._loopback()
server.sock_shutdown(2)
exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
- self.assertEqual(exc.args[0], EPIPE)
+ if platform == "win32":
+ self.assertEqual(exc.args[0], ESHUTDOWN)
+ else:
+ self.assertEqual(exc.args[0], EPIPE)
@@ -2060,66 +2202,68 @@
def test_sess_cache_off(self):
"""
- The value of L{OpenSSL.SSL.SESS_CACHE_OFF} 0x0, the value of
- L{SSL_SESS_CACHE_OFF} defined by I{openssl/ssl.h}.
+ The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
+ :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
"""
self.assertEqual(0x0, SESS_CACHE_OFF)
def test_sess_cache_client(self):
"""
- The value of L{OpenSSL.SSL.SESS_CACHE_CLIENT} 0x1, the value of
- L{SSL_SESS_CACHE_CLIENT} defined by I{openssl/ssl.h}.
+ The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
+ :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
"""
self.assertEqual(0x1, SESS_CACHE_CLIENT)
def test_sess_cache_server(self):
"""
- The value of L{OpenSSL.SSL.SESS_CACHE_SERVER} 0x2, the value of
- L{SSL_SESS_CACHE_SERVER} defined by I{openssl/ssl.h}.
+ The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
+ :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
"""
self.assertEqual(0x2, SESS_CACHE_SERVER)
def test_sess_cache_both(self):
"""
- The value of L{OpenSSL.SSL.SESS_CACHE_BOTH} 0x3, the value of
- L{SSL_SESS_CACHE_BOTH} defined by I{openssl/ssl.h}.
+ The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
+ :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
"""
self.assertEqual(0x3, SESS_CACHE_BOTH)
def test_sess_cache_no_auto_clear(self):
"""
- The value of L{OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR} 0x80, the value of
- L{SSL_SESS_CACHE_NO_AUTO_CLEAR} defined by I{openssl/ssl.h}.
+ The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
+ value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
+ ``openssl/ssl.h``.
"""
self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
def test_sess_cache_no_internal_lookup(self):
"""
- The value of L{OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP} 0x100, the
- value of L{SSL_SESS_CACHE_NO_INTERNAL_LOOKUP} defined by
- I{openssl/ssl.h}.
+ The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
+ the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
+ ``openssl/ssl.h``.
"""
self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
def test_sess_cache_no_internal_store(self):
"""
- The value of L{OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE} 0x200, the
- value of L{SSL_SESS_CACHE_NO_INTERNAL_STORE} defined by
- I{openssl/ssl.h}.
+ The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
+ the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
+ ``openssl/ssl.h``.
"""
self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
def test_sess_cache_no_internal(self):
"""
- The value of L{OpenSSL.SSL.SESS_CACHE_NO_INTERNAL} 0x300, the value of
- L{SSL_SESS_CACHE_NO_INTERNAL} defined by I{openssl/ssl.h}.
+ The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
+ value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
+ ``openssl/ssl.h``.
"""
self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
@@ -2530,6 +2674,40 @@
self.assertRaises(WantReadError, conn.bio_read, 1024)
+ def test_buffer_size(self):
+ """
+ :py:obj:`Connection.bio_read` accepts an integer giving the maximum
+ number of bytes to read and return.
+ """
+ ctx = Context(TLSv1_METHOD)
+ conn = Connection(ctx, None)
+ conn.set_connect_state()
+ try:
+ conn.do_handshake()
+ except WantReadError:
+ pass
+ data = conn.bio_read(2)
+ self.assertEqual(2, len(data))
+
+
+ if not PY3:
+ def test_buffer_size_long(self):
+ """
+ On Python 2 :py:obj:`Connection.bio_read` accepts values of type
+ :py:obj:`long` as well as :py:obj:`int`.
+ """
+ ctx = Context(TLSv1_METHOD)
+ conn = Connection(ctx, None)
+ conn.set_connect_state()
+ try:
+ conn.do_handshake()
+ except WantReadError:
+ pass
+ data = conn.bio_read(long(2))
+ self.assertEqual(2, len(data))
+
+
+
class InfoConstantTests(TestCase):
"""
diff --git a/OpenSSL/test/util.py b/OpenSSL/test/util.py
index 011e7da..4e4d812 100644
--- a/OpenSSL/test/util.py
+++ b/OpenSSL/test/util.py
@@ -17,7 +17,11 @@
from OpenSSL._util import exception_from_error_queue
from OpenSSL.crypto import Error
-import memdbg
+try:
+ import memdbg
+except Exception:
+ class _memdbg(object): heap = None
+ memdbg = _memdbg()
from OpenSSL._util import ffi, lib, byte_string as b
diff --git a/OpenSSL/version.py b/OpenSSL/version.py
index be51903..307dba0 100644
--- a/OpenSSL/version.py
+++ b/OpenSSL/version.py
@@ -6,4 +6,4 @@
pyOpenSSL - A simple wrapper around the OpenSSL library
"""
-__version__ = '0.13'
+__version__ = '0.14'
diff --git a/README b/README
index afe4ddc..1b2a093 100644
--- a/README
+++ b/README
@@ -3,3 +3,7 @@
------------------------------------------------------------------------------
See the file INSTALL for installation instructions.
+
+See http://github.com/pyca/pyopenssl for development.
+
+See https://mail.python.org/mailman/listinfo/pyopenssl-users for the discussion mailing list.
diff --git a/doc/conf.py b/doc/conf.py
index be9784b..d9c9a67 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -51,9 +51,9 @@
# built documents.
#
# The short X.Y version.
-version = '0.13'
+version = '0.14'
# The full version, including alpha/beta/rc tags.
-release = '0.13'
+release = '0.14'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff --git a/doc/index.rst b/doc/index.rst
index a63df87..e4a5a23 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -14,7 +14,6 @@
:maxdepth: 3
introduction
- install
api
internals
diff --git a/doc/install.rst b/doc/install.rst
deleted file mode 100644
index f525726..0000000
--- a/doc/install.rst
+++ /dev/null
@@ -1,69 +0,0 @@
-.. _building:
-
-Building and Installing
-=======================
-
-These instructions can also be found in the file ``INSTALL``.
-
-I have tested this on Debian Linux systems (woody and sid), Solaris 2.6 and
-2.7. Others have successfully compiled it on Windows and NT.
-
-.. _building-unix:
-
-Building the Module on a Unix System
-------------------------------------
-
-pyOpenSSL uses distutils, so there really shouldn't be any problems. To build
-the library::
-
- python setup.py build
-
-If your OpenSSL header files aren't in ``/usr/include``, you may need to supply
-the ``-I`` flag to let the setup script know where to look. The same goes for
-the libraries of course, use the ``-L`` flag. Note that ``build`` won't accept
-these flags, so you have to run first ``build_ext`` and then ``build``!
-Example::
-
- python setup.py build_ext -I/usr/local/ssl/include -L/usr/local/ssl/lib
- python setup.py build
-
-Now you should have a directory called ``OpenSSL`` that contains e.g.
-``SSL.so`` and ``__init__.py`` somewhere in the build dicrectory,
-so just::
-
- python setup.py install
-
-If you, for some arcane reason, don't want the module to appear in the
-``site-packages`` directory, use the ``--prefix`` option.
-
-You can, of course, do::
-
- python setup.py --help
-
-to find out more about how to use the script.
-
-.. _building-windows:
-
-Building the Module on a Windows System
----------------------------------------
-
-Big thanks to Itamar Shtull-Trauring and Oleg Orlov for their help with
-Windows build instructions. Same as for Unix systems, we have to separate
-the ``build_ext`` and the ``build``.
-
-Building the library::
-
- setup.py build_ext -I ...\openssl\inc32 -L ...\openssl\out32dll
- setup.py build
-
-Where ``...\openssl`` is of course the location of your OpenSSL installation.
-
-Installation is the same as for Unix systems::
-
- setup.py install
-
-And similarily, you can do::
-
- setup.py --help
-
-to get more information.
diff --git a/doc/internals.rst b/doc/internals.rst
index 839c446..a2a4cdc 100644
--- a/doc/internals.rst
+++ b/doc/internals.rst
@@ -27,38 +27,10 @@
Callbacks
---------
-There are a number of problems with callbacks. First of all, OpenSSL is written
-as a C library, it's not meant to have Python callbacks, so a way around that
-is needed. Another problem is thread support. A lot of the OpenSSL I/O
-functions can block if the socket is in blocking mode, and then you want other
-Python threads to be able to do other things. The real trouble is if you've
-released the global CPython interpreter lock to do a potentially blocking
-operation, and the operation calls a callback. Then we must take the GIL back,
-since calling Python APIs without holding it is not allowed.
-
-There are two solutions to the first problem, both of which are necessary. The
-first solution to use is if the C callback allows ''userdata'' to be passed to
-it (an arbitrary pointer normally). This is great! We can set our Python
-function object as the real userdata and emulate userdata for the Python
-function in another way. The other solution can be used if an object with an
-''app_data'' system always is passed to the callback. For example, the SSL
-object in OpenSSL has app_data functions and in e.g. the verification
-callbacks, you can retrieve the related SSL object. What we do is to set our
-wrapper :py:class:`.Connection` object as app_data for the SSL object, and we can
-easily find the Python callback.
-
-The other problem is solved using thread local variables. Whenever the GIL is
-released before calling into an OpenSSL API, the PyThreadState pointer returned
-by :c:func:`PyEval_SaveState` is stored in a global thread local variable
-(using Python's own TLS API, :c:func:`PyThread_set_key_value`). When it is
-necessary to re-acquire the GIL, either after the OpenSSL API returns or in a C
-callback invoked by that OpenSSL API, the value of the thread local variable is
-retrieved (:c:func:`PyThread_get_key_value`) and used to re-acquire the GIL.
-This allows Python threads to execute while OpenSSL APIs are running and allows
-use of any particular pyOpenSSL object from any Python thread, since there is
-no per-thread state associated with any of these objects and since OpenSSL is
-threadsafe (as long as properly initialized, as pyOpenSSL initializes it).
-
+Callbacks were more of a problem when pyOpenSSL was written in C.
+Having switched to being written in Python using cffi, callbacks are now straightforward.
+The problems that originally existed no longer do
+(if you are interested in the details you can find descriptions of those problems in the version control history for this document).
.. _socket-methods:
diff --git a/runtests.py b/runtests.py
index 2ec425b..13f5c4c 100644
--- a/runtests.py
+++ b/runtests.py
@@ -2,7 +2,10 @@
sys.modules['ssl'] = None
sys.modules['_hashlib'] = None
-import memdbg
+try:
+ import memdbg
+except Exception as e:
+ pass
from twisted.scripts.trial import run
run()
diff --git a/setup.py b/setup.py
index 7d5dce5..4c1915f 100755
--- a/setup.py
+++ b/setup.py
@@ -11,7 +11,7 @@
from setuptools import setup
# XXX Deduplicate this
-__version__ = '0.13'
+__version__ = '0.14'
setup(name='pyOpenSSL', version=__version__,
packages = ['OpenSSL'],
@@ -34,7 +34,7 @@
maintainer_email = 'exarkun@twistedmatrix.com',
url = 'https://github.com/pyca/pyopenssl',
license = 'APL2',
- install_requires=["cryptography>=0.1", "six>=1.5.2"],
+ install_requires=["cryptography>=0.2.1", "six>=1.5.2"],
long_description = """\
High-level wrapper around a subset of the OpenSSL library, includes
* SSL.Connection objects, wrapping the methods of Python's portable
@@ -49,11 +49,10 @@
'Operating System :: MacOS :: MacOS X',
'Operating System :: Microsoft :: Windows',
'Operating System :: POSIX',
- 'Programming Language :: Python :: 2.4',
- 'Programming Language :: Python :: 2.5',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.2',
+ 'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: Implementation :: CPython',
'Programming Language :: Python :: Implementation :: PyPy',
'Topic :: Security :: Cryptography',