Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(68)

Side by Side Diff: swarm_client/third_party/requests/auth.py

Issue 69143004: Delete swarm_client. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « swarm_client/third_party/requests/api.py ('k') | swarm_client/third_party/requests/cacert.pem » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 # -*- coding: utf-8 -*-
2
3 """
4 requests.auth
5 ~~~~~~~~~~~~~
6
7 This module contains the authentication handlers for Requests.
8 """
9
10 import os
11 import re
12 import time
13 import hashlib
14 import logging
15
16 from base64 import b64encode
17
18 from .compat import urlparse, str
19 from .utils import parse_dict_header
20
21 log = logging.getLogger(__name__)
22
23 CONTENT_TYPE_FORM_URLENCODED = 'application/x-www-form-urlencoded'
24 CONTENT_TYPE_MULTI_PART = 'multipart/form-data'
25
26
27 def _basic_auth_str(username, password):
28 """Returns a Basic Auth string."""
29
30 return 'Basic ' + b64encode(('%s:%s' % (username, password)).encode('latin1' )).strip().decode('latin1')
31
32
33 class AuthBase(object):
34 """Base class that all auth implementations derive from"""
35
36 def __call__(self, r):
37 raise NotImplementedError('Auth hooks must be callable.')
38
39
40 class HTTPBasicAuth(AuthBase):
41 """Attaches HTTP Basic Authentication to the given Request object."""
42 def __init__(self, username, password):
43 self.username = username
44 self.password = password
45
46 def __call__(self, r):
47 r.headers['Authorization'] = _basic_auth_str(self.username, self.passwor d)
48 return r
49
50
51 class HTTPProxyAuth(HTTPBasicAuth):
52 """Attaches HTTP Proxy Authentication to a given Request object."""
53 def __call__(self, r):
54 r.headers['Proxy-Authorization'] = _basic_auth_str(self.username, self.p assword)
55 return r
56
57
58 class HTTPDigestAuth(AuthBase):
59 """Attaches HTTP Digest Authentication to the given Request object."""
60 def __init__(self, username, password):
61 self.username = username
62 self.password = password
63 self.last_nonce = ''
64 self.nonce_count = 0
65 self.chal = {}
66
67 def build_digest_header(self, method, url):
68
69 realm = self.chal['realm']
70 nonce = self.chal['nonce']
71 qop = self.chal.get('qop')
72 algorithm = self.chal.get('algorithm')
73 opaque = self.chal.get('opaque')
74
75 if algorithm is None:
76 _algorithm = 'MD5'
77 else:
78 _algorithm = algorithm.upper()
79 # lambdas assume digest modules are imported at the top level
80 if _algorithm == 'MD5':
81 def md5_utf8(x):
82 if isinstance(x, str):
83 x = x.encode('utf-8')
84 return hashlib.md5(x).hexdigest()
85 hash_utf8 = md5_utf8
86 elif _algorithm == 'SHA':
87 def sha_utf8(x):
88 if isinstance(x, str):
89 x = x.encode('utf-8')
90 return hashlib.sha1(x).hexdigest()
91 hash_utf8 = sha_utf8
92 # XXX MD5-sess
93 KD = lambda s, d: hash_utf8("%s:%s" % (s, d))
94
95 if hash_utf8 is None:
96 return None
97
98 # XXX not implemented yet
99 entdig = None
100 p_parsed = urlparse(url)
101 path = p_parsed.path
102 if p_parsed.query:
103 path += '?' + p_parsed.query
104
105 A1 = '%s:%s:%s' % (self.username, realm, self.password)
106 A2 = '%s:%s' % (method, path)
107
108 if qop is None:
109 respdig = KD(hash_utf8(A1), "%s:%s" % (nonce, hash_utf8(A2)))
110 elif qop == 'auth' or 'auth' in qop.split(','):
111 if nonce == self.last_nonce:
112 self.nonce_count += 1
113 else:
114 self.nonce_count = 1
115
116 ncvalue = '%08x' % self.nonce_count
117 s = str(self.nonce_count).encode('utf-8')
118 s += nonce.encode('utf-8')
119 s += time.ctime().encode('utf-8')
120 s += os.urandom(8)
121
122 cnonce = (hashlib.sha1(s).hexdigest()[:16])
123 noncebit = "%s:%s:%s:%s:%s" % (nonce, ncvalue, cnonce, qop, hash_utf 8(A2))
124 respdig = KD(hash_utf8(A1), noncebit)
125 else:
126 # XXX handle auth-int.
127 return None
128
129 self.last_nonce = nonce
130
131 # XXX should the partial digests be encoded too?
132 base = 'username="%s", realm="%s", nonce="%s", uri="%s", ' \
133 'response="%s"' % (self.username, realm, nonce, path, respdig)
134 if opaque:
135 base += ', opaque="%s"' % opaque
136 if algorithm:
137 base += ', algorithm="%s"' % algorithm
138 if entdig:
139 base += ', digest="%s"' % entdig
140 if qop:
141 base += ', qop=auth, nc=%s, cnonce="%s"' % (ncvalue, cnonce)
142
143 return 'Digest %s' % (base)
144
145 def handle_401(self, r, **kwargs):
146 """Takes the given response and tries digest-auth, if needed."""
147
148 num_401_calls = getattr(self, 'num_401_calls', 1)
149 s_auth = r.headers.get('www-authenticate', '')
150
151 if 'digest' in s_auth.lower() and num_401_calls < 2:
152
153 setattr(self, 'num_401_calls', num_401_calls + 1)
154 pat = re.compile(r'digest ', flags=re.IGNORECASE)
155 self.chal = parse_dict_header(pat.sub('', s_auth, count=1))
156
157 # Consume content and release the original connection
158 # to allow our new request to reuse the same one.
159 r.content
160 r.raw.release_conn()
161 prep = r.request.copy()
162 prep.prepare_cookies(r.cookies)
163
164 prep.headers['Authorization'] = self.build_digest_header(
165 prep.method, prep.url)
166 _r = r.connection.send(prep, **kwargs)
167 _r.history.append(r)
168 _r.request = prep
169
170 return _r
171
172 setattr(self, 'num_401_calls', 1)
173 return r
174
175 def __call__(self, r):
176 # If we have a saved nonce, skip the 401
177 if self.last_nonce:
178 r.headers['Authorization'] = self.build_digest_header(r.method, r.ur l)
179 r.register_hook('response', self.handle_401)
180 return r
OLDNEW
« no previous file with comments | « swarm_client/third_party/requests/api.py ('k') | swarm_client/third_party/requests/cacert.pem » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698