From d95014aa296010cb8ed29f282ddb1abbec9e3692 Mon Sep 17 00:00:00 2001 From: Fedor Brunner Date: Mon, 3 Mar 2014 17:34:41 +0100 Subject: Get the actually used cipher name,bits,version of the established connection. get_cipher_name, get_cipher_bits, get_cipher_version methods are wrappers for SSL_get_cipher_name, SSL_get_cipher_bits, SSL_get_cipher_version https://www.openssl.org/docs/ssl/SSL_get_current_cipher.html https://www.openssl.org/docs/ssl/SSL_CIPHER_get_name.html --- OpenSSL/SSL.py | 38 +++++++++++++++++++++++++++++++++ OpenSSL/test/test_ssl.py | 55 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) diff --git a/OpenSSL/SSL.py b/OpenSSL/SSL.py index 67e4c82..7e2066c 100644 --- a/OpenSSL/SSL.py +++ b/OpenSSL/SSL.py @@ -1417,6 +1417,44 @@ class Connection(object): if not result: _raise_current_error() + def get_cipher_name(self): + """ + Obtain the name of the currently used cipher. + :returns: The name of the currently used cipher or :py:obj:`None` + if no connection has been established. + """ + cipher = _lib.SSL_get_current_cipher(self._ssl) + if cipher == _ffi.NULL: + return None + else: + return _native(_ffi.string(_lib.SSL_CIPHER_get_name(cipher))) + + def get_cipher_bits(self): + """ + Obtain the number of secret bits of the currently used cipher. + :returns: The number of secret bits of the currently used cipher + or :py:obj:`None` if no connection has been established. + """ + cipher = _lib.SSL_get_current_cipher(self._ssl) + if cipher == _ffi.NULL: + return None + else: + return _lib.SSL_CIPHER_get_bits(cipher, _ffi.NULL) + + def get_cipher_version(self): + """ + Obtain the protocol name of the currently used cipher. + :returns: The protocol name of the currently used cipher + or :py:obj:`None` if no connection has been established. + """ + cipher = _lib.SSL_get_current_cipher(self._ssl) + if cipher == _ffi.NULL: + return None + else: + return _native(_ffi.string(_lib.SSL_CIPHER_get_version(cipher))) + + + ConnectionType = Connection # This is similar to the initialization calls at the end of OpenSSL/crypto.py diff --git a/OpenSSL/test/test_ssl.py b/OpenSSL/test/test_ssl.py index a6f0127..983dc96 100644 --- a/OpenSSL/test/test_ssl.py +++ b/OpenSSL/test/test_ssl.py @@ -1932,7 +1932,62 @@ class ConnectionTests(TestCase, _LoopbackMixin): # XXX want_read + def test_get_cipher_name(self): + """ + :py:obj:`Connection.get_cipher_name` returns the name of the currently + used cipher or :py:obj:`None` if no connection has been established. + """ + # if connection is not established Connection.cipher returns None. + ctx = Context(TLSv1_METHOD) + conn = Connection(ctx, None) + self.assertEqual(conn.get_cipher_name(), None) + + server, client = self._loopback() + server_cipher_name, client_cipher_name = \ + server.get_cipher_name(), client.get_cipher_name() + + self.assertTrue(isinstance(server_cipher_name, str)) + self.assertTrue(isinstance(client_cipher_name, str)) + + self.assertEqual(server_cipher_name, client_cipher_name) + + def test_get_cipher_version(self): + """ + :py:obj:`Connection.get_cipher_version` returns the protocol name of the currently + used cipher or :py:obj:`None` if no connection has been established. + """ + # if connection is not established Connection.cipher returns None. + ctx = Context(TLSv1_METHOD) + conn = Connection(ctx, None) + self.assertEqual(conn.get_cipher_version(), None) + + server, client = self._loopback() + server_cipher_version, client_cipher_version = \ + server.get_cipher_version(), client.get_cipher_version() + + self.assertTrue(isinstance(server_cipher_version, str)) + self.assertTrue(isinstance(client_cipher_version, str)) + + self.assertEqual(server_cipher_version, client_cipher_version) + + def test_get_cipher_bits(self): + """ + :py:obj:`Connection.get_cipher_bits` returns the number of secret bits of the currently + used cipher or :py:obj:`None` if no connection has been established. + """ + # if connection is not established Connection.cipher returns None. + ctx = Context(TLSv1_METHOD) + conn = Connection(ctx, None) + self.assertEqual(conn.get_cipher_bits(), None) + + server, client = self._loopback() + server_cipher_bits, client_cipher_bits = \ + server.get_cipher_bits(), client.get_cipher_bits() + + self.assertTrue(isinstance(server_cipher_bits, int)) + self.assertTrue(isinstance(client_cipher_bits, int)) + self.assertEqual(server_cipher_bits, client_cipher_bits) class ConnectionGetCipherListTests(TestCase): """ -- cgit v1.2.1 From 5747b93d4c6eee7551fcff5e879c3e281f052036 Mon Sep 17 00:00:00 2001 From: Fedor Brunner Date: Wed, 5 Mar 2014 14:22:34 +0100 Subject: Interface for the SSL_get_peer_finished, SSL_get_finished. --- OpenSSL/SSL.py | 32 ++++++++++++++++++++++++++++++++ OpenSSL/test/test_ssl.py | 20 ++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/OpenSSL/SSL.py b/OpenSSL/SSL.py index 67e4c82..e4d2d3b 100644 --- a/OpenSSL/SSL.py +++ b/OpenSSL/SSL.py @@ -1417,6 +1417,38 @@ class Connection(object): if not result: _raise_current_error() + def get_finished(self): + """ + Obtain latest Finished message that we sent. + + :return: A string representing the Finished message + """ + # The size of Finished message is 12 bytes in TLS, + # 36 bytes in SSL protocol, but let's be safe with + # 128 bytes buffer + bufsiz = 128 + buf = _ffi.new("char[]", bufsiz) + result = _lib.SSL_get_finished(self._ssl, buf, bufsiz) + if result == 0: + return None # no Finished so far + else: + return _ffi.buffer(buf, result)[:] + + def get_peer_finished(self): + """ + Obtain latest Finished message that we expected from peer. + + :return: A string representing the Finished message + """ + # Same buffer size as in get_finished + bufsiz = 128 + buf = _ffi.new("char[]", bufsiz) + result = _lib.SSL_get_peer_finished(self._ssl, buf, bufsiz) + if result == 0: + return None # no Finished so far + else: + return _ffi.buffer(buf, result)[:] + ConnectionType = Connection # This is similar to the initialization calls at the end of OpenSSL/crypto.py diff --git a/OpenSSL/test/test_ssl.py b/OpenSSL/test/test_ssl.py index a6f0127..8861972 100644 --- a/OpenSSL/test/test_ssl.py +++ b/OpenSSL/test/test_ssl.py @@ -1932,7 +1932,27 @@ class ConnectionTests(TestCase, _LoopbackMixin): # XXX want_read + def test_finished(self): + """ + :py:obj:`Connection.get_finished` and :py:obj:`Connection.get_peer_finished` + methods return the TLS Finished messages. Finished messages are send + during TLS handshake. Before handshake :py:obj:`Connection.get_finished` and + :py:obj:`Connection.get_peer_finished` return None. + """ + + ctx = Context(TLSv1_METHOD) + connection = Connection(ctx, None) + self.assertEqual(connection.get_finished(), None) + self.assertEqual(connection.get_peer_finished(), None) + + server, client = self._loopback() + + self.assertNotEqual(server.get_finished(), None) + self.assertTrue(len(server.get_finished()) > 0) + self.assertTrue(len(server.get_peer_finished()) > 0) + self.assertEqual(server.get_finished(), client.get_peer_finished()) + self.assertEqual(client.get_finished(), server.get_peer_finished()) class ConnectionGetCipherListTests(TestCase): """ -- cgit v1.2.1 From 2cffdbc96f26052351d5ce7ec3e3ce738e7454ab Mon Sep 17 00:00:00 2001 From: Fedor Brunner Date: Mon, 10 Mar 2014 10:35:23 +0100 Subject: Test methods test_get_cipher_* have been split into two sets. assertTrue(isinstance was replaced with assertIsInstance. assertEqual for None was replaced with assertIs. Added entries to doc/api/ssl.rst. --- OpenSSL/test/test_ssl.py | 54 +++++++++++++++++++++++++++++------------------- doc/api/ssl.rst | 17 +++++++++++++++ setup.py | 2 +- 3 files changed, 51 insertions(+), 22 deletions(-) diff --git a/OpenSSL/test/test_ssl.py b/OpenSSL/test/test_ssl.py index 983dc96..4c2dff5 100644 --- a/OpenSSL/test/test_ssl.py +++ b/OpenSSL/test/test_ssl.py @@ -1932,60 +1932,72 @@ class ConnectionTests(TestCase, _LoopbackMixin): # XXX want_read - def test_get_cipher_name(self): + def test_get_cipher_name_before_connect(self): """ - :py:obj:`Connection.get_cipher_name` returns the name of the currently - used cipher or :py:obj:`None` if no connection has been established. + :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` + if no connection has been established. """ - # if connection is not established Connection.cipher returns None. ctx = Context(TLSv1_METHOD) conn = Connection(ctx, None) - self.assertEqual(conn.get_cipher_name(), None) + self.assertIs(conn.get_cipher_name(), None) + def test_get_cipher_name(self): + """ + :py:obj:`Connection.get_cipher_name` returns the name of the currently + used cipher. + """ server, client = self._loopback() server_cipher_name, client_cipher_name = \ server.get_cipher_name(), client.get_cipher_name() - self.assertTrue(isinstance(server_cipher_name, str)) - self.assertTrue(isinstance(client_cipher_name, str)) + self.assertIsInstance(server_cipher_name, str) + self.assertIsInstance(client_cipher_name, str) self.assertEqual(server_cipher_name, client_cipher_name) - def test_get_cipher_version(self): + def test_get_cipher_version_before_connect(self): """ - :py:obj:`Connection.get_cipher_version` returns the protocol name of the currently - used cipher or :py:obj:`None` if no connection has been established. + :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` + if no connection has been established. """ - # if connection is not established Connection.cipher returns None. ctx = Context(TLSv1_METHOD) conn = Connection(ctx, None) - self.assertEqual(conn.get_cipher_version(), None) + self.assertIs(conn.get_cipher_version(), None) + def test_get_cipher_version(self): + """ + :py:obj:`Connection.get_cipher_version` returns the protocol name of the currently + used cipher. + """ server, client = self._loopback() server_cipher_version, client_cipher_version = \ server.get_cipher_version(), client.get_cipher_version() - self.assertTrue(isinstance(server_cipher_version, str)) - self.assertTrue(isinstance(client_cipher_version, str)) + self.assertIsInstance(server_cipher_version, str) + self.assertIsInstance(client_cipher_version, str) self.assertEqual(server_cipher_version, client_cipher_version) - def test_get_cipher_bits(self): + def test_get_cipher_bits_before_connect(self): """ - :py:obj:`Connection.get_cipher_bits` returns the number of secret bits of the currently - used cipher or :py:obj:`None` if no connection has been established. + :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` + if no connection has been established. """ - # if connection is not established Connection.cipher returns None. ctx = Context(TLSv1_METHOD) conn = Connection(ctx, None) - self.assertEqual(conn.get_cipher_bits(), None) + self.assertIs(conn.get_cipher_bits(), None) + def test_get_cipher_bits(self): + """ + :py:obj:`Connection.get_cipher_bits` returns the number of secret bits of the currently + used cipher. + """ server, client = self._loopback() server_cipher_bits, client_cipher_bits = \ server.get_cipher_bits(), client.get_cipher_bits() - self.assertTrue(isinstance(server_cipher_bits, int)) - self.assertTrue(isinstance(client_cipher_bits, int)) + self.assertIsInstance(server_cipher_bits, int) + self.assertIsInstance(client_cipher_bits, int) self.assertEqual(server_cipher_bits, client_cipher_bits) diff --git a/doc/api/ssl.rst b/doc/api/ssl.rst index b506757..570fa7d 100644 --- a/doc/api/ssl.rst +++ b/doc/api/ssl.rst @@ -765,6 +765,23 @@ Connection objects have the following methods: .. versionadded:: 0.14 +.. py:method:: Connection.get_cipher_name() + + Obtain the name of the currently used cipher. + + .. versionadded:: 0.15 + +.. py:method:: Connection.get_cipher_bits() + + Obtain the number of secret bits of the currently used cipher. + + .. versionadded:: 0.15 + +.. py:method:: Connection.get_cipher_version() + + Obtain the protocol name of the currently used cipher. + + .. versionadded:: 0.15 .. Rubric:: Footnotes diff --git a/setup.py b/setup.py index 058ad7b..3e7605d 100755 --- a/setup.py +++ b/setup.py @@ -34,7 +34,7 @@ setup(name='pyOpenSSL', version=__version__, maintainer_email = 'exarkun@twistedmatrix.com', url = 'https://github.com/pyca/pyopenssl', license = 'APL2', - install_requires=["cryptography>=0.2.1", "six>=1.5.2"], + install_requires=["cryptography>=0.2.2", "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 -- cgit v1.2.1 From 9bf3f5c447f115fb256a0cf266968db132dacbcf Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Thu, 13 Mar 2014 22:43:54 -0400 Subject: test against the cryptography master --- .travis.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.travis.yml b/.travis.yml index 68149b4..a8535d1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,17 @@ python: - "3.2" - "3.3" +matrix: + include: + - python: "2.7" + env: CRYPTOGRAPHY_GIT_MASTER=true + allow_failures: + - python: "2.7" + env: CRYPTOGRAPHY_GIT_MASTER=true + +before_install: + - if [ -n "$CRYPTOGRAPHY_GIT_MASTER" ]; then pip install git+https://github.com/pyca/cryptography.git;fi + install: # Install the wheel library explicitly here. It is not really a setup # dependency. It is not an install dependency. It is only a dependency for -- cgit v1.2.1 From 680ba5fe98eb1ad15a2fa9c3e8c79dc1dd5a6f69 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Thu, 13 Mar 2014 22:53:09 -0400 Subject: only one thing is allowed to fail --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index a8535d1..f29af2d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,8 +16,7 @@ matrix: - python: "2.7" env: CRYPTOGRAPHY_GIT_MASTER=true allow_failures: - - python: "2.7" - env: CRYPTOGRAPHY_GIT_MASTER=true + - env: CRYPTOGRAPHY_GIT_MASTER=true before_install: - if [ -n "$CRYPTOGRAPHY_GIT_MASTER" ]; then pip install git+https://github.com/pyca/cryptography.git;fi -- cgit v1.2.1 From 82285ecf6a4c734c9ee49687790ca8b3bbd6a80f Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Thu, 13 Mar 2014 22:54:56 -0400 Subject: test all versions of python with master cryptography --- .travis.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.travis.yml b/.travis.yml index f29af2d..52f1032 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,8 +13,16 @@ python: matrix: include: + - python: "2.6" + env: CRYPTOGRAPHY_GIT_MASTER=true - python: "2.7" env: CRYPTOGRAPHY_GIT_MASTER=true + - python: "3.2" + env: CRYPTOGRAPHY_GIT_MASTER=true + - python: "3.3" + env: CRYPTOGRAPHY_GIT_MASTER=true + - python: "pypy" + env: CRYPTOGRAPHY_GIT_MASTER=true allow_failures: - env: CRYPTOGRAPHY_GIT_MASTER=true -- cgit v1.2.1 From 290aba132f8b1f681671765849bc50576b070f3d Mon Sep 17 00:00:00 2001 From: Laurens Van Houtven <_@lvh.cc> Date: Fri, 14 Mar 2014 15:20:18 +0100 Subject: Add a basic contribution guide --- CONTRIBUTING.md | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..28359b0 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,46 @@ +# Contributing + +First of all, thank you for your interest in contributing to +PyOpenSSL! + +## Filing bug reports + +Bug reports are very welcome. Please file them on the Github issue +tracker. Good bug reports come with extensive descriptions of the +error and how to reproduce it. Reporters are strongly encouraged to +include an [SSCCE](http://www.sscce.org/). + +## Patches + +All patches to PyOpenSSL should be submitted in the form of pull +requests to the main PyOpenSSL repository, `pyca/pyopenssl`. These +pull requests should satisfy the following properties: + +- Pull requests that involve code must follow the + [Twisted Coding Standard][tcs]. For example, `methodNamesLikeThis`, + three empty lines between module-level elements, and two empty lines + between class-level elements. +- Pull requests that introduce code must test all new behavior they + introduce, as well as previously untested or poorly tested behavior + that they touch. +- Pull requests are not allowed to break existing tests. +- Pull requests that include major changes should note those changes + in the `ChangeLog` text file in the root of the repository. + +Finally, pull requests must be reviewed before merging. This process +is based on [the one from cryptography][cryptography-review]. Everyone +can perform reviews; this is a very valuable way to contribute, and is +highly encouraged. + +All members of the pyca Github organization can merge pull requests, +of course keeping in mind all the requirements detailed in this +document as well as the pyca/cryptography merge requirements. + +The final responsibility for the reviewing of merged code lies with +the person merging it; since PyOpenSSL is obviously a sensitive +project from a security perspective, so reviewers are strongly +encouraged to take this review and merge process very seriously. + +[tcs]: https://twistedmatrix.com/documents/current/core/development/policy/coding-standard.html +"Twisted Coding Standard" +[cryptography-review]: https://cryptography.io/en/latest/development/reviewing-patches/ -- cgit v1.2.1 From dc06b70d7fd542591bba1600941d318cf3e5050c Mon Sep 17 00:00:00 2001 From: Laurens Van Houtven <_@lvh.cc> Date: Sat, 15 Mar 2014 18:11:47 +0100 Subject: Canonical capitalization is pyOpenSSL not PyOpenSSL --- CONTRIBUTING.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 28359b0..34c28ed 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,7 +1,7 @@ # Contributing First of all, thank you for your interest in contributing to -PyOpenSSL! +pyOpenSSL! ## Filing bug reports @@ -12,8 +12,8 @@ include an [SSCCE](http://www.sscce.org/). ## Patches -All patches to PyOpenSSL should be submitted in the form of pull -requests to the main PyOpenSSL repository, `pyca/pyopenssl`. These +All patches to pyOpenSSL should be submitted in the form of pull +requests to the main pyOpenSSL repository, `pyca/pyopenssl`. These pull requests should satisfy the following properties: - Pull requests that involve code must follow the @@ -37,7 +37,7 @@ of course keeping in mind all the requirements detailed in this document as well as the pyca/cryptography merge requirements. The final responsibility for the reviewing of merged code lies with -the person merging it; since PyOpenSSL is obviously a sensitive +the person merging it; since pyOpenSSL is obviously a sensitive project from a security perspective, so reviewers are strongly encouraged to take this review and merge process very seriously. -- cgit v1.2.1 From 5a422984825504381322ade1fa6fbf74078b8831 Mon Sep 17 00:00:00 2001 From: Laurens Van Houtven <_@lvh.cc> Date: Sat, 15 Mar 2014 21:42:31 +0100 Subject: ReStructured Textify --- CONTRIBUTING.md | 46 ---------------------------------------------- CONTRIBUTING.rst | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 46 deletions(-) delete mode 100644 CONTRIBUTING.md create mode 100644 CONTRIBUTING.rst diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 34c28ed..0000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,46 +0,0 @@ -# Contributing - -First of all, thank you for your interest in contributing to -pyOpenSSL! - -## Filing bug reports - -Bug reports are very welcome. Please file them on the Github issue -tracker. Good bug reports come with extensive descriptions of the -error and how to reproduce it. Reporters are strongly encouraged to -include an [SSCCE](http://www.sscce.org/). - -## Patches - -All patches to pyOpenSSL should be submitted in the form of pull -requests to the main pyOpenSSL repository, `pyca/pyopenssl`. These -pull requests should satisfy the following properties: - -- Pull requests that involve code must follow the - [Twisted Coding Standard][tcs]. For example, `methodNamesLikeThis`, - three empty lines between module-level elements, and two empty lines - between class-level elements. -- Pull requests that introduce code must test all new behavior they - introduce, as well as previously untested or poorly tested behavior - that they touch. -- Pull requests are not allowed to break existing tests. -- Pull requests that include major changes should note those changes - in the `ChangeLog` text file in the root of the repository. - -Finally, pull requests must be reviewed before merging. This process -is based on [the one from cryptography][cryptography-review]. Everyone -can perform reviews; this is a very valuable way to contribute, and is -highly encouraged. - -All members of the pyca Github organization can merge pull requests, -of course keeping in mind all the requirements detailed in this -document as well as the pyca/cryptography merge requirements. - -The final responsibility for the reviewing of merged code lies with -the person merging it; since pyOpenSSL is obviously a sensitive -project from a security perspective, so reviewers are strongly -encouraged to take this review and merge process very seriously. - -[tcs]: https://twistedmatrix.com/documents/current/core/development/policy/coding-standard.html -"Twisted Coding Standard" -[cryptography-review]: https://cryptography.io/en/latest/development/reviewing-patches/ diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst new file mode 100644 index 0000000..16b6b51 --- /dev/null +++ b/CONTRIBUTING.rst @@ -0,0 +1,47 @@ +Contributing +============ + +First of all, thank you for your interest in contributing to +pyOpenSSL! + +Filing bug reports +------------------ + +Bug reports are very welcome. Please file them on the Github issue +tracker. Good bug reports come with extensive descriptions of the +error and how to reproduce it. Reporters are strongly encouraged to +include an `SSCCE `_. + +Patches +------- + +All patches to pyOpenSSL should be submitted in the form of pull +requests to the main pyOpenSSL repository, ``pyca/pyopenssl``. These +pull requests should satisfy the following properties: + +- Pull requests that involve code must follow the + `Twisted Coding Standard`_. For example, ``methodNamesLikeThis``, + three empty lines between module-level elements, and two empty lines + between class-level elements. +- Pull requests that introduce code must test all new behavior they + introduce, as well as previously untested or poorly tested behavior + that they touch. +- Pull requests are not allowed to break existing tests. +- Pull requests that introduce features or fix bugs should note those + changes in the ``ChangeLog`` text file in the root of the repository. + +Finally, pull requests must be reviewed before merging. This process +mirrors the `cryptography code review process`_. Everyone can perform +reviews; this is a very valuable way to contribute, and is highly +encouraged. + +All members of the pyca Github organization can merge pull requests, +of course keeping in mind all the requirements detailed in this +document as well as the pyca/cryptography merge requirements. + +The final responsibility for the reviewing of merged code lies with +the person merging it; since pyOpenSSL is obviously a sensitive +project from a security perspective, so reviewers are strongly +encouraged to take this review and merge process very seriously. + +.. _cryptography code review process: https://cryptography.io/en/latest/development/reviewing-patches/ -- cgit v1.2.1 From df531cc9559a8aea37438fee13359333962279b3 Mon Sep 17 00:00:00 2001 From: Laurens Van Houtven <_@lvh.cc> Date: Sat, 15 Mar 2014 21:48:53 +0100 Subject: Mention changes should be documented --- CONTRIBUTING.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 16b6b51..c43a1c7 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -28,7 +28,9 @@ pull requests should satisfy the following properties: that they touch. - Pull requests are not allowed to break existing tests. - Pull requests that introduce features or fix bugs should note those - changes in the ``ChangeLog`` text file in the root of the repository. + changes in the ``ChangeLog`` text file in the root of the + repository. They should also document the changes, both in + docstrings and in the documentation in the ``doc/`` directory. Finally, pull requests must be reviewed before merging. This process mirrors the `cryptography code review process`_. Everyone can perform -- cgit v1.2.1 From 757807eea64120e4d19a4b0c8fe036f578a55ce7 Mon Sep 17 00:00:00 2001 From: Laurens Van Houtven <_@lvh.cc> Date: Sat, 15 Mar 2014 21:49:03 +0100 Subject: PEP8 + exceptions, not TCS --- CONTRIBUTING.rst | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index c43a1c7..1827d48 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -19,10 +19,12 @@ All patches to pyOpenSSL should be submitted in the form of pull requests to the main pyOpenSSL repository, ``pyca/pyopenssl``. These pull requests should satisfy the following properties: -- Pull requests that involve code must follow the - `Twisted Coding Standard`_. For example, ``methodNamesLikeThis``, - three empty lines between module-level elements, and two empty lines - between class-level elements. +- Code should mostly follow `PEP 8`_, especially in the "do what code + around you does" sense. One notable way pyOpenSSL code differs, for + example, is that there should be three empty lines between + module-level elements, and two empty lines between class-level + elements. Methods and functions are named in ``snake_case``. Follow + OpenSSL naming for callables whenever possible is preferred. - Pull requests that introduce code must test all new behavior they introduce, as well as previously untested or poorly tested behavior that they touch. @@ -46,4 +48,5 @@ the person merging it; since pyOpenSSL is obviously a sensitive project from a security perspective, so reviewers are strongly encouraged to take this review and merge process very seriously. +.. _PEP 8: http://legacy.python.org/dev/peps/pep-0008/ .. _cryptography code review process: https://cryptography.io/en/latest/development/reviewing-patches/ -- cgit v1.2.1 From 36a2665853e020e1cd94592213733e1289303bde Mon Sep 17 00:00:00 2001 From: Laurens Van Houtven <_@lvh.cc> Date: Sat, 15 Mar 2014 21:52:25 +0100 Subject: Semantic linefeeds --- CONTRIBUTING.rst | 60 ++++++++++++++++++++++---------------------------------- 1 file changed, 23 insertions(+), 37 deletions(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 1827d48..f9ac512 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -1,52 +1,38 @@ Contributing ============ -First of all, thank you for your interest in contributing to -pyOpenSSL! +First of all, thank you for your interest in contributing to pyOpenSSL! Filing bug reports ------------------ -Bug reports are very welcome. Please file them on the Github issue -tracker. Good bug reports come with extensive descriptions of the -error and how to reproduce it. Reporters are strongly encouraged to -include an `SSCCE `_. +Bug reports are very welcome. +Please file them on the Github issue tracker. +Good bug reports come with extensive descriptions of the error and how to reproduce it. +Reporters are strongly encouraged to include an `SSCCE `_. Patches ------- -All patches to pyOpenSSL should be submitted in the form of pull -requests to the main pyOpenSSL repository, ``pyca/pyopenssl``. These -pull requests should satisfy the following properties: - -- Code should mostly follow `PEP 8`_, especially in the "do what code - around you does" sense. One notable way pyOpenSSL code differs, for - example, is that there should be three empty lines between - module-level elements, and two empty lines between class-level - elements. Methods and functions are named in ``snake_case``. Follow - OpenSSL naming for callables whenever possible is preferred. -- Pull requests that introduce code must test all new behavior they - introduce, as well as previously untested or poorly tested behavior - that they touch. +All patches to pyOpenSSL should be submitted in the form of pull requests to the main pyOpenSSL repository, ``pyca/pyopenssl``. +These pull requests should satisfy the following properties: + +- Code should follow `PEP 8`_, especially in the "do what code around you does" sense. + One notable way pyOpenSSL code differs, for example, is that there should be three empty lines between module-level elements, and two empty lines between class-level elements. + Methods and functions are named in ``snake_case``. + Follow OpenSSL naming for callables whenever possible is preferred. +- Pull requests that introduce code must test all new behavior they introduce, as well as previously untested or poorly tested behavior that they touch. - Pull requests are not allowed to break existing tests. -- Pull requests that introduce features or fix bugs should note those - changes in the ``ChangeLog`` text file in the root of the - repository. They should also document the changes, both in - docstrings and in the documentation in the ``doc/`` directory. - -Finally, pull requests must be reviewed before merging. This process -mirrors the `cryptography code review process`_. Everyone can perform -reviews; this is a very valuable way to contribute, and is highly -encouraged. - -All members of the pyca Github organization can merge pull requests, -of course keeping in mind all the requirements detailed in this -document as well as the pyca/cryptography merge requirements. - -The final responsibility for the reviewing of merged code lies with -the person merging it; since pyOpenSSL is obviously a sensitive -project from a security perspective, so reviewers are strongly -encouraged to take this review and merge process very seriously. +- Pull requests that introduce features or fix bugs should note those changes in the ``ChangeLog`` text file in the root of the repository. + They should also document the changes, both in docstrings and in the documentation in the ``doc/`` directory. + +Finally, pull requests must be reviewed before merging. +This process mirrors the `cryptography code review process`_. +Everyone can perform reviews; this is a very valuable way to contribute, and is highly encouraged. + +All members of the pyca Github organization can merge pull requests, of course keeping in mind all the requirements detailed in this document as well as the pyca/cryptography merge requirements. + +The final responsibility for the reviewing of merged code lies with the person merging it; since pyOpenSSL is obviously a sensitive project from a security perspective, so reviewers are strongly encouraged to take this review and merge process very seriously. .. _PEP 8: http://legacy.python.org/dev/peps/pep-0008/ .. _cryptography code review process: https://cryptography.io/en/latest/development/reviewing-patches/ -- cgit v1.2.1 From 83b3e09d68e1fb08be469f0150e2da1a30abfce5 Mon Sep 17 00:00:00 2001 From: Laurens Van Houtven <_@lvh.cc> Date: Sun, 16 Mar 2014 15:06:24 +0100 Subject: pyopenssl-committers --- CONTRIBUTING.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index f9ac512..4495381 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -30,7 +30,8 @@ Finally, pull requests must be reviewed before merging. This process mirrors the `cryptography code review process`_. Everyone can perform reviews; this is a very valuable way to contribute, and is highly encouraged. -All members of the pyca Github organization can merge pull requests, of course keeping in mind all the requirements detailed in this document as well as the pyca/cryptography merge requirements. +Pull requests are merged by members of the `pyopenssl-committers team `_. +They should, of course, keep all the requirements detailed in this document as well as the pyca/cryptography merge requirements in mind. The final responsibility for the reviewing of merged code lies with the person merging it; since pyOpenSSL is obviously a sensitive project from a security perspective, so reviewers are strongly encouraged to take this review and merge process very seriously. -- cgit v1.2.1 From 0679a69b4da8929f2c794c7190be0a2df7c7329e Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Sun, 16 Mar 2014 10:17:09 -0400 Subject: minor tweaks --- CONTRIBUTING.rst | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 4495381..1bfa8f9 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -9,7 +9,7 @@ Filing bug reports Bug reports are very welcome. Please file them on the Github issue tracker. Good bug reports come with extensive descriptions of the error and how to reproduce it. -Reporters are strongly encouraged to include an `SSCCE `_. +Reporters are strongly encouraged to include an `short, self contained, correct example `_. Patches ------- @@ -17,11 +17,14 @@ Patches All patches to pyOpenSSL should be submitted in the form of pull requests to the main pyOpenSSL repository, ``pyca/pyopenssl``. These pull requests should satisfy the following properties: +- The branch referenced should be a feature branch focusing on one particular improvement to pyOpenSSL. + Create different branches and different pull requests for unrelated features or bugfixes. +- The branch referenced should have a distinctive name (in particular, please do not open pull requests for your ``master`` branch). - Code should follow `PEP 8`_, especially in the "do what code around you does" sense. - One notable way pyOpenSSL code differs, for example, is that there should be three empty lines between module-level elements, and two empty lines between class-level elements. + One notable way pyOpenSSL code differs, for example, is that there should be three empty lines between module-level elements,and two empty lines between class-level elements. Methods and functions are named in ``snake_case``. Follow OpenSSL naming for callables whenever possible is preferred. -- Pull requests that introduce code must test all new behavior they introduce, as well as previously untested or poorly tested behavior that they touch. +- Pull requests that introduce code must test all new behavior they introduce as well as for previously untested or poorly tested behavior that they touch. - Pull requests are not allowed to break existing tests. - Pull requests that introduce features or fix bugs should note those changes in the ``ChangeLog`` text file in the root of the repository. They should also document the changes, both in docstrings and in the documentation in the ``doc/`` directory. -- cgit v1.2.1 From 433d4bdbc9ae60e367a3dec4f5dfda9fbf61ec89 Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Sun, 16 Mar 2014 10:46:16 -0400 Subject: linkify feature branch --- CONTRIBUTING.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 1bfa8f9..a4040e4 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -17,7 +17,7 @@ Patches All patches to pyOpenSSL should be submitted in the form of pull requests to the main pyOpenSSL repository, ``pyca/pyopenssl``. These pull requests should satisfy the following properties: -- The branch referenced should be a feature branch focusing on one particular improvement to pyOpenSSL. +- The branch referenced should be a `feature branch`_ focusing on one particular improvement to pyOpenSSL. Create different branches and different pull requests for unrelated features or bugfixes. - The branch referenced should have a distinctive name (in particular, please do not open pull requests for your ``master`` branch). - Code should follow `PEP 8`_, especially in the "do what code around you does" sense. @@ -40,3 +40,4 @@ The final responsibility for the reviewing of merged code lies with the person m .. _PEP 8: http://legacy.python.org/dev/peps/pep-0008/ .. _cryptography code review process: https://cryptography.io/en/latest/development/reviewing-patches/ +.. _feature branch: http://nvie.com/posts/a-successful-git-branching-model/ -- cgit v1.2.1 From b1719a9d191eae3803b36c5464ebe72d57ae4fad Mon Sep 17 00:00:00 2001 From: Fedor Brunner Date: Tue, 25 Mar 2014 08:36:09 +0100 Subject: Replace assertIs with assertTrue, because assertIs is not supported in Python 2.6 --- OpenSSL/test/test_ssl.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSSL/test/test_ssl.py b/OpenSSL/test/test_ssl.py index 4c2dff5..535c935 100644 --- a/OpenSSL/test/test_ssl.py +++ b/OpenSSL/test/test_ssl.py @@ -1939,7 +1939,7 @@ class ConnectionTests(TestCase, _LoopbackMixin): """ ctx = Context(TLSv1_METHOD) conn = Connection(ctx, None) - self.assertIs(conn.get_cipher_name(), None) + self.assertTrue(conn.get_cipher_name() is None) def test_get_cipher_name(self): """ @@ -1962,7 +1962,7 @@ class ConnectionTests(TestCase, _LoopbackMixin): """ ctx = Context(TLSv1_METHOD) conn = Connection(ctx, None) - self.assertIs(conn.get_cipher_version(), None) + self.assertTrue(conn.get_cipher_version() is None) def test_get_cipher_version(self): """ @@ -1985,7 +1985,7 @@ class ConnectionTests(TestCase, _LoopbackMixin): """ ctx = Context(TLSv1_METHOD) conn = Connection(ctx, None) - self.assertIs(conn.get_cipher_bits(), None) + self.assertTrue(conn.get_cipher_bits() is None) def test_get_cipher_bits(self): """ -- cgit v1.2.1 From 65627a2d9216fe5e7bc398fee577c3a27f50198a Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Tue, 25 Mar 2014 20:58:30 -0400 Subject: Apply the changeset from https://code.launchpad.net/~redtoad/pyopenssl/pyopenssl/+merge/178226 by Sebastian Rahlf --- OpenSSL/test/test_tsafe.py | 35 +++++++++++++++++++++++++++++++++++ OpenSSL/tsafe.py | 2 +- 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 OpenSSL/test/test_tsafe.py diff --git a/OpenSSL/test/test_tsafe.py b/OpenSSL/test/test_tsafe.py new file mode 100644 index 0000000..425f4e6 --- /dev/null +++ b/OpenSSL/test/test_tsafe.py @@ -0,0 +1,35 @@ + +""" +Unit tests for :py:obj:`OpenSSL.tsafe`. +""" + +from OpenSSL import tsafe +from OpenSSL.SSL import SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD +from OpenSSL.SSL import Context +from OpenSSL.test.util import TestCase, bytes, b +from OpenSSL.test.test_ssl import _create_certificate_chain + + +class ConnectionTest(TestCase): + """ + Unit tests for :py:obj:`OpenSSL.tsafe.Connection`. + """ + + def test_instantiating_works_under_all_supported_Python_versions(self): + """ + At least one library (namely `Werkzeug`_) is instantiating + :py:obj:`Connection` directly which previously did not work under + Python 3 (Bug #1211834: Python 3 Code Uses "apply" function). + + .. _Werkzeug: http://werkzeug.pocoo.org + """ + chain = _create_certificate_chain() + [(_, _), (ikey, icert), (skey, scert)] = chain + + # Create the server context + ctx = Context(TLSv1_METHOD) + ctx.use_privatekey(skey) + ctx.use_certificate(scert) + + # The following line should not throw an error + socket = tsafe.Connection(ctx, None) diff --git a/OpenSSL/tsafe.py b/OpenSSL/tsafe.py index 9d7ad2f..3a9c710 100644 --- a/OpenSSL/tsafe.py +++ b/OpenSSL/tsafe.py @@ -8,7 +8,7 @@ del threading class Connection: def __init__(self, *args): - self._ssl_conn = apply(_ssl.Connection, args) + self._ssl_conn = _ssl.Connection(*args) self._lock = _RLock() for f in ('get_context', 'pending', 'send', 'write', 'recv', 'read', -- cgit v1.2.1 From a566e4e11bbe960197f0d1fe2f0b21b169e47a9c Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Tue, 25 Mar 2014 21:01:10 -0400 Subject: pyflakes and documentation cleanups --- OpenSSL/test/test_tsafe.py | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/OpenSSL/test/test_tsafe.py b/OpenSSL/test/test_tsafe.py index 425f4e6..5e0063b 100644 --- a/OpenSSL/test/test_tsafe.py +++ b/OpenSSL/test/test_tsafe.py @@ -1,27 +1,23 @@ +# Copyright (C) Jean-Paul Calderone +# See LICENSE for details. """ Unit tests for :py:obj:`OpenSSL.tsafe`. """ -from OpenSSL import tsafe -from OpenSSL.SSL import SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD -from OpenSSL.SSL import Context -from OpenSSL.test.util import TestCase, bytes, b +from OpenSSL.SSL import TLSv1_METHOD, Context +from OpenSSL.tsafe import Connection +from OpenSSL.test.util import TestCase from OpenSSL.test.test_ssl import _create_certificate_chain class ConnectionTest(TestCase): """ - Unit tests for :py:obj:`OpenSSL.tsafe.Connection`. + Tests for :py:obj:`OpenSSL.tsafe.Connection`. """ - - def test_instantiating_works_under_all_supported_Python_versions(self): + def test_instantiation(self): """ - At least one library (namely `Werkzeug`_) is instantiating - :py:obj:`Connection` directly which previously did not work under - Python 3 (Bug #1211834: Python 3 Code Uses "apply" function). - - .. _Werkzeug: http://werkzeug.pocoo.org + :py:obj:`OpenSSL.tsafe.Connection` can be instantiated. """ chain = _create_certificate_chain() [(_, _), (ikey, icert), (skey, scert)] = chain @@ -31,5 +27,7 @@ class ConnectionTest(TestCase): ctx.use_privatekey(skey) ctx.use_certificate(scert) - # The following line should not throw an error - socket = tsafe.Connection(ctx, None) + # The following line should not throw an error. This isn't an ideal + # test. It would be great to refactor the other Connection tests so + # they could automatically be applied to this class too. + Connection(ctx, None) -- cgit v1.2.1 From 5bfdea35063a84eee07f45fa00daacaa5639e6dd Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Tue, 25 Mar 2014 21:01:53 -0400 Subject: Further simplifications. --- OpenSSL/test/test_tsafe.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/OpenSSL/test/test_tsafe.py b/OpenSSL/test/test_tsafe.py index 5e0063b..0456957 100644 --- a/OpenSSL/test/test_tsafe.py +++ b/OpenSSL/test/test_tsafe.py @@ -8,7 +8,6 @@ Unit tests for :py:obj:`OpenSSL.tsafe`. from OpenSSL.SSL import TLSv1_METHOD, Context from OpenSSL.tsafe import Connection from OpenSSL.test.util import TestCase -from OpenSSL.test.test_ssl import _create_certificate_chain class ConnectionTest(TestCase): @@ -19,15 +18,7 @@ class ConnectionTest(TestCase): """ :py:obj:`OpenSSL.tsafe.Connection` can be instantiated. """ - chain = _create_certificate_chain() - [(_, _), (ikey, icert), (skey, scert)] = chain - - # Create the server context - ctx = Context(TLSv1_METHOD) - ctx.use_privatekey(skey) - ctx.use_certificate(scert) - # The following line should not throw an error. This isn't an ideal # test. It would be great to refactor the other Connection tests so # they could automatically be applied to this class too. - Connection(ctx, None) + Connection(Context(TLSv1_METHOD), None) -- cgit v1.2.1 From d735ae8534e664ceeb8f14ef073eda2f5a23e66c Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Tue, 25 Mar 2014 21:03:42 -0400 Subject: Add a changelog entry Fixes #48 --- ChangeLog | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ChangeLog b/ChangeLog index 873c1c4..2451dfd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2014-03-28 Jean-Paul Calderone + + * OpenSSL/tsafe.py: Replace the use of ``apply`` (which has been + removed in Python 3) with the equivalent syntax. + 2014-03-02 Stephen Holsapple * OpenSSL/crypto.py: Add ``get_extensions`` method to ``X509Req``. -- cgit v1.2.1 From 416f4a1d5cfd3c76736ebd68f33c4f76af27568b Mon Sep 17 00:00:00 2001 From: Fedor Brunner Date: Fri, 28 Mar 2014 13:18:38 +0100 Subject: Added dependency for cryptography>=0.3. Test split into multiple methods. Added changelog entry. If you use these methods to implement TLS channel binding (RFC 5929) disable session resumption because triple handshake attacks against TLS. https://www.ietf.org/mail-archive/web/tls/current/msg11337.html https://secure-resumption.com/tlsauth.pdf --- ChangeLog | 9 +++++++++ OpenSSL/SSL.py | 10 ++++++++-- OpenSSL/test/test_ssl.py | 46 +++++++++++++++++++++++++++++++++++++++++----- doc/api/ssl.rst | 13 +++++++++++++ setup.py | 2 +- 5 files changed, 72 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 873c1c4..c37fa8a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2014-03-28 Fedor Brunner + + * OpenSSL/ssl.py: Add ``get_finished``, ``get_peer_finished`` + methods to ``Connection``. If you use these methods to + implement TLS channel binding (RFC 5929) disable session + resumption because triple handshake attacks against TLS. + + + 2014-03-02 Stephen Holsapple * OpenSSL/crypto.py: Add ``get_extensions`` method to ``X509Req``. diff --git a/OpenSSL/SSL.py b/OpenSSL/SSL.py index e4d2d3b..41d764d 100644 --- a/OpenSSL/SSL.py +++ b/OpenSSL/SSL.py @@ -1421,7 +1421,10 @@ class Connection(object): """ Obtain latest Finished message that we sent. - :return: A string representing the Finished message + :return: The Finished message or :py:obj:`None` if the TLS handshake + is not completed. + :rtype: :py:data:`bytes` + """ # The size of Finished message is 12 bytes in TLS, # 36 bytes in SSL protocol, but let's be safe with @@ -1438,7 +1441,10 @@ class Connection(object): """ Obtain latest Finished message that we expected from peer. - :return: A string representing the Finished message + :return: The Finished message or :py:obj:`None` if the TLS handshake + is not completed. + :rtype: :py:data:`bytes` + """ # Same buffer size as in get_finished bufsiz = 128 diff --git a/OpenSSL/test/test_ssl.py b/OpenSSL/test/test_ssl.py index 8861972..5af8d86 100644 --- a/OpenSSL/test/test_ssl.py +++ b/OpenSSL/test/test_ssl.py @@ -1932,25 +1932,61 @@ class ConnectionTests(TestCase, _LoopbackMixin): # XXX want_read - def test_finished(self): + def test_get_finished_before_connect(self): """ - :py:obj:`Connection.get_finished` and :py:obj:`Connection.get_peer_finished` - methods return the TLS Finished messages. Finished messages are send - during TLS handshake. Before handshake :py:obj:`Connection.get_finished` and - :py:obj:`Connection.get_peer_finished` return None. + :py:obj:`Connection.get_finished` returns :py:obj:`None` + before TLS handshake is completed. """ ctx = Context(TLSv1_METHOD) connection = Connection(ctx, None) self.assertEqual(connection.get_finished(), None) + + def test_get_peer_finished_before_connect(self): + """ + :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` + before TLS handshake is completed. + """ + + ctx = Context(TLSv1_METHOD) + connection = Connection(ctx, None) self.assertEqual(connection.get_peer_finished(), None) + def test_get_finished(self): + """ + :py:obj:`Connection.get_finished` method returns the TLS Finished + message send from client, or server. Finished messages are send + during TLS handshake. + """ + server, client = self._loopback() self.assertNotEqual(server.get_finished(), None) self.assertTrue(len(server.get_finished()) > 0) + + def test_get_peer_finished(self): + """ + :py:obj:`Connection.get_peer_finished` method returns the TLS Finished + message received from client, or server. Finished messages are send + during TLS handshake. + """ + + server, client = self._loopback() + + self.assertNotEqual(server.get_peer_finished(), None) self.assertTrue(len(server.get_peer_finished()) > 0) + def test_tls_finished_message_symmetry(self): + """ + The TLS Finished message send by server muss be the TLS Finished message + received by client. + + The TLS Finished message send by client muss be the TLS Finished message + received by server. + """ + + server, client = self._loopback() + self.assertEqual(server.get_finished(), client.get_peer_finished()) self.assertEqual(client.get_finished(), server.get_peer_finished()) diff --git a/doc/api/ssl.rst b/doc/api/ssl.rst index b506757..df21a1d 100644 --- a/doc/api/ssl.rst +++ b/doc/api/ssl.rst @@ -765,6 +765,19 @@ Connection objects have the following methods: .. versionadded:: 0.14 +.. py:method:: Connection.get_finished() + + Obtain latest TLS Finished message that we sent, or :py:obj:`None` if + handshake is not completed. + + .. versionadded:: 0.15 + +.. py:method:: Connection.get_peer_finished() + + Obtain latest TLS Finished message that we expected from peer, or + :py:obj:`None` if handshake is not completed. + + .. versionadded:: 0.15 .. Rubric:: Footnotes diff --git a/setup.py b/setup.py index 058ad7b..f12714d 100755 --- a/setup.py +++ b/setup.py @@ -34,7 +34,7 @@ setup(name='pyOpenSSL', version=__version__, maintainer_email = 'exarkun@twistedmatrix.com', url = 'https://github.com/pyca/pyopenssl', license = 'APL2', - install_requires=["cryptography>=0.2.1", "six>=1.5.2"], + install_requires=["cryptography>=0.3", "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 -- cgit v1.2.1 From dbd76271031f30e6bcd9addb6fdf2cd6fc70e61a Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Sat, 29 Mar 2014 18:09:40 -0400 Subject: whitespace: three blank lines between top-level suites, two blank lines between indented suites --- OpenSSL/SSL.py | 3 +++ OpenSSL/test/test_ssl.py | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/OpenSSL/SSL.py b/OpenSSL/SSL.py index 7e2066c..9a3151d 100644 --- a/OpenSSL/SSL.py +++ b/OpenSSL/SSL.py @@ -1417,6 +1417,7 @@ class Connection(object): if not result: _raise_current_error() + def get_cipher_name(self): """ Obtain the name of the currently used cipher. @@ -1429,6 +1430,7 @@ class Connection(object): else: return _native(_ffi.string(_lib.SSL_CIPHER_get_name(cipher))) + def get_cipher_bits(self): """ Obtain the number of secret bits of the currently used cipher. @@ -1441,6 +1443,7 @@ class Connection(object): else: return _lib.SSL_CIPHER_get_bits(cipher, _ffi.NULL) + def get_cipher_version(self): """ Obtain the protocol name of the currently used cipher. diff --git a/OpenSSL/test/test_ssl.py b/OpenSSL/test/test_ssl.py index 535c935..1f9f5c4 100644 --- a/OpenSSL/test/test_ssl.py +++ b/OpenSSL/test/test_ssl.py @@ -1941,6 +1941,7 @@ class ConnectionTests(TestCase, _LoopbackMixin): conn = Connection(ctx, None) self.assertTrue(conn.get_cipher_name() is None) + def test_get_cipher_name(self): """ :py:obj:`Connection.get_cipher_name` returns the name of the currently @@ -1955,6 +1956,7 @@ class ConnectionTests(TestCase, _LoopbackMixin): self.assertEqual(server_cipher_name, client_cipher_name) + def test_get_cipher_version_before_connect(self): """ :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` @@ -1964,6 +1966,7 @@ class ConnectionTests(TestCase, _LoopbackMixin): conn = Connection(ctx, None) self.assertTrue(conn.get_cipher_version() is None) + def test_get_cipher_version(self): """ :py:obj:`Connection.get_cipher_version` returns the protocol name of the currently @@ -1978,6 +1981,7 @@ class ConnectionTests(TestCase, _LoopbackMixin): self.assertEqual(server_cipher_version, client_cipher_version) + def test_get_cipher_bits_before_connect(self): """ :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` @@ -1987,6 +1991,7 @@ class ConnectionTests(TestCase, _LoopbackMixin): conn = Connection(ctx, None) self.assertTrue(conn.get_cipher_bits() is None) + def test_get_cipher_bits(self): """ :py:obj:`Connection.get_cipher_bits` returns the number of secret bits of the currently @@ -2001,6 +2006,8 @@ class ConnectionTests(TestCase, _LoopbackMixin): self.assertEqual(server_cipher_bits, client_cipher_bits) + + class ConnectionGetCipherListTests(TestCase): """ Tests for :py:obj:`Connection.get_cipher_list`. -- cgit v1.2.1 From 9e3ccd454e0eb483bbbe1ee3a8ac25dbe2a2ab91 Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Sat, 29 Mar 2014 18:13:36 -0400 Subject: Add return type API documentation. --- OpenSSL/SSL.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/OpenSSL/SSL.py b/OpenSSL/SSL.py index 9a3151d..c6a649b 100644 --- a/OpenSSL/SSL.py +++ b/OpenSSL/SSL.py @@ -1421,8 +1421,10 @@ class Connection(object): def get_cipher_name(self): """ Obtain the name of the currently used cipher. + :returns: The name of the currently used cipher or :py:obj:`None` if no connection has been established. + :rtype: :py:class:`str` or :py:class:`NoneType` """ cipher = _lib.SSL_get_current_cipher(self._ssl) if cipher == _ffi.NULL: @@ -1434,8 +1436,10 @@ class Connection(object): def get_cipher_bits(self): """ Obtain the number of secret bits of the currently used cipher. + :returns: The number of secret bits of the currently used cipher or :py:obj:`None` if no connection has been established. + :rtype: :py:class:`int` or :py:class:`NoneType` """ cipher = _lib.SSL_get_current_cipher(self._ssl) if cipher == _ffi.NULL: @@ -1446,9 +1450,11 @@ class Connection(object): def get_cipher_version(self): """ - Obtain the protocol name of the currently used cipher. + Obtain the protocol version of the currently used cipher. + :returns: The protocol name of the currently used cipher or :py:obj:`None` if no connection has been established. + :rtype: :py:class:`str` or :py:class:`NoneType` """ cipher = _lib.SSL_get_current_cipher(self._ssl) if cipher == _ffi.NULL: -- cgit v1.2.1 From ab04bdcb04a32eb95e13086891e313706358b2ea Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Sat, 29 Mar 2014 18:16:34 -0400 Subject: ChangeLog entry --- ChangeLog | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ChangeLog b/ChangeLog index 873c1c4..7b31cc9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2014-03-29 fedor-brunner + + * OpenSSL/SSL.py: Add ``get_cipher_name``, ``get_cipher_bits``, + and ``get_cipher_version`` to ``Connection``. + 2014-03-02 Stephen Holsapple * OpenSSL/crypto.py: Add ``get_extensions`` method to ``X509Req``. -- cgit v1.2.1 From 069e2bfae12a642c4b82b5258a8cb7edcf523c3b Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Sat, 29 Mar 2014 18:21:58 -0400 Subject: Use assertIdentical instead of the other thing. --- OpenSSL/test/test_ssl.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSSL/test/test_ssl.py b/OpenSSL/test/test_ssl.py index 1f9f5c4..7a8a932 100644 --- a/OpenSSL/test/test_ssl.py +++ b/OpenSSL/test/test_ssl.py @@ -1939,7 +1939,7 @@ class ConnectionTests(TestCase, _LoopbackMixin): """ ctx = Context(TLSv1_METHOD) conn = Connection(ctx, None) - self.assertTrue(conn.get_cipher_name() is None) + self.assertIdentical(conn.get_cipher_name(), None) def test_get_cipher_name(self): @@ -1964,7 +1964,7 @@ class ConnectionTests(TestCase, _LoopbackMixin): """ ctx = Context(TLSv1_METHOD) conn = Connection(ctx, None) - self.assertTrue(conn.get_cipher_version() is None) + self.assertIdentical(conn.get_cipher_version(), None) def test_get_cipher_version(self): @@ -1989,7 +1989,7 @@ class ConnectionTests(TestCase, _LoopbackMixin): """ ctx = Context(TLSv1_METHOD) conn = Connection(ctx, None) - self.assertTrue(conn.get_cipher_bits() is None) + self.assertIdentical(conn.get_cipher_bits(), None) def test_get_cipher_bits(self): -- cgit v1.2.1 From 7f0ded49f108018e0d86b646025cc98bbb1d9e0d Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Sun, 30 Mar 2014 10:34:17 -0400 Subject: Return unicode from these new APIs rather than the native string type. --- OpenSSL/SSL.py | 10 ++++++---- OpenSSL/test/test_ssl.py | 18 +++++++++--------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/OpenSSL/SSL.py b/OpenSSL/SSL.py index d3572dd..4a497f1 100644 --- a/OpenSSL/SSL.py +++ b/OpenSSL/SSL.py @@ -1427,13 +1427,14 @@ class Connection(object): :returns: The name of the currently used cipher or :py:obj:`None` if no connection has been established. - :rtype: :py:class:`str` or :py:class:`NoneType` + :rtype: :py:class:`unicode` or :py:class:`NoneType` """ cipher = _lib.SSL_get_current_cipher(self._ssl) if cipher == _ffi.NULL: return None else: - return _native(_ffi.string(_lib.SSL_CIPHER_get_name(cipher))) + name = _ffi.string(_lib.SSL_CIPHER_get_name(cipher)) + return name.decode("utf-8") def get_cipher_bits(self): @@ -1457,13 +1458,14 @@ class Connection(object): :returns: The protocol name of the currently used cipher or :py:obj:`None` if no connection has been established. - :rtype: :py:class:`str` or :py:class:`NoneType` + :rtype: :py:class:`unicode` or :py:class:`NoneType` """ cipher = _lib.SSL_get_current_cipher(self._ssl) if cipher == _ffi.NULL: return None else: - return _native(_ffi.string(_lib.SSL_CIPHER_get_version(cipher))) + version =_ffi.string(_lib.SSL_CIPHER_get_version(cipher)) + return version.decode("utf-8") diff --git a/OpenSSL/test/test_ssl.py b/OpenSSL/test/test_ssl.py index 7a8a932..406bc04 100644 --- a/OpenSSL/test/test_ssl.py +++ b/OpenSSL/test/test_ssl.py @@ -14,7 +14,7 @@ from os.path import join from unittest import main from weakref import ref -from six import PY3, u +from six import PY3, text_type, u from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM from OpenSSL.crypto import PKey, X509, X509Extension, X509Store @@ -1944,15 +1944,15 @@ class ConnectionTests(TestCase, _LoopbackMixin): def test_get_cipher_name(self): """ - :py:obj:`Connection.get_cipher_name` returns the name of the currently - used cipher. + :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode` + string giving the name of the currently used cipher. """ server, client = self._loopback() server_cipher_name, client_cipher_name = \ server.get_cipher_name(), client.get_cipher_name() - self.assertIsInstance(server_cipher_name, str) - self.assertIsInstance(client_cipher_name, str) + self.assertIsInstance(server_cipher_name, text_type) + self.assertIsInstance(client_cipher_name, text_type) self.assertEqual(server_cipher_name, client_cipher_name) @@ -1969,15 +1969,15 @@ class ConnectionTests(TestCase, _LoopbackMixin): def test_get_cipher_version(self): """ - :py:obj:`Connection.get_cipher_version` returns the protocol name of the currently - used cipher. + :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode` + string giving the protocol name of the currently used cipher. """ server, client = self._loopback() server_cipher_version, client_cipher_version = \ server.get_cipher_version(), client.get_cipher_version() - self.assertIsInstance(server_cipher_version, str) - self.assertIsInstance(client_cipher_version, str) + self.assertIsInstance(server_cipher_version, text_type) + self.assertIsInstance(client_cipher_version, text_type) self.assertEqual(server_cipher_version, client_cipher_version) -- cgit v1.2.1 From ac20956a8f3fbb91fc3cdf4cb2ae1ae384652770 Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Sun, 30 Mar 2014 11:26:32 -0400 Subject: Refactor the implementation to avoid duplication; use the result of the API to determine the proper buffer size to use. --- OpenSSL/SSL.py | 61 +++++++++++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/OpenSSL/SSL.py b/OpenSSL/SSL.py index 6134a10..9fdd3e1 100644 --- a/OpenSSL/SSL.py +++ b/OpenSSL/SSL.py @@ -1421,43 +1421,48 @@ class Connection(object): _raise_current_error() - def get_finished(self): + def _get_finished_message(self, function): """ - Obtain latest Finished message that we sent. + Helper to implement :py:meth:`get_finished` and + :py:meth:`get_peer_finished`. - :return: The Finished message or :py:obj:`None` if the TLS handshake - is not completed. - :rtype: :py:data:`bytes` + :param function: Either :py:data:`SSL_get_finished`: or + :py:data:`SSL_get_peer_finished`. + :return: :py:data:`None` if the desired message has not yet been + received, otherwise the contents of the message. + :rtype: :py:class:`bytes` or :py:class:`NoneType` """ - # The size of Finished message is 12 bytes in TLS, - # 36 bytes in SSL protocol, but let's be safe with - # 128 bytes buffer - bufsiz = 128 - buf = _ffi.new("char[]", bufsiz) - result = _lib.SSL_get_finished(self._ssl, buf, bufsiz) - if result == 0: - return None # no Finished so far - else: - return _ffi.buffer(buf, result)[:] + size = function(self._ssl, _ffi.NULL, 0) + if size == 0: + # No Finished message so far. + return None - def get_peer_finished(self): + buf = _ffi.new("char[]", size) + function(self._ssl, buf, size) + return _ffi.buffer(buf, size)[:] + + + def get_finished(self): """ - Obtain latest Finished message that we expected from peer. + Obtain the latest `handshake finished` message sent to the peer. + + :return: The contents of the message or :py:obj:`None` if the TLS + handshake has not yet completed. + :rtype: :py:class:`bytes` or :py:class:`NoneType` + """ + return self._get_finished_message(_lib.SSL_get_finished) - :return: The Finished message or :py:obj:`None` if the TLS handshake - is not completed. - :rtype: :py:data:`bytes` + def get_peer_finished(self): """ - # Same buffer size as in get_finished - bufsiz = 128 - buf = _ffi.new("char[]", bufsiz) - result = _lib.SSL_get_peer_finished(self._ssl, buf, bufsiz) - if result == 0: - return None # no Finished so far - else: - return _ffi.buffer(buf, result)[:] + Obtain the latest `handshake finished` message received from the peer. + + :return: The contents of the message or :py:obj:`None` if the TLS + handshake has not yet completed. + :rtype: :py:class:`bytes` or :py:class:`NoneType` + """ + return self._get_finished_message(_lib.SSL_get_peer_finished) def get_cipher_name(self): -- cgit v1.2.1 From 76f841527cd1b57ccadd0bd639d02cc598966298 Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Sun, 30 Mar 2014 11:27:25 -0400 Subject: Correct filename. --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index dec311f..e36f2d2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,6 @@ 2014-03-30 Fedor Brunner - * OpenSSL/ssl.py: Add ``get_finished``, ``get_peer_finished`` + * OpenSSL/SSL.py: Add ``get_finished``, ``get_peer_finished`` methods to ``Connection``. If you use these methods to implement TLS channel binding (RFC 5929) disable session resumption because triple handshake attacks against TLS. -- cgit v1.2.1 From 5b05b4851ca9fb36936779971725c98de39232a7 Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Sun, 30 Mar 2014 11:28:54 -0400 Subject: Docstring and whitespace fixes. --- OpenSSL/test/test_ssl.py | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/OpenSSL/test/test_ssl.py b/OpenSSL/test/test_ssl.py index 6c125c1..3ec4b93 100644 --- a/OpenSSL/test/test_ssl.py +++ b/OpenSSL/test/test_ssl.py @@ -1934,29 +1934,29 @@ class ConnectionTests(TestCase, _LoopbackMixin): def test_get_finished_before_connect(self): """ - :py:obj:`Connection.get_finished` returns :py:obj:`None` - before TLS handshake is completed. + :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS + handshake is completed. """ - ctx = Context(TLSv1_METHOD) connection = Connection(ctx, None) self.assertEqual(connection.get_finished(), None) + def test_get_peer_finished_before_connect(self): """ - :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` - before TLS handshake is completed. + :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before + TLS handshake is completed. """ - ctx = Context(TLSv1_METHOD) connection = Connection(ctx, None) self.assertEqual(connection.get_peer_finished(), None) + def test_get_finished(self): """ :py:obj:`Connection.get_finished` method returns the TLS Finished - message send from client, or server. Finished messages are send - during TLS handshake. + message send from client, or server. Finished messages are send during + TLS handshake. """ server, client = self._loopback() @@ -1967,33 +1967,33 @@ class ConnectionTests(TestCase, _LoopbackMixin): def test_get_peer_finished(self): """ :py:obj:`Connection.get_peer_finished` method returns the TLS Finished - message received from client, or server. Finished messages are send - during TLS handshake. + message received from client, or server. Finished messages are send + during TLS handshake. """ - server, client = self._loopback() self.assertNotEqual(server.get_peer_finished(), None) self.assertTrue(len(server.get_peer_finished()) > 0) + def test_tls_finished_message_symmetry(self): """ - The TLS Finished message send by server muss be the TLS Finished message + The TLS Finished message send by server must be the TLS Finished message received by client. - The TLS Finished message send by client muss be the TLS Finished message + The TLS Finished message send by client must be the TLS Finished message received by server. """ - server, client = self._loopback() self.assertEqual(server.get_finished(), client.get_peer_finished()) self.assertEqual(client.get_finished(), server.get_peer_finished()) + def test_get_cipher_name_before_connect(self): """ - :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` - if no connection has been established. + :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no + connection has been established. """ ctx = Context(TLSv1_METHOD) conn = Connection(ctx, None) @@ -2017,8 +2017,8 @@ class ConnectionTests(TestCase, _LoopbackMixin): def test_get_cipher_version_before_connect(self): """ - :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` - if no connection has been established. + :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no + connection has been established. """ ctx = Context(TLSv1_METHOD) conn = Connection(ctx, None) @@ -2042,8 +2042,8 @@ class ConnectionTests(TestCase, _LoopbackMixin): def test_get_cipher_bits_before_connect(self): """ - :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` - if no connection has been established. + :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no + connection has been established. """ ctx = Context(TLSv1_METHOD) conn = Connection(ctx, None) @@ -2052,8 +2052,8 @@ class ConnectionTests(TestCase, _LoopbackMixin): def test_get_cipher_bits(self): """ - :py:obj:`Connection.get_cipher_bits` returns the number of secret bits of the currently - used cipher. + :py:obj:`Connection.get_cipher_bits` returns the number of secret bits + of the currently used cipher. """ server, client = self._loopback() server_cipher_bits, client_cipher_bits = \ -- cgit v1.2.1 From 01af9046022025a6dacac110dd4aed48e7163d63 Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Sun, 30 Mar 2014 11:40:42 -0400 Subject: ... avoid undefined behavior. --- OpenSSL/SSL.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/OpenSSL/SSL.py b/OpenSSL/SSL.py index 9fdd3e1..fbb18f0 100644 --- a/OpenSSL/SSL.py +++ b/OpenSSL/SSL.py @@ -1433,7 +1433,20 @@ class Connection(object): received, otherwise the contents of the message. :rtype: :py:class:`bytes` or :py:class:`NoneType` """ - size = function(self._ssl, _ffi.NULL, 0) + # The OpenSSL documentation says nothing about what might happen if the + # count argument given is zero. Specifically, it doesn't say whether + # the output buffer may be NULL in that case or not. Inspection of the + # implementation reveals that it calls memcpy() unconditionally. + # Section 7.1.4, paragraph 1 of the C standard suggests that + # memcpy(NULL, source, 0) is not guaranteed to produce defined (let + # alone desirable) behavior (though it probably does on just about + # every implementation...) + # + # Allocate a tiny buffer to pass in (instead of just passing NULL as + # one might expect) for the initial call so as to be safe against this + # potentially undefined behavior. + empty = _ffi.new("char[]", 0) + size = function(self._ssl, empty, 0) if size == 0: # No Finished message so far. return None -- cgit v1.2.1 From d979f23035026ddca11053f2accf7e85590d29d6 Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Sun, 30 Mar 2014 11:58:00 -0400 Subject: one more whitespace fix --- OpenSSL/test/test_ssl.py | 1 + 1 file changed, 1 insertion(+) diff --git a/OpenSSL/test/test_ssl.py b/OpenSSL/test/test_ssl.py index 3ec4b93..bfe3114 100644 --- a/OpenSSL/test/test_ssl.py +++ b/OpenSSL/test/test_ssl.py @@ -1964,6 +1964,7 @@ class ConnectionTests(TestCase, _LoopbackMixin): self.assertNotEqual(server.get_finished(), None) self.assertTrue(len(server.get_finished()) > 0) + def test_get_peer_finished(self): """ :py:obj:`Connection.get_peer_finished` method returns the TLS Finished -- cgit v1.2.1 From b5b9322b960ce43b3fced797db995042c74c245d Mon Sep 17 00:00:00 2001 From: Jonathan Giannuzzi Date: Thu, 20 Mar 2014 15:54:29 +0100 Subject: Fix memory leak in _X509_REVOKED_dup The call to X509_REVOKED_new() will create two empty ASN1 structures that were never freed, but simply replaced by a copy. When doing multiple calls to CRL.get_revoked() on a big CRL, this results in a huge memory leak. This change adds two calls to free those empty ASN1 structures before replacing them with the copy. This change requires https://github.com/pyca/cryptography/pull/830 in order to work. --- OpenSSL/crypto.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/OpenSSL/crypto.py b/OpenSSL/crypto.py index ed0b629..65e28d7 100644 --- a/OpenSSL/crypto.py +++ b/OpenSSL/crypto.py @@ -1323,9 +1323,11 @@ def _X509_REVOKED_dup(original): _raise_current_error() if original.serialNumber != _ffi.NULL: + _lib.ASN1_INTEGER_free(copy.serialNumber) copy.serialNumber = _lib.ASN1_INTEGER_dup(original.serialNumber) if original.revocationDate != _ffi.NULL: + _lib.ASN1_TIME_free(copy.revocationDate) copy.revocationDate = _lib.M_ASN1_TIME_dup(original.revocationDate) if original.extensions != _ffi.NULL: -- cgit v1.2.1 From 1ad14afccb8347693883def24bf1d959a5dd7ce5 Mon Sep 17 00:00:00 2001 From: Jonathan Giannuzzi Date: Thu, 20 Mar 2014 16:03:30 +0100 Subject: Changelog entry --- ChangeLog | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ChangeLog b/ChangeLog index b0fd98a..1fa4879 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7,6 +7,9 @@ * OpenSSL/tsafe.py: Replace the use of ``apply`` (which has been removed in Python 3) with the equivalent syntax. +2014-03-20 Jonathan Giannuzzi + + * OpenSSL/crypto.py: Fix memory leak in _X509_REVOKED_dup. 2014-03-02 Stephen Holsapple -- cgit v1.2.1 From 99eff82b9b9ff4c0b21dd8a922d5dba4649b3eee Mon Sep 17 00:00:00 2001 From: Jonathan Giannuzzi Date: Sun, 23 Mar 2014 22:48:41 +0100 Subject: Add a leakcheck test for CRL.get_revoked --- leakcheck/crypto.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/leakcheck/crypto.py b/leakcheck/crypto.py index 6a9af92..d534c57 100644 --- a/leakcheck/crypto.py +++ b/leakcheck/crypto.py @@ -2,9 +2,10 @@ # See LICENSE for details. import sys +import datetime from OpenSSL.crypto import ( - FILETYPE_PEM, TYPE_DSA, Error, PKey, X509, load_privatekey) + FILETYPE_PEM, TYPE_DSA, Error, PKey, X509, load_privatekey, CRL, Revoked) @@ -101,6 +102,27 @@ FCB5K3c2kkTv2KjcCAimjxkE+SBKfHg35W0wB0AWkXpVFO5W/TbHg4tqtkpt/KMn pass + +class Checker_CRL_get_revoked(BaseChecker): + """ + Leak checks for L{CRL.get_revoked}. + """ + def check_get_revoked(self): + """ + Create a CRL object with 1000 Revoked objects, then call the + get_revoked method repeatedly. + """ + crl = CRL() + for serial in xrange(1000): + revoked = Revoked() + revoked.set_serial(str(serial)) + revoked.set_rev_date(datetime.datetime.utcnow().strftime('%Y%m%d%H%M%SZ')) + crl.add_revoked(revoked) + for i in xrange(self.iterations): + crl.get_revoked() + + + def vmsize(): return [x for x in file('/proc/self/status').readlines() if 'VmSize' in x] -- cgit v1.2.1 From 2ee8280a6433503cbb3a50ee602aa1cc706a0ee5 Mon Sep 17 00:00:00 2001 From: Jonathan Giannuzzi Date: Sun, 23 Mar 2014 22:54:31 +0100 Subject: Make sure that lines are not longer than 80 characters --- leakcheck/crypto.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/leakcheck/crypto.py b/leakcheck/crypto.py index d534c57..b07d1f0 100644 --- a/leakcheck/crypto.py +++ b/leakcheck/crypto.py @@ -2,7 +2,7 @@ # See LICENSE for details. import sys -import datetime +from datetime import datetime from OpenSSL.crypto import ( FILETYPE_PEM, TYPE_DSA, Error, PKey, X509, load_privatekey, CRL, Revoked) @@ -116,7 +116,7 @@ class Checker_CRL_get_revoked(BaseChecker): for serial in xrange(1000): revoked = Revoked() revoked.set_serial(str(serial)) - revoked.set_rev_date(datetime.datetime.utcnow().strftime('%Y%m%d%H%M%SZ')) + revoked.set_rev_date(datetime.utcnow().strftime('%Y%m%d%H%M%SZ')) crl.add_revoked(revoked) for i in xrange(self.iterations): crl.get_revoked() -- cgit v1.2.1 From 3b97ec1370de513491ce77667ac0022643ae8147 Mon Sep 17 00:00:00 2001 From: Jonathan Giannuzzi Date: Mon, 24 Mar 2014 00:47:06 +0100 Subject: Remove unneeded calls A serial number and a revocation date do not need to be set for the leak to occur in the current version of pyOpenSSL. --- leakcheck/crypto.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/leakcheck/crypto.py b/leakcheck/crypto.py index b07d1f0..5db5956 100644 --- a/leakcheck/crypto.py +++ b/leakcheck/crypto.py @@ -2,7 +2,6 @@ # See LICENSE for details. import sys -from datetime import datetime from OpenSSL.crypto import ( FILETYPE_PEM, TYPE_DSA, Error, PKey, X509, load_privatekey, CRL, Revoked) @@ -109,15 +108,12 @@ class Checker_CRL_get_revoked(BaseChecker): """ def check_get_revoked(self): """ - Create a CRL object with 1000 Revoked objects, then call the + Create a CRL object with 100 Revoked objects, then call the get_revoked method repeatedly. """ crl = CRL() - for serial in xrange(1000): - revoked = Revoked() - revoked.set_serial(str(serial)) - revoked.set_rev_date(datetime.utcnow().strftime('%Y%m%d%H%M%SZ')) - crl.add_revoked(revoked) + for i in xrange(100): + crl.add_revoked(Revoked()) for i in xrange(self.iterations): crl.get_revoked() -- cgit v1.2.1 From 8e6a64ee4c4373235f52e78bfa56692cf22bbec7 Mon Sep 17 00:00:00 2001 From: Jonathan Giannuzzi Date: Mon, 24 Mar 2014 01:32:58 +0100 Subject: Add a leakcheck test for CRL.add_revoked --- leakcheck/crypto.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/leakcheck/crypto.py b/leakcheck/crypto.py index 5db5956..c52b975 100644 --- a/leakcheck/crypto.py +++ b/leakcheck/crypto.py @@ -102,10 +102,18 @@ FCB5K3c2kkTv2KjcCAimjxkE+SBKfHg35W0wB0AWkXpVFO5W/TbHg4tqtkpt/KMn -class Checker_CRL_get_revoked(BaseChecker): +class Checker_CRL(BaseChecker): """ - Leak checks for L{CRL.get_revoked}. + Leak checks for L{CRL.add_revoked} and L{CRL.get_revoked}. """ + def check_add_revoked(self): + """ + Call the add_revoked method repeatedly on an empty CRL. + """ + for i in xrange(self.iterations * 200): + CRL().add_revoked(Revoked()) + + def check_get_revoked(self): """ Create a CRL object with 100 Revoked objects, then call the -- cgit v1.2.1 From 54c42008e8c0b993388c0b6926f5d3c0a75ef9b0 Mon Sep 17 00:00:00 2001 From: Jonathan Giannuzzi Date: Mon, 24 Mar 2014 01:33:08 +0100 Subject: Add a leakcheck test for _X509_REVOKED_dup --- leakcheck/crypto.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/leakcheck/crypto.py b/leakcheck/crypto.py index c52b975..f5fe2f8 100644 --- a/leakcheck/crypto.py +++ b/leakcheck/crypto.py @@ -4,7 +4,10 @@ import sys from OpenSSL.crypto import ( - FILETYPE_PEM, TYPE_DSA, Error, PKey, X509, load_privatekey, CRL, Revoked) + FILETYPE_PEM, TYPE_DSA, Error, PKey, X509, load_privatekey, CRL, Revoked, + _X509_REVOKED_dup) + +from OpenSSL._util import lib as _lib @@ -127,6 +130,21 @@ class Checker_CRL(BaseChecker): +class Checker_X509_REVOKED_dup(BaseChecker): + """ + Leak checks for :py:obj:`_X509_REVOKED_dup`. + """ + def check_X509_REVOKED_dup(self): + """ + Copy an empty Revoked object repeatedly. The copy is not garbage + collected, therefore it needs to be manually freed. + """ + for i in xrange(self.iterations * 100): + revoked_copy = _X509_REVOKED_dup(Revoked()._revoked) + _lib.X509_REVOKED_free(revoked_copy) + + + def vmsize(): return [x for x in file('/proc/self/status').readlines() if 'VmSize' in x] -- cgit v1.2.1 From 934a5094ff31262364f315551fae338a1725789c Mon Sep 17 00:00:00 2001 From: Jonathan Giannuzzi Date: Fri, 28 Mar 2014 15:58:41 +0100 Subject: Require cryptography 0.3 Require cryptography 0.3 to have the ASN1_TIME_free binding. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 3e7605d..f12714d 100755 --- a/setup.py +++ b/setup.py @@ -34,7 +34,7 @@ setup(name='pyOpenSSL', version=__version__, maintainer_email = 'exarkun@twistedmatrix.com', url = 'https://github.com/pyca/pyopenssl', license = 'APL2', - install_requires=["cryptography>=0.2.2", "six>=1.5.2"], + install_requires=["cryptography>=0.3", "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 -- cgit v1.2.1 From 070c35669d18c6d385b7e14e2eed40e6feb68d65 Mon Sep 17 00:00:00 2001 From: Jonathan Giannuzzi Date: Fri, 28 Mar 2014 15:58:54 +0100 Subject: Changelog entries --- ChangeLog | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 1fa4879..c787255 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7,9 +7,13 @@ * OpenSSL/tsafe.py: Replace the use of ``apply`` (which has been removed in Python 3) with the equivalent syntax. -2014-03-20 Jonathan Giannuzzi + +2014-03-28 Jonathan Giannuzzi * OpenSSL/crypto.py: Fix memory leak in _X509_REVOKED_dup. + * leakcheck/crypto.py: Add checks for _X509_REVOKED_dup, CRL.add_revoked + and CRL.get_revoked. + * setup.py: Require cryptography 0.3 to have the ASN1_TIME_free binding. 2014-03-02 Stephen Holsapple -- cgit v1.2.1 From 6b5028d0b1143bd6e16d7b4ce98878bb6d527d0f Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 31 Mar 2014 14:23:57 -0700 Subject: Removed a stray period --- doc/api/ssl.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/ssl.rst b/doc/api/ssl.rst index 1fed8d3..7c45bc8 100644 --- a/doc/api/ssl.rst +++ b/doc/api/ssl.rst @@ -252,7 +252,7 @@ Context objects have the following methods: .. py:method:: Context.get_cert_store() Retrieve the certificate store (a X509Store object) that the context uses. - This can be used to add "trusted" certificates without using the. + This can be used to add "trusted" certificates without using the :py:meth:`load_verify_locations` method. -- cgit v1.2.1 From 54f0fd037f7e799f3db4750070fc3f0e25645e8b Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Mon, 14 Apr 2014 10:20:49 -0400 Subject: coveralls the thing; --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 52f1032..149ffe4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,6 +29,9 @@ matrix: before_install: - if [ -n "$CRYPTOGRAPHY_GIT_MASTER" ]; then pip install git+https://github.com/pyca/cryptography.git;fi +after_success: + - coveralls + install: # Install the wheel library explicitly here. It is not really a setup # dependency. It is not an install dependency. It is only a dependency for -- cgit v1.2.1 From ba67ab23d6baa60fec922cad24883b239fa8d8be Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Mon, 14 Apr 2014 10:22:05 -0400 Subject: advertise how awesome everything is --- README | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README b/README index 1b2a093..22517a5 100644 --- a/README +++ b/README @@ -7,3 +7,5 @@ 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. + +.. image:: https://coveralls.io/repos/pyca/pyopenssl/badge.png :target: https://coveralls.io/r/pyca/pyopenssl -- cgit v1.2.1 From 99a694826e2476baa69309ffdc061fd240e10e24 Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Mon, 14 Apr 2014 10:43:04 -0400 Subject: Maybe some more travis intergraterations for stuff --- .travis.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 149ffe4..aed1c91 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,5 +39,9 @@ install: # travis. - pip install wheel + # Also install some tools for measuring code coverage and sending the results + to coveralls. + - pip install coveralls coverage + script: - - python setup.py bdist_wheel test + - coverage run --branch --source=OpenSSL setup.py bdist_wheel test -- cgit v1.2.1 From d247c8cbe050a3898da6fbc9a93ee5918e9d2cf3 Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Mon, 14 Apr 2014 10:44:02 -0400 Subject: Also stick a quick summary at the end of every build --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index aed1c91..bff47ae 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,3 +45,4 @@ install: script: - coverage run --branch --source=OpenSSL setup.py bdist_wheel test + - coverage report -m -- cgit v1.2.1 From 3e99442cfcfbe9fe24b49964c0432f447d8ab222 Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Mon, 14 Apr 2014 10:47:18 -0400 Subject: where is my emacs yaml mode --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index bff47ae..cb0eefc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,7 +40,7 @@ install: - pip install wheel # Also install some tools for measuring code coverage and sending the results - to coveralls. + # to coveralls. - pip install coveralls coverage script: -- cgit v1.2.1 From 2bfd11f4903b9cac467f2c7488f8ee236ddc18f5 Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Wed, 16 Apr 2014 18:31:03 -0400 Subject: Fix the rST markup for coveralls. --- README | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README b/README index 22517a5..de9aa4e 100644 --- a/README +++ b/README @@ -8,4 +8,5 @@ See http://github.com/pyca/pyopenssl for development. See https://mail.python.org/mailman/listinfo/pyopenssl-users for the discussion mailing list. -.. image:: https://coveralls.io/repos/pyca/pyopenssl/badge.png :target: https://coveralls.io/r/pyca/pyopenssl +.. image:: https://coveralls.io/repos/pyca/pyopenssl/badge.png + :target: https://coveralls.io/r/pyca/pyopenssl -- cgit v1.2.1 From 9f2ec96d2e92e9ea417a7b4bd8385de8bfcd12bc Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Wed, 16 Apr 2014 18:32:34 -0400 Subject: Make the travis configuration read linearly. --- .travis.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index cb0eefc..0a8bbab 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,9 +29,6 @@ matrix: before_install: - if [ -n "$CRYPTOGRAPHY_GIT_MASTER" ]; then pip install git+https://github.com/pyca/cryptography.git;fi -after_success: - - coveralls - install: # Install the wheel library explicitly here. It is not really a setup # dependency. It is not an install dependency. It is only a dependency for @@ -46,3 +43,9 @@ install: script: - coverage run --branch --source=OpenSSL setup.py bdist_wheel test - coverage report -m + +after_success: + - coveralls + +notifications: + email: false -- cgit v1.2.1 From 8dc60320bfa8d81a5a90f5f4a9957a4e652c6c90 Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Wed, 16 Apr 2014 18:35:16 -0400 Subject: This is a rST file now. --- README | 12 ------------ README.rst | 12 ++++++++++++ 2 files changed, 12 insertions(+), 12 deletions(-) delete mode 100644 README create mode 100644 README.rst diff --git a/README b/README deleted file mode 100644 index de9aa4e..0000000 --- a/README +++ /dev/null @@ -1,12 +0,0 @@ - -pyOpenSSL - A Python wrapper around the OpenSSL library ------------------------------------------------------------------------------- - -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. - -.. image:: https://coveralls.io/repos/pyca/pyopenssl/badge.png - :target: https://coveralls.io/r/pyca/pyopenssl diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..de9aa4e --- /dev/null +++ b/README.rst @@ -0,0 +1,12 @@ + +pyOpenSSL - A Python wrapper around the OpenSSL library +------------------------------------------------------------------------------ + +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. + +.. image:: https://coveralls.io/repos/pyca/pyopenssl/badge.png + :target: https://coveralls.io/r/pyca/pyopenssl -- cgit v1.2.1 From a2d7e09c195f583e4d223489b620c418ca9992e7 Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Thu, 17 Apr 2014 10:07:34 -0400 Subject: take a stab at running tests against openssl 0.9.8 as well --- .travis.yml | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0a8bbab..543dc50 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,6 @@ language: python os: - linux - - osx python: - "pypy" @@ -13,18 +12,33 @@ python: matrix: include: + # Also run the tests against cryptography master. - python: "2.6" - env: CRYPTOGRAPHY_GIT_MASTER=true + env: + CRYPTOGRAPHY_GIT_MASTER=true - python: "2.7" - env: CRYPTOGRAPHY_GIT_MASTER=true + env: + CRYPTOGRAPHY_GIT_MASTER=true - python: "3.2" - env: CRYPTOGRAPHY_GIT_MASTER=true + env: + CRYPTOGRAPHY_GIT_MASTER=true - python: "3.3" - env: CRYPTOGRAPHY_GIT_MASTER=true + env: + CRYPTOGRAPHY_GIT_MASTER=true - python: "pypy" - env: CRYPTOGRAPHY_GIT_MASTER=true + env: + CRYPTOGRAPHY_GIT_MASTER=true + + # Also run at least a little bit against an older version of OpenSSL. + - python: "2.7" + env: + OPENSSL=0.9.8 + + # Let the cryptography master builds fail because they might be triggered by + # cryptography changes beyond our control. allow_failures: - - env: CRYPTOGRAPHY_GIT_MASTER=true + - env: + CRYPTOGRAPHY_GIT_MASTER=true before_install: - if [ -n "$CRYPTOGRAPHY_GIT_MASTER" ]; then pip install git+https://github.com/pyca/cryptography.git;fi @@ -41,8 +55,16 @@ install: - pip install coveralls coverage script: - - coverage run --branch --source=OpenSSL setup.py bdist_wheel test - - coverage report -m + - | + if [[ "${OPENSSL}" == "0.9.8" ]]; then + sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu/ lucid main" + sudo apt-get -y update + sudo apt-get install -y --force-yes libssl-dev/lucid + fi + - | + coverage run --branch --source=OpenSSL setup.py bdist_wheel test + - | + coverage report -m after_success: - coveralls -- cgit v1.2.1 From 3bcc881c6008eb23f3e54c1d8ffd50da4ae71311 Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Thu, 17 Apr 2014 10:20:21 -0400 Subject: That seemed to work but not all of the tests are passing on 0.9.8 so until that happens this configuration will be allowed to fail. --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 543dc50..595e37c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,6 +39,8 @@ matrix: allow_failures: - env: CRYPTOGRAPHY_GIT_MASTER=true + - env: + OPENSSL=0.9.8 before_install: - if [ -n "$CRYPTOGRAPHY_GIT_MASTER" ]; then pip install git+https://github.com/pyca/cryptography.git;fi -- cgit v1.2.1