diff options
author | Jean-Paul Calderone <exarkun@twistedmatrix.com> | 2014-03-30 10:45:00 -0400 |
---|---|---|
committer | Jean-Paul Calderone <exarkun@twistedmatrix.com> | 2014-03-30 10:45:00 -0400 |
commit | 7c556ef6ab9e721b25f2704c306d0ef2dd66dae0 (patch) | |
tree | 13e17d7df7515f2953a9f913feb90bb5ba0a5196 | |
parent | 416f4a1d5cfd3c76736ebd68f33c4f76af27568b (diff) | |
parent | f31707592c248784b2605affa06303a2cb6eb694 (diff) | |
download | pyopenssl-7c556ef6ab9e721b25f2704c306d0ef2dd66dae0.tar.gz |
merge master
-rw-r--r-- | .travis.yml | 27 | ||||
-rw-r--r-- | CONTRIBUTING.rst | 43 | ||||
-rw-r--r-- | ChangeLog | 12 | ||||
-rw-r--r-- | OpenSSL/SSL.py | 55 | ||||
-rw-r--r-- | OpenSSL/test/test_ssl.py | 78 | ||||
-rw-r--r-- | OpenSSL/test/test_tsafe.py | 24 | ||||
-rw-r--r-- | OpenSSL/tsafe.py | 2 | ||||
-rw-r--r-- | doc/api/ssl.rst | 30 | ||||
-rw-r--r-- | setup.cfg | 3 |
9 files changed, 263 insertions, 11 deletions
diff --git a/.travis.yml b/.travis.yml index 659677a..52f1032 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,5 +11,30 @@ python: - "3.2" - "3.3" +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 + +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 + # the script directive below - because we want to exercise wheel building on + # travis. + - pip install wheel + script: - - python setup.py test + - python setup.py bdist_wheel test diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst new file mode 100644 index 0000000..a4040e4 --- /dev/null +++ b/CONTRIBUTING.rst @@ -0,0 +1,43 @@ +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 `short, self contained, correct example <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: + +- 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. + 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 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. + +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. + +Pull requests are merged by members of the `pyopenssl-committers team <https://github.com/orgs/pyca/teams/pyopenssl-committers>`_. +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. + +.. _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/ @@ -1,4 +1,4 @@ -2014-03-28 Fedor Brunner <fedor.brunner@azet.sk> +2014-03-30 Fedor Brunner <fedor.brunner@azet.sk> * OpenSSL/ssl.py: Add ``get_finished``, ``get_peer_finished`` methods to ``Connection``. If you use these methods to @@ -7,6 +7,16 @@ <https://www.ietf.org/mail-archive/web/tls/current/msg11337.html> <https://secure-resumption.com/tlsauth.pdf> +2014-03-29 Fedor Brunner <fedor.brunner@azet.sk> + + * OpenSSL/SSL.py: Add ``get_cipher_name``, ``get_cipher_bits``, + and ``get_cipher_version`` to ``Connection``. + +2014-03-28 Jean-Paul Calderone <exarkun@twistedmatrix.com> + + * OpenSSL/tsafe.py: Replace the use of ``apply`` (which has been + removed in Python 3) with the equivalent syntax. + 2014-03-02 Stephen Holsapple <sholsapp@gmail.com> * OpenSSL/crypto.py: Add ``get_extensions`` method to ``X509Req``. diff --git a/OpenSSL/SSL.py b/OpenSSL/SSL.py index 41d764d..6134a10 100644 --- a/OpenSSL/SSL.py +++ b/OpenSSL/SSL.py @@ -81,7 +81,10 @@ except AttributeError: OP_NO_QUERY_MTU = _lib.SSL_OP_NO_QUERY_MTU OP_COOKIE_EXCHANGE = _lib.SSL_OP_COOKIE_EXCHANGE -OP_NO_TICKET = _lib.SSL_OP_NO_TICKET +try: + OP_NO_TICKET = _lib.SSL_OP_NO_TICKET +except AttributeError: + pass OP_ALL = _lib.SSL_OP_ALL @@ -1417,6 +1420,7 @@ class Connection(object): if not result: _raise_current_error() + def get_finished(self): """ Obtain latest Finished message that we sent. @@ -1455,6 +1459,55 @@ class Connection(object): else: return _ffi.buffer(buf, result)[:] + + 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:`unicode` or :py:class:`NoneType` + """ + cipher = _lib.SSL_get_current_cipher(self._ssl) + if cipher == _ffi.NULL: + return None + else: + name = _ffi.string(_lib.SSL_CIPHER_get_name(cipher)) + return name.decode("utf-8") + + + 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: + return None + else: + return _lib.SSL_CIPHER_get_bits(cipher, _ffi.NULL) + + + def get_cipher_version(self): + """ + 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:`unicode` or :py:class:`NoneType` + """ + cipher = _lib.SSL_get_current_cipher(self._ssl) + if cipher == _ffi.NULL: + return None + else: + version =_ffi.string(_lib.SSL_CIPHER_get_version(cipher)) + return version.decode("utf-8") + + + 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 5af8d86..6c125c1 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 @@ -1990,6 +1990,82 @@ class ConnectionTests(TestCase, _LoopbackMixin): 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. + """ + ctx = Context(TLSv1_METHOD) + conn = Connection(ctx, None) + self.assertIdentical(conn.get_cipher_name(), None) + + + def test_get_cipher_name(self): + """ + :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, text_type) + self.assertIsInstance(client_cipher_name, text_type) + + 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` + if no connection has been established. + """ + ctx = Context(TLSv1_METHOD) + conn = Connection(ctx, None) + self.assertIdentical(conn.get_cipher_version(), None) + + + def test_get_cipher_version(self): + """ + :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, text_type) + self.assertIsInstance(client_cipher_version, text_type) + + 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` + if no connection has been established. + """ + ctx = Context(TLSv1_METHOD) + conn = Connection(ctx, None) + self.assertIdentical(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.assertIsInstance(server_cipher_bits, int) + self.assertIsInstance(client_cipher_bits, int) + + self.assertEqual(server_cipher_bits, client_cipher_bits) + + + class ConnectionGetCipherListTests(TestCase): """ Tests for :py:obj:`Connection.get_cipher_list`. diff --git a/OpenSSL/test/test_tsafe.py b/OpenSSL/test/test_tsafe.py new file mode 100644 index 0000000..0456957 --- /dev/null +++ b/OpenSSL/test/test_tsafe.py @@ -0,0 +1,24 @@ +# Copyright (C) Jean-Paul Calderone +# See LICENSE for details. + +""" +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 + + +class ConnectionTest(TestCase): + """ + Tests for :py:obj:`OpenSSL.tsafe.Connection`. + """ + def test_instantiation(self): + """ + :py:obj:`OpenSSL.tsafe.Connection` can be instantiated. + """ + # 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(Context(TLSv1_METHOD), 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', diff --git a/doc/api/ssl.rst b/doc/api/ssl.rst index df21a1d..dfeb158 100644 --- a/doc/api/ssl.rst +++ b/doc/api/ssl.rst @@ -83,12 +83,6 @@ Context, Connection. :py:const:`OP_NO_*` constant may be undefined. -.. py:data:: MODE_NO_COMPRESSION - - Constant used with :py:meth:`set_mode` of Context objects to disable - automatic compression of application traffic. - - .. py:data:: SSLEAY_VERSION SSLEAY_CFLAGS SSLEAY_BUILT_ON @@ -765,6 +759,7 @@ 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 @@ -772,6 +767,7 @@ Connection objects have the following methods: .. versionadded:: 0.15 + .. py:method:: Connection.get_peer_finished() Obtain latest TLS Finished message that we expected from peer, or @@ -779,6 +775,28 @@ Connection objects have the following methods: .. versionadded:: 0.15 + +.. 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 .. [#connection-context-socket] Actually, all that is required is an object that @@ -1,6 +1,9 @@ [sdist] force_manifest=1 +[wheel] +universal = 1 + # bdist_rpm settings contributed by Mihai Ibanescu <misa@redhat.com> [bdist_rpm] release = 1 |