Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hhhrrrttt222111
GitHub Repository: hhhrrrttt222111/Dorkify
Path: blob/master/venv/Lib/site-packages/setuptools/ssl_support.py
811 views
1
import os
2
import socket
3
import atexit
4
import re
5
import functools
6
7
from setuptools.extern.six.moves import urllib, http_client, map, filter
8
9
from pkg_resources import ResolutionError, ExtractionError
10
11
try:
12
import ssl
13
except ImportError:
14
ssl = None
15
16
__all__ = [
17
'VerifyingHTTPSHandler', 'find_ca_bundle', 'is_available', 'cert_paths',
18
'opener_for'
19
]
20
21
cert_paths = """
22
/etc/pki/tls/certs/ca-bundle.crt
23
/etc/ssl/certs/ca-certificates.crt
24
/usr/share/ssl/certs/ca-bundle.crt
25
/usr/local/share/certs/ca-root.crt
26
/etc/ssl/cert.pem
27
/System/Library/OpenSSL/certs/cert.pem
28
/usr/local/share/certs/ca-root-nss.crt
29
/etc/ssl/ca-bundle.pem
30
""".strip().split()
31
32
try:
33
HTTPSHandler = urllib.request.HTTPSHandler
34
HTTPSConnection = http_client.HTTPSConnection
35
except AttributeError:
36
HTTPSHandler = HTTPSConnection = object
37
38
is_available = ssl is not None and object not in (
39
HTTPSHandler, HTTPSConnection)
40
41
42
try:
43
from ssl import CertificateError, match_hostname
44
except ImportError:
45
try:
46
from backports.ssl_match_hostname import CertificateError
47
from backports.ssl_match_hostname import match_hostname
48
except ImportError:
49
CertificateError = None
50
match_hostname = None
51
52
if not CertificateError:
53
54
class CertificateError(ValueError):
55
pass
56
57
58
if not match_hostname:
59
60
def _dnsname_match(dn, hostname, max_wildcards=1):
61
"""Matching according to RFC 6125, section 6.4.3
62
63
https://tools.ietf.org/html/rfc6125#section-6.4.3
64
"""
65
pats = []
66
if not dn:
67
return False
68
69
# Ported from python3-syntax:
70
# leftmost, *remainder = dn.split(r'.')
71
parts = dn.split(r'.')
72
leftmost = parts[0]
73
remainder = parts[1:]
74
75
wildcards = leftmost.count('*')
76
if wildcards > max_wildcards:
77
# Issue #17980: avoid denials of service by refusing more
78
# than one wildcard per fragment. A survey of established
79
# policy among SSL implementations showed it to be a
80
# reasonable choice.
81
raise CertificateError(
82
"too many wildcards in certificate DNS name: " + repr(dn))
83
84
# speed up common case w/o wildcards
85
if not wildcards:
86
return dn.lower() == hostname.lower()
87
88
# RFC 6125, section 6.4.3, subitem 1.
89
# The client SHOULD NOT attempt to match a
90
# presented identifier in which the wildcard
91
# character comprises a label other than the
92
# left-most label.
93
if leftmost == '*':
94
# When '*' is a fragment by itself, it matches a non-empty dotless
95
# fragment.
96
pats.append('[^.]+')
97
elif leftmost.startswith('xn--') or hostname.startswith('xn--'):
98
# RFC 6125, section 6.4.3, subitem 3.
99
# The client SHOULD NOT attempt to match a presented identifier
100
# where the wildcard character is embedded within an A-label or
101
# U-label of an internationalized domain name.
102
pats.append(re.escape(leftmost))
103
else:
104
# Otherwise, '*' matches any dotless string, e.g. www*
105
pats.append(re.escape(leftmost).replace(r'\*', '[^.]*'))
106
107
# add the remaining fragments, ignore any wildcards
108
for frag in remainder:
109
pats.append(re.escape(frag))
110
111
pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE)
112
return pat.match(hostname)
113
114
def match_hostname(cert, hostname):
115
"""Verify that *cert* (in decoded format as returned by
116
SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125
117
rules are followed, but IP addresses are not accepted for *hostname*.
118
119
CertificateError is raised on failure. On success, the function
120
returns nothing.
121
"""
122
if not cert:
123
raise ValueError("empty or no certificate")
124
dnsnames = []
125
san = cert.get('subjectAltName', ())
126
for key, value in san:
127
if key == 'DNS':
128
if _dnsname_match(value, hostname):
129
return
130
dnsnames.append(value)
131
if not dnsnames:
132
# The subject is only checked when there is no dNSName entry
133
# in subjectAltName
134
for sub in cert.get('subject', ()):
135
for key, value in sub:
136
# XXX according to RFC 2818, the most specific Common Name
137
# must be used.
138
if key == 'commonName':
139
if _dnsname_match(value, hostname):
140
return
141
dnsnames.append(value)
142
if len(dnsnames) > 1:
143
raise CertificateError(
144
"hostname %r doesn't match either of %s"
145
% (hostname, ', '.join(map(repr, dnsnames))))
146
elif len(dnsnames) == 1:
147
raise CertificateError(
148
"hostname %r doesn't match %r"
149
% (hostname, dnsnames[0]))
150
else:
151
raise CertificateError(
152
"no appropriate commonName or "
153
"subjectAltName fields were found")
154
155
156
class VerifyingHTTPSHandler(HTTPSHandler):
157
"""Simple verifying handler: no auth, subclasses, timeouts, etc."""
158
159
def __init__(self, ca_bundle):
160
self.ca_bundle = ca_bundle
161
HTTPSHandler.__init__(self)
162
163
def https_open(self, req):
164
return self.do_open(
165
lambda host, **kw: VerifyingHTTPSConn(host, self.ca_bundle, **kw),
166
req
167
)
168
169
170
class VerifyingHTTPSConn(HTTPSConnection):
171
"""Simple verifying connection: no auth, subclasses, timeouts, etc."""
172
173
def __init__(self, host, ca_bundle, **kw):
174
HTTPSConnection.__init__(self, host, **kw)
175
self.ca_bundle = ca_bundle
176
177
def connect(self):
178
sock = socket.create_connection(
179
(self.host, self.port), getattr(self, 'source_address', None)
180
)
181
182
# Handle the socket if a (proxy) tunnel is present
183
if hasattr(self, '_tunnel') and getattr(self, '_tunnel_host', None):
184
self.sock = sock
185
self._tunnel()
186
# http://bugs.python.org/issue7776: Python>=3.4.1 and >=2.7.7
187
# change self.host to mean the proxy server host when tunneling is
188
# being used. Adapt, since we are interested in the destination
189
# host for the match_hostname() comparison.
190
actual_host = self._tunnel_host
191
else:
192
actual_host = self.host
193
194
if hasattr(ssl, 'create_default_context'):
195
ctx = ssl.create_default_context(cafile=self.ca_bundle)
196
self.sock = ctx.wrap_socket(sock, server_hostname=actual_host)
197
else:
198
# This is for python < 2.7.9 and < 3.4?
199
self.sock = ssl.wrap_socket(
200
sock, cert_reqs=ssl.CERT_REQUIRED, ca_certs=self.ca_bundle
201
)
202
try:
203
match_hostname(self.sock.getpeercert(), actual_host)
204
except CertificateError:
205
self.sock.shutdown(socket.SHUT_RDWR)
206
self.sock.close()
207
raise
208
209
210
def opener_for(ca_bundle=None):
211
"""Get a urlopen() replacement that uses ca_bundle for verification"""
212
return urllib.request.build_opener(
213
VerifyingHTTPSHandler(ca_bundle or find_ca_bundle())
214
).open
215
216
217
# from jaraco.functools
218
def once(func):
219
@functools.wraps(func)
220
def wrapper(*args, **kwargs):
221
if not hasattr(func, 'always_returns'):
222
func.always_returns = func(*args, **kwargs)
223
return func.always_returns
224
return wrapper
225
226
227
@once
228
def get_win_certfile():
229
try:
230
import wincertstore
231
except ImportError:
232
return None
233
234
class CertFile(wincertstore.CertFile):
235
def __init__(self):
236
super(CertFile, self).__init__()
237
atexit.register(self.close)
238
239
def close(self):
240
try:
241
super(CertFile, self).close()
242
except OSError:
243
pass
244
245
_wincerts = CertFile()
246
_wincerts.addstore('CA')
247
_wincerts.addstore('ROOT')
248
return _wincerts.name
249
250
251
def find_ca_bundle():
252
"""Return an existing CA bundle path, or None"""
253
extant_cert_paths = filter(os.path.isfile, cert_paths)
254
return (
255
get_win_certfile()
256
or next(extant_cert_paths, None)
257
or _certifi_where()
258
)
259
260
261
def _certifi_where():
262
try:
263
return __import__('certifi').where()
264
except (ImportError, ResolutionError, ExtractionError):
265
pass
266
267