Skip to content

Commit dc798e5

Browse files
committed
Remove X509Extension, which has been deprecated for a year
1 parent a6678a9 commit dc798e5

File tree

4 files changed

+2
-654
lines changed

4 files changed

+2
-654
lines changed

CHANGELOG.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ The third digit is only for regressions.
1010
Backward-incompatible changes:
1111
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1212

13+
- Removed deprecated ``OpenSSL.crypto.X509Extension``, ``OpenSSL.crypto.X509Req.add_extension``, ``OpenSSL.crypto.X509Req.get_extensions``, ``OpenSSL.crypto.X509.add_extension``, ``OpenSSL.crypto.X509.get_extensions``
14+
1315
Deprecations:
1416
^^^^^^^^^^^^^
1517

doc/api/crypto.rst

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -162,16 +162,6 @@ PKey objects
162162
163163
Key type constants.
164164

165-
.. _openssl-509ext:
166-
167-
X509Extension objects
168-
---------------------
169-
170-
.. autoclass:: X509Extension
171-
:members:
172-
:special-members:
173-
:exclude-members: __weakref__
174-
175165
.. _crl:
176166

177167
CRL objects

src/OpenSSL/crypto.py

Lines changed: 0 additions & 319 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,12 @@
44
import datetime
55
import functools
66
import typing
7-
import warnings
87
from base64 import b16encode
98
from functools import partial
109
from os import PathLike
1110
from typing import (
1211
Any,
1312
Callable,
14-
Iterable,
1513
Sequence,
1614
Union,
1715
)
@@ -61,7 +59,6 @@
6159
"Error",
6260
"PKey",
6361
"Revoked",
64-
"X509Extension",
6562
"X509Name",
6663
"X509Req",
6764
"X509Store",
@@ -797,189 +794,6 @@ def get_components(self) -> list[tuple[bytes, bytes]]:
797794
return result
798795

799796

800-
class X509Extension:
801-
"""
802-
An X.509 v3 certificate extension.
803-
804-
.. deprecated:: 23.3.0
805-
Use cryptography's X509 APIs instead.
806-
"""
807-
808-
def __init__(
809-
self,
810-
type_name: bytes,
811-
critical: bool,
812-
value: bytes,
813-
subject: X509 | None = None,
814-
issuer: X509 | None = None,
815-
) -> None:
816-
"""
817-
Initializes an X509 extension.
818-
819-
:param type_name: The name of the type of extension_ to create.
820-
:type type_name: :py:data:`bytes`
821-
822-
:param bool critical: A flag indicating whether this is a critical
823-
extension.
824-
825-
:param value: The OpenSSL textual representation of the extension's
826-
value.
827-
:type value: :py:data:`bytes`
828-
829-
:param subject: Optional X509 certificate to use as subject.
830-
:type subject: :py:class:`X509`
831-
832-
:param issuer: Optional X509 certificate to use as issuer.
833-
:type issuer: :py:class:`X509`
834-
835-
.. _extension: https://www.openssl.org/docs/manmaster/man5/
836-
x509v3_config.html#STANDARD-EXTENSIONS
837-
"""
838-
ctx = _ffi.new("X509V3_CTX*")
839-
840-
# A context is necessary for any extension which uses the r2i
841-
# conversion method. That is, X509V3_EXT_nconf may segfault if passed
842-
# a NULL ctx. Start off by initializing most of the fields to NULL.
843-
_lib.X509V3_set_ctx(ctx, _ffi.NULL, _ffi.NULL, _ffi.NULL, _ffi.NULL, 0)
844-
845-
# We have no configuration database - but perhaps we should (some
846-
# extensions may require it).
847-
_lib.X509V3_set_ctx_nodb(ctx)
848-
849-
# Initialize the subject and issuer, if appropriate. ctx is a local,
850-
# and as far as I can tell none of the X509V3_* APIs invoked here steal
851-
# any references, so no need to mess with reference counts or
852-
# duplicates.
853-
if issuer is not None:
854-
if not isinstance(issuer, X509):
855-
raise TypeError("issuer must be an X509 instance")
856-
ctx.issuer_cert = issuer._x509
857-
if subject is not None:
858-
if not isinstance(subject, X509):
859-
raise TypeError("subject must be an X509 instance")
860-
ctx.subject_cert = subject._x509
861-
862-
if critical:
863-
# There are other OpenSSL APIs which would let us pass in critical
864-
# separately, but they're harder to use, and since value is already
865-
# a pile of crappy junk smuggling a ton of utterly important
866-
# structured data, what's the point of trying to avoid nasty stuff
867-
# with strings? (However, X509V3_EXT_i2d in particular seems like
868-
# it would be a better API to invoke. I do not know where to get
869-
# the ext_struc it desires for its last parameter, though.)
870-
value = b"critical," + value
871-
872-
extension = _lib.X509V3_EXT_nconf(_ffi.NULL, ctx, type_name, value)
873-
if extension == _ffi.NULL:
874-
_raise_current_error()
875-
self._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
876-
877-
@property
878-
def _nid(self) -> Any:
879-
return _lib.OBJ_obj2nid(
880-
_lib.X509_EXTENSION_get_object(self._extension)
881-
)
882-
883-
_prefixes: typing.ClassVar[dict[int, str]] = {
884-
_lib.GEN_EMAIL: "email",
885-
_lib.GEN_DNS: "DNS",
886-
_lib.GEN_URI: "URI",
887-
}
888-
889-
def _subjectAltNameString(self) -> str:
890-
names = _ffi.cast(
891-
"GENERAL_NAMES*", _lib.X509V3_EXT_d2i(self._extension)
892-
)
893-
894-
names = _ffi.gc(names, _lib.GENERAL_NAMES_free)
895-
parts = []
896-
for i in range(_lib.sk_GENERAL_NAME_num(names)):
897-
name = _lib.sk_GENERAL_NAME_value(names, i)
898-
try:
899-
label = self._prefixes[name.type]
900-
except KeyError:
901-
bio = _new_mem_buf()
902-
_lib.GENERAL_NAME_print(bio, name)
903-
parts.append(_bio_to_string(bio).decode("utf-8"))
904-
else:
905-
value = _ffi.buffer(name.d.ia5.data, name.d.ia5.length)[
906-
:
907-
].decode("utf-8")
908-
parts.append(label + ":" + value)
909-
return ", ".join(parts)
910-
911-
def __str__(self) -> str:
912-
"""
913-
:return: a nice text representation of the extension
914-
"""
915-
if _lib.NID_subject_alt_name == self._nid:
916-
return self._subjectAltNameString()
917-
918-
bio = _new_mem_buf()
919-
print_result = _lib.X509V3_EXT_print(bio, self._extension, 0, 0)
920-
_openssl_assert(print_result != 0)
921-
922-
return _bio_to_string(bio).decode("utf-8")
923-
924-
def get_critical(self) -> bool:
925-
"""
926-
Returns the critical field of this X.509 extension.
927-
928-
:return: The critical field.
929-
"""
930-
return _lib.X509_EXTENSION_get_critical(self._extension)
931-
932-
def get_short_name(self) -> bytes:
933-
"""
934-
Returns the short type name of this X.509 extension.
935-
936-
The result is a byte string such as :py:const:`b"basicConstraints"`.
937-
938-
:return: The short type name.
939-
:rtype: :py:data:`bytes`
940-
941-
.. versionadded:: 0.12
942-
"""
943-
obj = _lib.X509_EXTENSION_get_object(self._extension)
944-
nid = _lib.OBJ_obj2nid(obj)
945-
# OpenSSL 3.1.0 has a bug where nid2sn returns NULL for NIDs that
946-
# previously returned UNDEF. This is a workaround for that issue.
947-
# https://github.com/openssl/openssl/commit/908ba3ed9adbb3df90f76
948-
buf = _lib.OBJ_nid2sn(nid)
949-
if buf != _ffi.NULL:
950-
return _ffi.string(buf)
951-
else:
952-
return b"UNDEF"
953-
954-
def get_data(self) -> bytes:
955-
"""
956-
Returns the data of the X509 extension, encoded as ASN.1.
957-
958-
:return: The ASN.1 encoded data of this X509 extension.
959-
:rtype: :py:data:`bytes`
960-
961-
.. versionadded:: 0.12
962-
"""
963-
octet_result = _lib.X509_EXTENSION_get_data(self._extension)
964-
string_result = _ffi.cast("ASN1_STRING*", octet_result)
965-
char_result = _lib.ASN1_STRING_get0_data(string_result)
966-
result_length = _lib.ASN1_STRING_length(string_result)
967-
return _ffi.buffer(char_result, result_length)[:]
968-
969-
970-
_X509ExtensionInternal = X509Extension
971-
utils.deprecated(
972-
X509Extension,
973-
__name__,
974-
(
975-
"X509Extension support in pyOpenSSL is deprecated. You should use the "
976-
"APIs in cryptography."
977-
),
978-
DeprecationWarning,
979-
name="X509Extension",
980-
)
981-
982-
983797
class X509Req:
984798
"""
985799
An X.509 certificate signing requests.
@@ -1105,79 +919,6 @@ def get_subject(self) -> X509Name:
1105919

1106920
return name
1107921

1108-
def add_extensions(
1109-
self, extensions: Iterable[_X509ExtensionInternal]
1110-
) -> None:
1111-
"""
1112-
Add extensions to the certificate signing request.
1113-
1114-
:param extensions: The X.509 extensions to add.
1115-
:type extensions: iterable of :py:class:`X509Extension`
1116-
:return: ``None``
1117-
"""
1118-
warnings.warn(
1119-
(
1120-
"This API is deprecated and will be removed in a future "
1121-
"version of pyOpenSSL. You should use pyca/cryptography's "
1122-
"X.509 APIs instead."
1123-
),
1124-
DeprecationWarning,
1125-
stacklevel=2,
1126-
)
1127-
1128-
stack = _lib.sk_X509_EXTENSION_new_null()
1129-
_openssl_assert(stack != _ffi.NULL)
1130-
1131-
stack = _ffi.gc(stack, _lib.sk_X509_EXTENSION_free)
1132-
1133-
for ext in extensions:
1134-
if not isinstance(ext, _X509ExtensionInternal):
1135-
raise ValueError("One of the elements is not an X509Extension")
1136-
1137-
# TODO push can fail (here and elsewhere)
1138-
_lib.sk_X509_EXTENSION_push(stack, ext._extension)
1139-
1140-
add_result = _lib.X509_REQ_add_extensions(self._req, stack)
1141-
_openssl_assert(add_result == 1)
1142-
1143-
def get_extensions(self) -> list[_X509ExtensionInternal]:
1144-
"""
1145-
Get X.509 extensions in the certificate signing request.
1146-
1147-
:return: The X.509 extensions in this request.
1148-
:rtype: :py:class:`list` of :py:class:`X509Extension` objects.
1149-
1150-
.. versionadded:: 0.15
1151-
"""
1152-
warnings.warn(
1153-
(
1154-
"This API is deprecated and will be removed in a future "
1155-
"version of pyOpenSSL. You should use pyca/cryptography's "
1156-
"X.509 APIs instead."
1157-
),
1158-
DeprecationWarning,
1159-
stacklevel=2,
1160-
)
1161-
1162-
exts = []
1163-
native_exts_obj = _lib.X509_REQ_get_extensions(self._req)
1164-
native_exts_obj = _ffi.gc(
1165-
native_exts_obj,
1166-
lambda x: _lib.sk_X509_EXTENSION_pop_free(
1167-
x,
1168-
_ffi.addressof(_lib._original_lib, "X509_EXTENSION_free"),
1169-
),
1170-
)
1171-
1172-
for i in range(_lib.sk_X509_EXTENSION_num(native_exts_obj)):
1173-
ext = _X509ExtensionInternal.__new__(_X509ExtensionInternal)
1174-
extension = _lib.X509_EXTENSION_dup(
1175-
_lib.sk_X509_EXTENSION_value(native_exts_obj, i)
1176-
)
1177-
ext._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
1178-
exts.append(ext)
1179-
return exts
1180-
1181922
def sign(self, pkey: PKey, digest: str) -> None:
1182923
"""
1183924
Sign the certificate signing request with this key and digest type.
@@ -1669,66 +1410,6 @@ def get_extension_count(self) -> int:
16691410
"""
16701411
return _lib.X509_get_ext_count(self._x509)
16711412

1672-
def add_extensions(
1673-
self, extensions: Iterable[_X509ExtensionInternal]
1674-
) -> None:
1675-
"""
1676-
Add extensions to the certificate.
1677-
1678-
:param extensions: The extensions to add.
1679-
:type extensions: An iterable of :py:class:`X509Extension` objects.
1680-
:return: ``None``
1681-
"""
1682-
warnings.warn(
1683-
(
1684-
"This API is deprecated and will be removed in a future "
1685-
"version of pyOpenSSL. You should use pyca/cryptography's "
1686-
"X.509 APIs instead."
1687-
),
1688-
DeprecationWarning,
1689-
stacklevel=2,
1690-
)
1691-
1692-
for ext in extensions:
1693-
if not isinstance(ext, _X509ExtensionInternal):
1694-
raise ValueError("One of the elements is not an X509Extension")
1695-
1696-
add_result = _lib.X509_add_ext(self._x509, ext._extension, -1)
1697-
_openssl_assert(add_result == 1)
1698-
1699-
def get_extension(self, index: int) -> _X509ExtensionInternal:
1700-
"""
1701-
Get a specific extension of the certificate by index.
1702-
1703-
Extensions on a certificate are kept in order. The index
1704-
parameter selects which extension will be returned.
1705-
1706-
:param int index: The index of the extension to retrieve.
1707-
:return: The extension at the specified index.
1708-
:rtype: :py:class:`X509Extension`
1709-
:raises IndexError: If the extension index was out of bounds.
1710-
1711-
.. versionadded:: 0.12
1712-
"""
1713-
warnings.warn(
1714-
(
1715-
"This API is deprecated and will be removed in a future "
1716-
"version of pyOpenSSL. You should use pyca/cryptography's "
1717-
"X.509 APIs instead."
1718-
),
1719-
DeprecationWarning,
1720-
stacklevel=2,
1721-
)
1722-
1723-
ext = _X509ExtensionInternal.__new__(_X509ExtensionInternal)
1724-
ext._extension = _lib.X509_get_ext(self._x509, index)
1725-
if ext._extension == _ffi.NULL:
1726-
raise IndexError("extension index out of bounds")
1727-
1728-
extension = _lib.X509_EXTENSION_dup(ext._extension)
1729-
ext._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
1730-
return ext
1731-
17321413

17331414
class X509StoreFlags:
17341415
"""

0 commit comments

Comments
 (0)