A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://github.com/python/cpython/commit/aef1283ba428e33397d87cee3c54a5110861552d below:

Simplify and improve ssl.match_hostname (#5620) · python/cpython@aef1283 · GitHub

90 90

ALERT_DESCRIPTION_UNKNOWN_PSK_IDENTITY

91 91

"""

92 92 93 -

import ipaddress

94 -

import re

95 93

import sys

96 94

import os

97 95

from collections import namedtuple

160 158 161 159

from socket import socket, AF_INET, SOCK_STREAM, create_connection

162 160

from socket import SOL_SOCKET, SO_TYPE

161 +

import socket as _socket

163 162

import base64 # for DER-to-PEM translation

164 163

import errno

165 164

import warnings

183 182

def _dnsname_match(dn, hostname):

184 183

"""Matching according to RFC 6125, section 6.4.3

185 184 186 -

http://tools.ietf.org/html/rfc6125#section-6.4.3

185 +

- Hostnames are compared lower case.

186 +

- For IDNA, both dn and hostname must be encoded as IDN A-label (ACE).

187 +

- Partial wildcards like 'www*.example.org', multiple wildcards, sole

188 +

wildcard or wildcards in labels other then the left-most label are not

189 +

supported and a CertificateError is raised.

190 +

- A wildcard must match at least one character.

187 191

"""

188 -

pats = []

189 192

if not dn:

190 193

return False

191 194 192 -

leftmost, *remainder = dn.split(r'.')

195 +

wildcards = dn.count('*')

196 +

# speed up common case w/o wildcards

197 +

if not wildcards:

198 +

return dn.lower() == hostname.lower()

199 + 200 +

if wildcards > 1:

201 +

raise CertificateError(

202 +

"too many wildcards in certificate DNS name: {!r}.".format(dn))

193 203 194 -

wildcards = leftmost.count('*')

195 -

if wildcards == 1 and len(leftmost) > 1:

204 +

dn_leftmost, sep, dn_remainder = dn.partition('.')

205 + 206 +

if '*' in dn_remainder:

196 207

# Only match wildcard in leftmost segment.

197 208

raise CertificateError(

198 -

"wildcard can only be present in the leftmost segment: " + repr(dn))

209 +

"wildcard can only be present in the leftmost label: "

210 +

"{!r}.".format(dn))

199 211 200 -

if wildcards > 1:

201 -

# Issue #17980: avoid denials of service by refusing more

202 -

# than one wildcard per fragment. A survey of established

203 -

# policy among SSL implementations showed it to be a

204 -

# reasonable choice.

212 +

if not sep:

213 +

# no right side

205 214

raise CertificateError(

206 -

"too many wildcards in certificate DNS name: " + repr(dn))

215 +

"sole wildcard without additional labels are not support: "

216 +

"{!r}.".format(dn))

207 217 208 -

# speed up common case w/o wildcards

209 -

if not wildcards:

210 -

return dn.lower() == hostname.lower()

218 +

if dn_leftmost != '*':

219 +

# no partial wildcard matching

220 +

raise CertificateError(

221 +

"partial wildcards in leftmost label are not supported: "

222 +

"{!r}.".format(dn))

211 223 212 -

# RFC 6125, section 6.4.3, subitem 1.

213 -

# The client SHOULD NOT attempt to match a presented identifier in which

214 -

# the wildcard character comprises a label other than the left-most label.

215 -

if leftmost == '*':

216 -

# When '*' is a fragment by itself, it matches a non-empty dotless

217 -

# fragment.

218 -

pats.append('[^.]+')

219 -

elif leftmost.startswith('xn--') or hostname.startswith('xn--'):

220 -

# RFC 6125, section 6.4.3, subitem 3.

221 -

# The client SHOULD NOT attempt to match a presented identifier

222 -

# where the wildcard character is embedded within an A-label or

223 -

# U-label of an internationalized domain name.

224 -

pats.append(re.escape(leftmost))

225 -

else:

226 -

# Otherwise, '*' matches any dotless string, e.g. www*

227 -

pats.append(re.escape(leftmost).replace(r'\*', '[^.]*'))

224 +

hostname_leftmost, sep, hostname_remainder = hostname.partition('.')

225 +

if not hostname_leftmost or not sep:

226 +

# wildcard must match at least one char

227 +

return False

228 +

return dn_remainder.lower() == hostname_remainder.lower()

228 229 229 -

# add the remaining fragments, ignore any wildcards

230 -

for frag in remainder:

231 -

pats.append(re.escape(frag))

232 230 233 -

pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE)

234 -

return pat.match(hostname)

231 +

def _inet_paton(ipname):

232 +

"""Try to convert an IP address to packed binary form

233 + 234 +

Supports IPv4 addresses on all platforms and IPv6 on platforms with IPv6

235 +

support.

236 +

"""

237 +

# inet_aton() also accepts strings like '1'

238 +

if ipname.count('.') == 3:

239 +

try:

240 +

return _socket.inet_aton(ipname)

241 +

except OSError:

242 +

pass

243 + 244 +

try:

245 +

return _socket.inet_pton(_socket.AF_INET6, ipname)

246 +

except OSError:

247 +

raise ValueError("{!r} is neither an IPv4 nor an IP6 "

248 +

"address.".format(ipname))

249 +

except AttributeError:

250 +

# AF_INET6 not available

251 +

pass

252 + 253 +

raise ValueError("{!r} is not an IPv4 address.".format(ipname))

235 254 236 255 237 256

def _ipaddress_match(ipname, host_ip):

@@ -241,14 +260,19 @@ def _ipaddress_match(ipname, host_ip):

241 260

(section 1.7.2 - "Out of Scope").

242 261

"""

243 262

# OpenSSL may add a trailing newline to a subjectAltName's IP address

244 -

ip = ipaddress.ip_address(ipname.rstrip())

263 +

ip = _inet_paton(ipname.rstrip())

245 264

return ip == host_ip

246 265 247 266 248 267

def match_hostname(cert, hostname):

249 268

"""Verify that *cert* (in decoded format as returned by

250 269

SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125

251 -

rules are followed, but IP addresses are not accepted for *hostname*.

270 +

rules are followed.

271 + 272 +

The function matches IP addresses rather than dNSNames if hostname is a

273 +

valid ipaddress string. IPv4 addresses are supported on all platforms.

274 +

IPv6 addresses are supported on platforms with IPv6 support (AF_INET6

275 +

and inet_pton).

252 276 253 277

CertificateError is raised on failure. On success, the function

254 278

returns nothing.

@@ -258,7 +282,7 @@ def match_hostname(cert, hostname):

258 282

"SSL socket or SSL context with either "

259 283

"CERT_OPTIONAL or CERT_REQUIRED")

260 284

try:

261 -

host_ip = ipaddress.ip_address(hostname)

285 +

host_ip = _inet_paton(hostname)

262 286

except ValueError:

263 287

# Not an IP address (common case)

264 288

host_ip = None


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4