File 0001-Don-t-use-things-after-they-re-freed.duh-709.patch of Package python-pyOpenSSL.36114
From 4aa52c33d3ee51c632e0e1e10cafb7745fd1028c Mon Sep 17 00:00:00 2001
From: Alex Gaynor <alex.gaynor@gmail.com>
Date: Mon, 20 Nov 2017 09:04:08 -0500
Subject: [PATCH] Don't use things after they're freed...duh (#709)
* Don't use things after they're freed...duh
* changelog
* more details
---
src/OpenSSL/SSL.py | 7 ++-----
src/OpenSSL/crypto.py | 45 ++++++++++++++++++++++++++++++++++++---------
2 files changed, 38 insertions(+), 14 deletions(-)
Index: pyOpenSSL-17.1.0/src/OpenSSL/SSL.py
===================================================================
--- pyOpenSSL-17.1.0.orig/src/OpenSSL/SSL.py
+++ pyOpenSSL-17.1.0/src/OpenSSL/SSL.py
@@ -1956,9 +1956,7 @@ class Connection(object):
"""
cert = _lib.SSL_get_peer_certificate(self._ssl)
if cert != _ffi.NULL:
- pycert = X509.__new__(X509)
- pycert._x509 = _ffi.gc(cert, _lib.X509_free)
- return pycert
+ return X509._from_raw_x509_ptr(cert)
return None
def get_peer_cert_chain(self):
@@ -1976,8 +1974,7 @@ class Connection(object):
for i in range(_lib.sk_X509_num(cert_stack)):
# TODO could incref instead of dup here
cert = _lib.X509_dup(_lib.sk_X509_value(cert_stack, i))
- pycert = X509.__new__(X509)
- pycert._x509 = _ffi.gc(cert, _lib.X509_free)
+ pycert = X509._from_raw_x509_ptr(cert)
result.append(pycert)
return result
Index: pyOpenSSL-17.1.0/src/OpenSSL/crypto.py
===================================================================
--- pyOpenSSL-17.1.0.orig/src/OpenSSL/crypto.py
+++ pyOpenSSL-17.1.0/src/OpenSSL/crypto.py
@@ -174,6 +174,19 @@ def _get_asn1_time(timestamp):
return string_result
+class _X509NameInvalidator(object):
+ def __init__(self):
+ self._names = []
+
+ def add(self, name):
+ self._names.append(name)
+
+ def clear(self):
+ for name in self._names:
+ # Breaks the object, but also prevents UAF!
+ del name._name
+
+
class PKey(object):
"""
A class representing an DSA or RSA public key or key pair.
@@ -1045,6 +1058,17 @@ class X509(object):
_openssl_assert(x509 != _ffi.NULL)
self._x509 = _ffi.gc(x509, _lib.X509_free)
+ self._issuer_invalidator = _X509NameInvalidator()
+ self._subject_invalidator = _X509NameInvalidator()
+
+ @classmethod
+ def _from_raw_x509_ptr(cls, x509):
+ cert = cls.__new__(cls)
+ cert._x509 = _ffi.gc(x509, _lib.X509_free)
+ cert._issuer_invalidator = _X509NameInvalidator()
+ cert._subject_invalidator = _X509NameInvalidator()
+ return cert
+
def to_cryptography(self):
"""
Export as a ``cryptography`` certificate.
@@ -1395,7 +1419,9 @@ class X509(object):
:return: The issuer of this certificate.
:rtype: :class:`X509Name`
"""
- return self._get_name(_lib.X509_get_issuer_name)
+ name = self._get_name(_lib.X509_get_issuer_name)
+ self._issuer_invalidator.add(name)
+ return name
def set_issuer(self, issuer):
"""
@@ -1406,7 +1432,8 @@ class X509(object):
:return: ``None``
"""
- return self._set_name(_lib.X509_set_issuer_name, issuer)
+ self._set_name(_lib.X509_set_issuer_name, issuer)
+ self._issuer_invalidator.clear()
def get_subject(self):
"""
@@ -1420,7 +1447,9 @@ class X509(object):
:return: The subject of this certificate.
:rtype: :class:`X509Name`
"""
- return self._get_name(_lib.X509_get_subject_name)
+ name = self._get_name(_lib.X509_get_subject_name)
+ self._subject_invalidator.add(name)
+ return name
def set_subject(self, subject):
"""
@@ -1431,7 +1460,8 @@ class X509(object):
:return: ``None``
"""
- return self._set_name(_lib.X509_set_subject_name, subject)
+ self._set_name(_lib.X509_set_subject_name, subject)
+ self._subject_invalidator.clear()
def get_extension_count(self):
"""
@@ -1701,8 +1731,7 @@ class X509StoreContext(object):
# 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)
+ pycert = X509._from_raw_x509_ptr(_cert)
return X509StoreContextError(errors, pycert)
def set_store(self, store):
@@ -1761,9 +1790,7 @@ def load_certificate(type, buffer):
if x509 == _ffi.NULL:
_raise_current_error()
- cert = X509.__new__(X509)
- cert._x509 = _ffi.gc(x509, _lib.X509_free)
- return cert
+ return X509._from_raw_x509_ptr(x509)
def dump_certificate(type, cert):