Author timboddy
Recipients timboddy
Date 2018-06-07.12:27:37
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1528374457.54.0.592728768989.issue33795@psf.upfronthosting.co.za>
In-reply-to
Content
I noticed a memory leak /usr/lib/python3.5/site-packages/OpenSSL/crypto.py in the definition of the class X509StoreContext. The problem is that the __init__ function calls self._init() then later the function verify_certificate calls _init() again. In spite of the disclaimer int __init__ about "no adverse effect", the adverse effect here is that if one does two calls to X509_STORE_CTX_init on the same X509_STORE_CTX without any intervening calls to X509_STORE_CTX_cleanup on that same X509_STORE_CTX it will leak one X509_VERIFY_PARAM and one X509_VERIFY_PARAM_ID.

Here is most of the relevant class:

class X509StoreContext(object):
    """
    An X.509 store context.

    An X.509 store context is used to carry out the actual verification process
    of a certificate in a described context. For describing such a context, see
    :class:`X509Store`.

    :ivar _store_ctx: The underlying X509_STORE_CTX structure used by this
        instance. It is dynamically allocated and automatically garbage
        collected.
    :ivar _store: See the ``store`` ``__init__`` parameter.
    :ivar _cert: See the ``certificate`` ``__init__`` parameter.
    :param X509Store store: The certificates which will be trusted for the
        purposes of any verifications.
    :param X509 certificate: The certificate to be verified.
    """

    def __init__(self, store, certificate):
        store_ctx = _lib.X509_STORE_CTX_new()
        self._store_ctx = _ffi.gc(store_ctx, _lib.X509_STORE_CTX_free)
        self._store = store
        self._cert = certificate
        # Make the store context available for use after instantiating this
        # class by initializing it now. Per testing, subsequent calls to
        # :meth:`_init` have no adverse affect.
        self._init()

    def _init(self):
        """
        Set up the store context for a subsequent verification operation.
        """
        Set up the store context for a subsequent verification operation.
        """
        ret = _lib.X509_STORE_CTX_init(
            self._store_ctx, self._store._store, self._cert._x509, _ffi.NULL
        )
        if ret <= 0:
            _raise_current_error()

    def _cleanup(self):
        """
        Internally cleans up the store context.

        The store context can then be reused with a new call to :meth:`_init`.
        """
        _lib.X509_STORE_CTX_cleanup(self._store_ctx)

    def _exception_from_context(self):
        """
        Convert an OpenSSL native context error failure into a Python
        exception.

        When a call to native OpenSSL X509_verify_cert fails, additional
        information about the failure can be obtained from the store context.
        """
        errors = [
            _lib.X509_STORE_CTX_get_error(self._store_ctx),
            _lib.X509_STORE_CTX_get_error_depth(self._store_ctx),
            _native(_ffi.string(_lib.X509_verify_cert_error_string(
                _lib.X509_STORE_CTX_get_error(self._store_ctx)))),
        ]
        # A context error should always be associated with a certificate, so we
        # expect this call to never return :class:`None`.
        _x509 = _lib.X509_STORE_CTX_get_current_cert(self._store_ctx)
        _cert = _lib.X509_dup(_x509)
        pycert = X509.__new__(X509)
        pycert._x509 = _ffi.gc(_cert, _lib.X509_free)
        return X509StoreContextError(errors, pycert)

    def set_store(self, store):
        """
        Set the context's X.509 store.

        .. versionadded:: 0.15

        :param X509Store store: The store description which will be used for
            the purposes of any *future* verifications.
        """
        self._store = store

    def verify_certificate(self):
        """
        Verify a certificate in a context.

        .. versionadded:: 0.15

        :raises X509StoreContextError: If an error occurred when validating a
          certificate in the context. Sets ``certificate`` attribute to
          indicate which certificate caused the error.
        """
        # Always re-initialize the store context in case
        # :meth:`verify_certificate` is called multiple times.
        self._init()
        ret = _lib.X509_verify_cert(self._store_ctx)
        self._cleanup()
        if ret <= 0:
            raise self._exception_from_context()
History
Date User Action Args
2018-06-07 12:27:37timboddysetrecipients: + timboddy
2018-06-07 12:27:37timboddysetmessageid: <1528374457.54.0.592728768989.issue33795@psf.upfronthosting.co.za>
2018-06-07 12:27:37timboddylinkissue33795 messages
2018-06-07 12:27:37timboddycreate