Files
palemoon27/python/requests/requests/auth.py
T
roytam1 a25085b248 import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1195173 - Test asyncopen2 security checks for stylesheets (r=bz,ehsan) (358ae850a4)
- Bug 1223644 - Clean up the nsSVGClipPathFrame reference loop detection code. r=longsonr (65042c3148)
- Bug 1157064 - font-display descriptor parsing. r=dbaron (18f63d9244)
- Bug 1242523 - Guard against GetWidget getting called with a null shell. r=snorp (55de891c6c)
- Bug 1247679, part 3 - Replace NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK with JS_MEMBER. r=smaug (09435e582c)
- Bug 1247515 - Check nsScriptErrorWithStack's mStack member for null before tracing; r=mccr8 (0cb1e09aa9)
- Bug 1178803. Fix the handling of the 'length' key in IDB keypaths when operating on a string. r=bent (69f15272a8)
- Bug 1240660 - Remove "+" prefixes in jar manifests. r=gps (27de5a6a87)
- Bug 1240660 - Remove support for the "+" prefix in jar manifests. r=gps (2bdf115c40)
- 1240660 fallout fix (3b1c1e2d8b)
- Back out the videocontrols piece of bug 1231828 due to b2g breakage and add to the ignore list. r=backout (bffe92e32c)
- Bug 1201037 - coalesce network-events on Windows, r=mcmanus (5f48aab5c3)
- Bug 1131626, fix autoscroll tests to work in e10s, r=felipe (c47adbaa10)
- Bug 1231529 - Increase the timeout of browser_bug295977_autoscroll_overflow.js (691d27224d)
- Bug 416611 - Changed BookmarkHTMLUtils.jsm to import bookmark tags from HTML document. r=mak (49a0accc13)
- Bug 1130858 - Recipient autocomplete suggestion overrides ANY manual address input if quickly entered/pasted and confirmed with Enter/Tab before autocomplete suggestions disappear. r=mak (308196e116)
- Bug 1197361. Optimize page thumbnails based on screen size. r=ttaubert (29dca20366)
- Bug 555087 - Add check for exception when passing undefined parameter. r=adw (3588477c56)
- Bug 750544 - Remove the scope bar from the Library window. r=mano. (e1544ca40a)
- Bug 1175678 - Update icons for different Mixed Content Blocking states in the URL bar r=MattN (79a8c1d70a)
- remove parent folder (95af2afea6)
- Bug 1145063 - Remove the keywords column from the Library r=mak (600f18004a)
- Bug 1203803: Force cleanup for specific states only; r=khuey a=CLOSED TREE (2f9f78ad72)
- Bug 1203803 - Remove forced cleanup from FactoryOp::ActorDestroy() since it cause more harm than good; r=khuey (76a00e58cb)
- Bug 1195149 - Upgrade the  check to a MOZ_RELEASE_ASSERT. r=janv (071d1fc267)
- Bug 1185223 - crash at [@ mozilla::dom::quota::QuotaObject::Release() ]; r=khuey (d460972a45)
- Bug 1229376 - Downgrade lastVacuumSize > 0 assertion to an NS_ASSERTION so we don't have to star it all over the place, rs=khuey (81d715ab71)
- Bug 1239666 - part 1, get rid of the default parameter. r=waldo (639fb79ec3)
- Bug 1239666 - part 2, dom/indexedDB change. r=khuey (6faaf25df4)
- Bug 1239666 - part 3, devtools test case changes. r=sphink (c010d06a77)
- Bug 1248309 - Fix caret size not updated when only zoom level is changed. r=roc (91cc5b35df)
- bits of Bug 983623 - Implement cmd_un/redo for the new async TM (7fd41a9c37)
- Bug 1245649: Turn on no-trailing-spaces. r=Gijs (7f87c967af)
- Bug 1245649: Enable no-negated-in-lhs, no-native-reassign, no-func-assign and no-labels. r=MattN (5f801e4a4c)
- Bug 1177639 - ensure copy is made visible again, r=mak (a0a3238cc1)
- Bug 993274 - Remove cmd_new:livemark. r=mak (2a29f447d5)
- more openparent removal (e8f0c74bbd)
- minor fixes (b80d0307e9)
- hide pocket, we don't support it anyway (8a802e9e5b)
- Bug 1197966 - Fix typo when releasing content-side probes in PerformanceStats-content.js. r=felipe (9241324efd)
- Bug 1219144 - Performance alerts are now labelled with isJankVisible; r=avih,froydnj (c1549a24f5)
- Bug 1219144 - Using the nsRefreshDriver's jank indication for performance monitoring;f?froydnj r=froydnj (735c6fba9c)
- Bug 1211783 - Add KeyframeEffect interface to dom/webidl/KeyframeEffect.webidl. r=smaug,birtles (fca332fea0)
- Fix up missing dependency in bug 1247162. r=me (897f1ebd9b)
- Bug 795681 - Print out failures in mozunit runner. r=gps (ce418e5ea8)
- Bug 801679 - Handle expected failures and skipped tests in mozunit runner. r=gps (396ca02893)
- Bug 1247833 - Display the class name in mozunit output. r=gps (0b5724f41c)
- Bug 1245022 - Kill stlport's Makefile.in. r=mshal (225f662efc)
- Bug 1194603 - Remove INTERNAL_TOOLS; r=mshal (e8e90ec1c3)
- Bug 1247994 - Upgrade vendored requests package to 2.9.1; r=mshal (591a9e849a)
- Bug 1234612: Print path when failing to create virtualenv r=gps (ae69d82c1f)
- Bug 1235109 - Remove support for -I in preprocessor and jar maker. r=gps (a6c60bb407)
- Bug 1248027 - '#define FOO' should use an empty value, not '1'; r=glandium (8a3a33bad9)
- Bug 1239872 - Prevent jar maker from installing the same file twice. r=gps (4c3e496212)
- Bug 1224450 - Skip difficult directories in the CompileDB. r=gps (4fe09cff61)
- Bug 1245015 - Properly handle ObjC sources in the CompileDB backend. r=mshal (9d2f312c01)
- Bug 1224450 - Ignore host compilations in the CompileDB backend. r=gps (c0e6d114b5)
- Bug 1224450 - Make the CompileDB derive its commands from the moz.build data. r=gps (abee41178f)
- Bug 1247743 - Expose non-pinning JS_Atomize[UC]String JSAPI functions; r=terrence (66aa23066d)
- Bug 1230071 - Enable warnings-as-errors in js/src. r=Waldo (a0c8acf6ad)
- Bug 1007136 - Ensure malloc/free always match when using JSAutoByteString; r=bz (81dfcf036a)
- Bug 1246850 - check the NotifyIpInterfaceChange() return code, r=mcmanus (bc224f287c)
- Bug 739029 - null check a thread allocation in notifyaddrlistener r=bagder (ce0ddfc44c)
2023-11-16 17:42:59 +08:00

224 lines
7.4 KiB
Python

# -*- coding: utf-8 -*-
"""
requests.auth
~~~~~~~~~~~~~
This module contains the authentication handlers for Requests.
"""
import os
import re
import time
import hashlib
import threading
from base64 import b64encode
from .compat import urlparse, str
from .cookies import extract_cookies_to_jar
from .utils import parse_dict_header, to_native_string
from .status_codes import codes
CONTENT_TYPE_FORM_URLENCODED = 'application/x-www-form-urlencoded'
CONTENT_TYPE_MULTI_PART = 'multipart/form-data'
def _basic_auth_str(username, password):
"""Returns a Basic Auth string."""
authstr = 'Basic ' + to_native_string(
b64encode(('%s:%s' % (username, password)).encode('latin1')).strip()
)
return authstr
class AuthBase(object):
"""Base class that all auth implementations derive from"""
def __call__(self, r):
raise NotImplementedError('Auth hooks must be callable.')
class HTTPBasicAuth(AuthBase):
"""Attaches HTTP Basic Authentication to the given Request object."""
def __init__(self, username, password):
self.username = username
self.password = password
def __call__(self, r):
r.headers['Authorization'] = _basic_auth_str(self.username, self.password)
return r
class HTTPProxyAuth(HTTPBasicAuth):
"""Attaches HTTP Proxy Authentication to a given Request object."""
def __call__(self, r):
r.headers['Proxy-Authorization'] = _basic_auth_str(self.username, self.password)
return r
class HTTPDigestAuth(AuthBase):
"""Attaches HTTP Digest Authentication to the given Request object."""
def __init__(self, username, password):
self.username = username
self.password = password
# Keep state in per-thread local storage
self._thread_local = threading.local()
def init_per_thread_state(self):
# Ensure state is initialized just once per-thread
if not hasattr(self._thread_local, 'init'):
self._thread_local.init = True
self._thread_local.last_nonce = ''
self._thread_local.nonce_count = 0
self._thread_local.chal = {}
self._thread_local.pos = None
self._thread_local.num_401_calls = None
def build_digest_header(self, method, url):
realm = self._thread_local.chal['realm']
nonce = self._thread_local.chal['nonce']
qop = self._thread_local.chal.get('qop')
algorithm = self._thread_local.chal.get('algorithm')
opaque = self._thread_local.chal.get('opaque')
if algorithm is None:
_algorithm = 'MD5'
else:
_algorithm = algorithm.upper()
# lambdas assume digest modules are imported at the top level
if _algorithm == 'MD5' or _algorithm == 'MD5-SESS':
def md5_utf8(x):
if isinstance(x, str):
x = x.encode('utf-8')
return hashlib.md5(x).hexdigest()
hash_utf8 = md5_utf8
elif _algorithm == 'SHA':
def sha_utf8(x):
if isinstance(x, str):
x = x.encode('utf-8')
return hashlib.sha1(x).hexdigest()
hash_utf8 = sha_utf8
KD = lambda s, d: hash_utf8("%s:%s" % (s, d))
if hash_utf8 is None:
return None
# XXX not implemented yet
entdig = None
p_parsed = urlparse(url)
#: path is request-uri defined in RFC 2616 which should not be empty
path = p_parsed.path or "/"
if p_parsed.query:
path += '?' + p_parsed.query
A1 = '%s:%s:%s' % (self.username, realm, self.password)
A2 = '%s:%s' % (method, path)
HA1 = hash_utf8(A1)
HA2 = hash_utf8(A2)
if nonce == self._thread_local.last_nonce:
self._thread_local.nonce_count += 1
else:
self._thread_local.nonce_count = 1
ncvalue = '%08x' % self._thread_local.nonce_count
s = str(self._thread_local.nonce_count).encode('utf-8')
s += nonce.encode('utf-8')
s += time.ctime().encode('utf-8')
s += os.urandom(8)
cnonce = (hashlib.sha1(s).hexdigest()[:16])
if _algorithm == 'MD5-SESS':
HA1 = hash_utf8('%s:%s:%s' % (HA1, nonce, cnonce))
if not qop:
respdig = KD(HA1, "%s:%s" % (nonce, HA2))
elif qop == 'auth' or 'auth' in qop.split(','):
noncebit = "%s:%s:%s:%s:%s" % (
nonce, ncvalue, cnonce, 'auth', HA2
)
respdig = KD(HA1, noncebit)
else:
# XXX handle auth-int.
return None
self._thread_local.last_nonce = nonce
# XXX should the partial digests be encoded too?
base = 'username="%s", realm="%s", nonce="%s", uri="%s", ' \
'response="%s"' % (self.username, realm, nonce, path, respdig)
if opaque:
base += ', opaque="%s"' % opaque
if algorithm:
base += ', algorithm="%s"' % algorithm
if entdig:
base += ', digest="%s"' % entdig
if qop:
base += ', qop="auth", nc=%s, cnonce="%s"' % (ncvalue, cnonce)
return 'Digest %s' % (base)
def handle_redirect(self, r, **kwargs):
"""Reset num_401_calls counter on redirects."""
if r.is_redirect:
self._thread_local.num_401_calls = 1
def handle_401(self, r, **kwargs):
"""Takes the given response and tries digest-auth, if needed."""
if self._thread_local.pos is not None:
# Rewind the file position indicator of the body to where
# it was to resend the request.
r.request.body.seek(self._thread_local.pos)
s_auth = r.headers.get('www-authenticate', '')
if 'digest' in s_auth.lower() and self._thread_local.num_401_calls < 2:
self._thread_local.num_401_calls += 1
pat = re.compile(r'digest ', flags=re.IGNORECASE)
self._thread_local.chal = parse_dict_header(pat.sub('', s_auth, count=1))
# Consume content and release the original connection
# to allow our new request to reuse the same one.
r.content
r.close()
prep = r.request.copy()
extract_cookies_to_jar(prep._cookies, r.request, r.raw)
prep.prepare_cookies(prep._cookies)
prep.headers['Authorization'] = self.build_digest_header(
prep.method, prep.url)
_r = r.connection.send(prep, **kwargs)
_r.history.append(r)
_r.request = prep
return _r
self._thread_local.num_401_calls = 1
return r
def __call__(self, r):
# Initialize per-thread state, if needed
self.init_per_thread_state()
# If we have a saved nonce, skip the 401
if self._thread_local.last_nonce:
r.headers['Authorization'] = self.build_digest_header(r.method, r.url)
try:
self._thread_local.pos = r.body.tell()
except AttributeError:
# In the case of HTTPDigestAuth being reused and the body of
# the previous request was a file-like object, pos has the
# file position of the previous body. Ensure it's set to
# None.
self._thread_local.pos = None
r.register_hook('response', self.handle_401)
r.register_hook('response', self.handle_redirect)
self._thread_local.num_401_calls = 1
return r