1# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
2# For details: https://github.com/pylint-dev/astroid/blob/main/LICENSE
3# Copyright (c) https://github.com/pylint-dev/astroid/blob/main/CONTRIBUTORS.txt
4
5"""Astroid hooks for the ssl library."""
6
7from astroid import nodes
8from astroid.brain.helpers import register_module_extender
9from astroid.builder import parse
10from astroid.const import PY310_PLUS, PY312_PLUS
11from astroid.manager import AstroidManager
12
13
14def _verifyflags_enum() -> str:
15 enum = """
16 class VerifyFlags(_IntFlag):
17 VERIFY_DEFAULT = 0
18 VERIFY_CRL_CHECK_LEAF = 1
19 VERIFY_CRL_CHECK_CHAIN = 2
20 VERIFY_X509_STRICT = 3
21 VERIFY_X509_TRUSTED_FIRST = 4"""
22 if PY310_PLUS:
23 enum += """
24 VERIFY_ALLOW_PROXY_CERTS = 5
25 VERIFY_X509_PARTIAL_CHAIN = 6
26 """
27 return enum
28
29
30def _options_enum() -> str:
31 enum = """
32 class Options(_IntFlag):
33 OP_ALL = 1
34 OP_NO_SSLv2 = 2
35 OP_NO_SSLv3 = 3
36 OP_NO_TLSv1 = 4
37 OP_NO_TLSv1_1 = 5
38 OP_NO_TLSv1_2 = 6
39 OP_NO_TLSv1_3 = 7
40 OP_CIPHER_SERVER_PREFERENCE = 8
41 OP_SINGLE_DH_USE = 9
42 OP_SINGLE_ECDH_USE = 10
43 OP_NO_COMPRESSION = 11
44 OP_NO_TICKET = 12
45 OP_NO_RENEGOTIATION = 13
46 OP_ENABLE_MIDDLEBOX_COMPAT = 14
47 """
48 if PY312_PLUS:
49 enum += "OP_LEGACY_SERVER_CONNECT = 15"
50 return enum
51
52
53def ssl_transform() -> nodes.Module:
54 return parse(
55 f"""
56 # Import necessary for conversion of objects defined in C into enums
57 from enum import IntEnum as _IntEnum, IntFlag as _IntFlag
58
59 from _ssl import OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_INFO, OPENSSL_VERSION
60 from _ssl import _SSLContext, MemoryBIO
61 from _ssl import (
62 SSLError, SSLZeroReturnError, SSLWantReadError, SSLWantWriteError,
63 SSLSyscallError, SSLEOFError,
64 )
65 from _ssl import CERT_NONE, CERT_OPTIONAL, CERT_REQUIRED
66 from _ssl import txt2obj as _txt2obj, nid2obj as _nid2obj
67 from _ssl import RAND_status, RAND_add, RAND_bytes, RAND_pseudo_bytes
68 try:
69 from _ssl import RAND_egd
70 except ImportError:
71 # LibreSSL does not provide RAND_egd
72 pass
73 from _ssl import (OP_ALL, OP_CIPHER_SERVER_PREFERENCE,
74 OP_NO_COMPRESSION, OP_NO_SSLv2, OP_NO_SSLv3,
75 OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2,
76 OP_SINGLE_DH_USE, OP_SINGLE_ECDH_USE)
77
78 {"from _ssl import OP_LEGACY_SERVER_CONNECT" if PY312_PLUS else ""}
79
80 from _ssl import (ALERT_DESCRIPTION_ACCESS_DENIED, ALERT_DESCRIPTION_BAD_CERTIFICATE,
81 ALERT_DESCRIPTION_BAD_CERTIFICATE_HASH_VALUE,
82 ALERT_DESCRIPTION_BAD_CERTIFICATE_STATUS_RESPONSE,
83 ALERT_DESCRIPTION_BAD_RECORD_MAC,
84 ALERT_DESCRIPTION_CERTIFICATE_EXPIRED,
85 ALERT_DESCRIPTION_CERTIFICATE_REVOKED,
86 ALERT_DESCRIPTION_CERTIFICATE_UNKNOWN,
87 ALERT_DESCRIPTION_CERTIFICATE_UNOBTAINABLE,
88 ALERT_DESCRIPTION_CLOSE_NOTIFY, ALERT_DESCRIPTION_DECODE_ERROR,
89 ALERT_DESCRIPTION_DECOMPRESSION_FAILURE,
90 ALERT_DESCRIPTION_DECRYPT_ERROR,
91 ALERT_DESCRIPTION_HANDSHAKE_FAILURE,
92 ALERT_DESCRIPTION_ILLEGAL_PARAMETER,
93 ALERT_DESCRIPTION_INSUFFICIENT_SECURITY,
94 ALERT_DESCRIPTION_INTERNAL_ERROR,
95 ALERT_DESCRIPTION_NO_RENEGOTIATION,
96 ALERT_DESCRIPTION_PROTOCOL_VERSION,
97 ALERT_DESCRIPTION_RECORD_OVERFLOW,
98 ALERT_DESCRIPTION_UNEXPECTED_MESSAGE,
99 ALERT_DESCRIPTION_UNKNOWN_CA,
100 ALERT_DESCRIPTION_UNKNOWN_PSK_IDENTITY,
101 ALERT_DESCRIPTION_UNRECOGNIZED_NAME,
102 ALERT_DESCRIPTION_UNSUPPORTED_CERTIFICATE,
103 ALERT_DESCRIPTION_UNSUPPORTED_EXTENSION,
104 ALERT_DESCRIPTION_USER_CANCELLED)
105 from _ssl import (SSL_ERROR_EOF, SSL_ERROR_INVALID_ERROR_CODE, SSL_ERROR_SSL,
106 SSL_ERROR_SYSCALL, SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_READ,
107 SSL_ERROR_WANT_WRITE, SSL_ERROR_WANT_X509_LOOKUP, SSL_ERROR_ZERO_RETURN)
108 from _ssl import VERIFY_CRL_CHECK_CHAIN, VERIFY_CRL_CHECK_LEAF, VERIFY_DEFAULT, VERIFY_X509_STRICT
109 from _ssl import HAS_SNI, HAS_ECDH, HAS_NPN, HAS_ALPN
110 from _ssl import _OPENSSL_API_VERSION
111 from _ssl import PROTOCOL_SSLv23, PROTOCOL_TLSv1, PROTOCOL_TLSv1_1, PROTOCOL_TLSv1_2
112 from _ssl import PROTOCOL_TLS, PROTOCOL_TLS_CLIENT, PROTOCOL_TLS_SERVER
113
114 class AlertDescription(_IntEnum):
115 ALERT_DESCRIPTION_ACCESS_DENIED = 0
116 ALERT_DESCRIPTION_BAD_CERTIFICATE = 1
117 ALERT_DESCRIPTION_BAD_CERTIFICATE_HASH_VALUE = 2
118 ALERT_DESCRIPTION_BAD_CERTIFICATE_STATUS_RESPONSE = 3
119 ALERT_DESCRIPTION_BAD_RECORD_MAC = 4
120 ALERT_DESCRIPTION_CERTIFICATE_EXPIRED = 5
121 ALERT_DESCRIPTION_CERTIFICATE_REVOKED = 6
122 ALERT_DESCRIPTION_CERTIFICATE_UNKNOWN = 7
123 ALERT_DESCRIPTION_CERTIFICATE_UNOBTAINABLE = 8
124 ALERT_DESCRIPTION_CLOSE_NOTIFY = 9
125 ALERT_DESCRIPTION_DECODE_ERROR = 10
126 ALERT_DESCRIPTION_DECOMPRESSION_FAILURE = 11
127 ALERT_DESCRIPTION_DECRYPT_ERROR = 12
128 ALERT_DESCRIPTION_HANDSHAKE_FAILURE = 13
129 ALERT_DESCRIPTION_ILLEGAL_PARAMETER = 14
130 ALERT_DESCRIPTION_INSUFFICIENT_SECURITY = 15
131 ALERT_DESCRIPTION_INTERNAL_ERROR = 16
132 ALERT_DESCRIPTION_NO_RENEGOTIATION = 17
133 ALERT_DESCRIPTION_PROTOCOL_VERSION = 18
134 ALERT_DESCRIPTION_RECORD_OVERFLOW = 19
135 ALERT_DESCRIPTION_UNEXPECTED_MESSAGE = 20
136 ALERT_DESCRIPTION_UNKNOWN_CA = 21
137 ALERT_DESCRIPTION_UNKNOWN_PSK_IDENTITY = 22
138 ALERT_DESCRIPTION_UNRECOGNIZED_NAME = 23
139 ALERT_DESCRIPTION_UNSUPPORTED_CERTIFICATE = 24
140 ALERT_DESCRIPTION_UNSUPPORTED_EXTENSION = 25
141 ALERT_DESCRIPTION_USER_CANCELLED = 26
142
143 class SSLErrorNumber(_IntEnum):
144 SSL_ERROR_EOF = 0
145 SSL_ERROR_INVALID_ERROR_CODE = 1
146 SSL_ERROR_SSL = 2
147 SSL_ERROR_SYSCALL = 3
148 SSL_ERROR_WANT_CONNECT = 4
149 SSL_ERROR_WANT_READ = 5
150 SSL_ERROR_WANT_WRITE = 6
151 SSL_ERROR_WANT_X509_LOOKUP = 7
152 SSL_ERROR_ZERO_RETURN = 8
153
154 class VerifyMode(_IntEnum):
155 CERT_NONE = 0
156 CERT_OPTIONAL = 1
157 CERT_REQUIRED = 2
158 """
159 + _verifyflags_enum()
160 + _options_enum()
161 )
162
163
164def register(manager: AstroidManager) -> None:
165 register_module_extender(manager, "ssl", ssl_transform)