Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 1 | import httplib2 |
| 2 | import pytest |
| 3 | import tests |
| 4 | from six.moves import urllib |
| 5 | |
| 6 | |
| 7 | def test_credentials(): |
| 8 | c = httplib2.Credentials() |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 9 | c.add("joe", "password") |
| 10 | assert tuple(c.iter("bitworking.org"))[0] == ("joe", "password") |
| 11 | assert tuple(c.iter(""))[0] == ("joe", "password") |
| 12 | c.add("fred", "password2", "wellformedweb.org") |
| 13 | assert tuple(c.iter("bitworking.org"))[0] == ("joe", "password") |
| 14 | assert len(tuple(c.iter("bitworking.org"))) == 1 |
| 15 | assert len(tuple(c.iter("wellformedweb.org"))) == 2 |
| 16 | assert ("fred", "password2") in tuple(c.iter("wellformedweb.org")) |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 17 | c.clear() |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 18 | assert len(tuple(c.iter("bitworking.org"))) == 0 |
| 19 | c.add("fred", "password2", "wellformedweb.org") |
| 20 | assert ("fred", "password2") in tuple(c.iter("wellformedweb.org")) |
| 21 | assert len(tuple(c.iter("bitworking.org"))) == 0 |
| 22 | assert len(tuple(c.iter(""))) == 0 |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 23 | |
| 24 | |
| 25 | def test_basic(): |
| 26 | # Test Basic Authentication |
| 27 | http = httplib2.Http() |
| 28 | password = tests.gen_password() |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 29 | handler = tests.http_reflect_with_auth( |
| 30 | allow_scheme="basic", allow_credentials=(("joe", password),) |
| 31 | ) |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 32 | with tests.server_request(handler, request_count=3) as uri: |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 33 | response, content = http.request(uri, "GET") |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 34 | assert response.status == 401 |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 35 | http.add_credentials("joe", password) |
| 36 | response, content = http.request(uri, "GET") |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 37 | assert response.status == 200 |
| 38 | |
| 39 | |
| 40 | def test_basic_for_domain(): |
| 41 | # Test Basic Authentication |
| 42 | http = httplib2.Http() |
| 43 | password = tests.gen_password() |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 44 | handler = tests.http_reflect_with_auth( |
| 45 | allow_scheme="basic", allow_credentials=(("joe", password),) |
| 46 | ) |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 47 | with tests.server_request(handler, request_count=4) as uri: |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 48 | response, content = http.request(uri, "GET") |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 49 | assert response.status == 401 |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 50 | http.add_credentials("joe", password, "example.org") |
| 51 | response, content = http.request(uri, "GET") |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 52 | assert response.status == 401 |
| 53 | domain = urllib.parse.urlparse(uri)[1] |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 54 | http.add_credentials("joe", password, domain) |
| 55 | response, content = http.request(uri, "GET") |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 56 | assert response.status == 200 |
| 57 | |
| 58 | |
| 59 | def test_basic_two_credentials(): |
| 60 | # Test Basic Authentication with multiple sets of credentials |
| 61 | http = httplib2.Http() |
| 62 | password1 = tests.gen_password() |
| 63 | password2 = tests.gen_password() |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 64 | allowed = [("joe", password1)] # exploit shared mutable list |
| 65 | handler = tests.http_reflect_with_auth( |
| 66 | allow_scheme="basic", allow_credentials=allowed |
| 67 | ) |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 68 | with tests.server_request(handler, request_count=7) as uri: |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 69 | http.add_credentials("fred", password2) |
| 70 | response, content = http.request(uri, "GET") |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 71 | assert response.status == 401 |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 72 | http.add_credentials("joe", password1) |
| 73 | response, content = http.request(uri, "GET") |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 74 | assert response.status == 200 |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 75 | allowed[0] = ("fred", password2) |
| 76 | response, content = http.request(uri, "GET") |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 77 | assert response.status == 200 |
| 78 | |
| 79 | |
| 80 | def test_digest(): |
| 81 | # Test that we support Digest Authentication |
| 82 | http = httplib2.Http() |
| 83 | password = tests.gen_password() |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 84 | handler = tests.http_reflect_with_auth( |
| 85 | allow_scheme="digest", allow_credentials=(("joe", password),) |
| 86 | ) |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 87 | with tests.server_request(handler, request_count=3) as uri: |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 88 | response, content = http.request(uri, "GET") |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 89 | assert response.status == 401 |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 90 | http.add_credentials("joe", password) |
| 91 | response, content = http.request(uri, "GET") |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 92 | assert response.status == 200, content.decode() |
| 93 | |
| 94 | |
| 95 | def test_digest_next_nonce_nc(): |
| 96 | # Test that if the server sets nextnonce that we reset |
| 97 | # the nonce count back to 1 |
| 98 | http = httplib2.Http() |
| 99 | password = tests.gen_password() |
| 100 | grenew_nonce = [None] |
| 101 | handler = tests.http_reflect_with_auth( |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 102 | allow_scheme="digest", |
| 103 | allow_credentials=(("joe", password),), |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 104 | out_renew_nonce=grenew_nonce, |
| 105 | ) |
| 106 | with tests.server_request(handler, request_count=5) as uri: |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 107 | http.add_credentials("joe", password) |
| 108 | response1, _ = http.request(uri, "GET") |
| 109 | info = httplib2._parse_www_authenticate(response1, "authentication-info") |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 110 | assert response1.status == 200 |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 111 | assert info.get("digest", {}).get("nc") == "00000001", info |
| 112 | assert not info.get("digest", {}).get("nextnonce"), info |
| 113 | response2, _ = http.request(uri, "GET") |
| 114 | info2 = httplib2._parse_www_authenticate(response2, "authentication-info") |
| 115 | assert info2.get("digest", {}).get("nc") == "00000002", info2 |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 116 | grenew_nonce[0]() |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 117 | response3, content = http.request(uri, "GET") |
| 118 | info3 = httplib2._parse_www_authenticate(response3, "authentication-info") |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 119 | assert response3.status == 200 |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 120 | assert info3.get("digest", {}).get("nc") == "00000001", info3 |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 121 | |
| 122 | |
| 123 | def test_digest_auth_stale(): |
| 124 | # Test that we can handle a nonce becoming stale |
| 125 | http = httplib2.Http() |
| 126 | password = tests.gen_password() |
| 127 | grenew_nonce = [None] |
| 128 | requests = [] |
| 129 | handler = tests.http_reflect_with_auth( |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 130 | allow_scheme="digest", |
| 131 | allow_credentials=(("joe", password),), |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 132 | out_renew_nonce=grenew_nonce, |
| 133 | out_requests=requests, |
| 134 | ) |
| 135 | with tests.server_request(handler, request_count=4) as uri: |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 136 | http.add_credentials("joe", password) |
| 137 | response, _ = http.request(uri, "GET") |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 138 | assert response.status == 200 |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 139 | info = httplib2._parse_www_authenticate( |
| 140 | requests[0][1].headers, "www-authenticate" |
| 141 | ) |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 142 | grenew_nonce[0]() |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 143 | response, _ = http.request(uri, "GET") |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 144 | assert response.status == 200 |
| 145 | assert not response.fromcache |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 146 | assert getattr(response, "_stale_digest", False) |
| 147 | info2 = httplib2._parse_www_authenticate( |
| 148 | requests[2][1].headers, "www-authenticate" |
| 149 | ) |
| 150 | nonce1 = info.get("digest", {}).get("nonce", "") |
| 151 | nonce2 = info2.get("digest", {}).get("nonce", "") |
| 152 | assert nonce1 != "" |
| 153 | assert nonce2 != "" |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 154 | assert nonce1 != nonce2, (nonce1, nonce2) |
| 155 | |
| 156 | |
| 157 | @pytest.mark.parametrize( |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 158 | "data", |
| 159 | ( |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 160 | ({}, {}), |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 161 | ({"www-authenticate": ""}, {}), |
| 162 | ( |
| 163 | { |
| 164 | "www-authenticate": 'Test realm="test realm" , foo=foo ,bar="bar", baz=baz,qux=qux' |
| 165 | }, |
| 166 | { |
| 167 | "test": { |
| 168 | "realm": "test realm", |
| 169 | "foo": "foo", |
| 170 | "bar": "bar", |
| 171 | "baz": "baz", |
| 172 | "qux": "qux", |
| 173 | } |
| 174 | }, |
| 175 | ), |
| 176 | ( |
| 177 | {"www-authenticate": 'T*!%#st realm=to*!%#en, to*!%#en="quoted string"'}, |
| 178 | {"t*!%#st": {"realm": "to*!%#en", "to*!%#en": "quoted string"}}, |
| 179 | ), |
| 180 | ( |
| 181 | {"www-authenticate": 'Test realm="a \\"test\\" realm"'}, |
| 182 | {"test": {"realm": 'a "test" realm'}}, |
| 183 | ), |
| 184 | ({"www-authenticate": 'Basic realm="me"'}, {"basic": {"realm": "me"}}), |
| 185 | ( |
| 186 | {"www-authenticate": 'Basic realm="me", algorithm="MD5"'}, |
| 187 | {"basic": {"realm": "me", "algorithm": "MD5"}}, |
| 188 | ), |
| 189 | ( |
| 190 | {"www-authenticate": 'Basic realm="me", algorithm=MD5'}, |
| 191 | {"basic": {"realm": "me", "algorithm": "MD5"}}, |
| 192 | ), |
| 193 | ( |
| 194 | {"www-authenticate": 'Basic realm="me",other="fred" '}, |
| 195 | {"basic": {"realm": "me", "other": "fred"}}, |
| 196 | ), |
| 197 | ({"www-authenticate": 'Basic REAlm="me" '}, {"basic": {"realm": "me"}}), |
| 198 | ( |
| 199 | { |
| 200 | "www-authenticate": 'Digest realm="digest1", qop="auth,auth-int", nonce="7102dd2", opaque="e9517f"' |
| 201 | }, |
| 202 | { |
| 203 | "digest": { |
| 204 | "realm": "digest1", |
| 205 | "qop": "auth,auth-int", |
| 206 | "nonce": "7102dd2", |
| 207 | "opaque": "e9517f", |
| 208 | } |
| 209 | }, |
| 210 | ), |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 211 | # multiple schema choice |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 212 | ( |
| 213 | { |
| 214 | "www-authenticate": 'Digest realm="multi-d", nonce="8b11d0f6", opaque="cc069c" Basic realm="multi-b" ' |
| 215 | }, |
| 216 | { |
| 217 | "digest": {"realm": "multi-d", "nonce": "8b11d0f6", "opaque": "cc069c"}, |
| 218 | "basic": {"realm": "multi-b"}, |
| 219 | }, |
| 220 | ), |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 221 | # FIXME |
| 222 | # comma between schemas (glue for multiple headers with same name) |
| 223 | # ({'www-authenticate': 'Digest realm="2-comma-d", qop="auth-int", nonce="c0c8ff1", Basic realm="2-comma-b"'}, |
| 224 | # {'digest': {'realm': '2-comma-d', 'qop': 'auth-int', 'nonce': 'c0c8ff1'}, |
| 225 | # 'basic': {'realm': '2-comma-b'}}), |
| 226 | # FIXME |
| 227 | # comma between schemas + WSSE (glue for multiple headers with same name) |
| 228 | # ({'www-authenticate': 'Digest realm="com3d", Basic realm="com3b", WSSE realm="com3w", profile="token"'}, |
| 229 | # {'digest': {'realm': 'com3d'}, 'basic': {'realm': 'com3b'}, 'wsse': {'realm': 'com3w', profile': 'token'}}), |
| 230 | # FIXME |
| 231 | # multiple syntax figures |
| 232 | # ({'www-authenticate': |
| 233 | # 'Digest realm="brig", qop \t=\t"\tauth,auth-int", nonce="(*)&^&$%#",opaque="5ccc"' + |
| 234 | # ', Basic REAlm="zoo", WSSE realm="very", profile="UsernameToken"'}, |
| 235 | # {'digest': {'realm': 'brig', 'qop': 'auth,auth-int', 'nonce': '(*)&^&$%#', 'opaque': '5ccc'}, |
| 236 | # 'basic': {'realm': 'zoo'}, |
| 237 | # 'wsse': {'realm': 'very', 'profile': 'UsernameToken'}}), |
| 238 | # more quote combos |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 239 | ( |
| 240 | { |
| 241 | "www-authenticate": 'Digest realm="myrealm", nonce="KBAA=3", algorithm=MD5, qop="auth", stale=true' |
| 242 | }, |
| 243 | { |
| 244 | "digest": { |
| 245 | "realm": "myrealm", |
| 246 | "nonce": "KBAA=3", |
| 247 | "algorithm": "MD5", |
| 248 | "qop": "auth", |
| 249 | "stale": "true", |
| 250 | } |
| 251 | }, |
| 252 | ), |
| 253 | ), |
| 254 | ids=lambda data: str(data[0]), |
| 255 | ) |
| 256 | @pytest.mark.parametrize("strict", (True, False), ids=("strict", "relax")) |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 257 | def test_parse_www_authenticate_correct(data, strict): |
| 258 | headers, info = data |
| 259 | # FIXME: move strict to parse argument |
| 260 | httplib2.USE_WWW_AUTH_STRICT_PARSING = strict |
| 261 | try: |
| 262 | assert httplib2._parse_www_authenticate(headers) == info |
| 263 | finally: |
| 264 | httplib2.USE_WWW_AUTH_STRICT_PARSING = 0 |
| 265 | |
| 266 | |
| 267 | def test_parse_www_authenticate_malformed(): |
| 268 | # TODO: test (and fix) header value 'barbqwnbm-bb...:asd' leads to dead loop |
| 269 | with tests.assert_raises(httplib2.MalformedHeader): |
| 270 | httplib2._parse_www_authenticate( |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 271 | { |
| 272 | "www-authenticate": 'OAuth "Facebook Platform" "invalid_token" "Invalid OAuth access token."' |
| 273 | } |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 274 | ) |
| 275 | |
| 276 | |
| 277 | def test_digest_object(): |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 278 | credentials = ("joe", "password") |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 279 | host = None |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 280 | request_uri = "/test/digest/" |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 281 | headers = {} |
| 282 | response = { |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 283 | "www-authenticate": 'Digest realm="myrealm", nonce="KBAA=35", algorithm=MD5, qop="auth"' |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 284 | } |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 285 | content = b"" |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 286 | |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 287 | d = httplib2.DigestAuthentication( |
| 288 | credentials, host, request_uri, headers, response, content, None |
| 289 | ) |
| 290 | d.request("GET", request_uri, headers, content, cnonce="33033375ec278a46") |
| 291 | our_request = "authorization: " + headers["authorization"] |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 292 | working_request = ( |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 293 | 'authorization: Digest username="joe", realm="myrealm", ' |
| 294 | 'nonce="KBAA=35", uri="/test/digest/"' |
| 295 | + ', algorithm=MD5, response="de6d4a123b80801d0e94550411b6283f", ' |
| 296 | 'qop=auth, nc=00000001, cnonce="33033375ec278a46"' |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 297 | ) |
| 298 | assert our_request == working_request |
| 299 | |
| 300 | |
| 301 | def test_digest_object_with_opaque(): |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 302 | credentials = ("joe", "password") |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 303 | host = None |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 304 | request_uri = "/digest/opaque/" |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 305 | headers = {} |
| 306 | response = { |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 307 | "www-authenticate": 'Digest realm="myrealm", nonce="30352fd", algorithm=MD5, ' |
| 308 | 'qop="auth", opaque="atestopaque"' |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 309 | } |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 310 | content = "" |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 311 | |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 312 | d = httplib2.DigestAuthentication( |
| 313 | credentials, host, request_uri, headers, response, content, None |
| 314 | ) |
| 315 | d.request("GET", request_uri, headers, content, cnonce="5ec2") |
| 316 | our_request = "authorization: " + headers["authorization"] |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 317 | working_request = ( |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 318 | 'authorization: Digest username="joe", realm="myrealm", ' |
| 319 | 'nonce="30352fd", uri="/digest/opaque/", algorithm=MD5' |
| 320 | + ', response="a1fab43041f8f3789a447f48018bee48", qop=auth, nc=00000001, ' |
| 321 | 'cnonce="5ec2", opaque="atestopaque"' |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 322 | ) |
| 323 | assert our_request == working_request |
| 324 | |
| 325 | |
| 326 | def test_digest_object_stale(): |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 327 | credentials = ("joe", "password") |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 328 | host = None |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 329 | request_uri = "/digest/stale/" |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 330 | headers = {} |
| 331 | response = httplib2.Response({}) |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 332 | response["www-authenticate"] = ( |
| 333 | 'Digest realm="myrealm", nonce="bd669f", ' |
| 334 | 'algorithm=MD5, qop="auth", stale=true' |
| 335 | ) |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 336 | response.status = 401 |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 337 | content = b"" |
| 338 | d = httplib2.DigestAuthentication( |
| 339 | credentials, host, request_uri, headers, response, content, None |
| 340 | ) |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 341 | # Returns true to force a retry |
| 342 | assert d.response(response, content) |
| 343 | |
| 344 | |
| 345 | def test_digest_object_auth_info(): |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 346 | credentials = ("joe", "password") |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 347 | host = None |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 348 | request_uri = "/digest/nextnonce/" |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 349 | headers = {} |
| 350 | response = httplib2.Response({}) |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 351 | response["www-authenticate"] = ( |
| 352 | 'Digest realm="myrealm", nonce="barney", ' |
| 353 | 'algorithm=MD5, qop="auth", stale=true' |
| 354 | ) |
| 355 | response["authentication-info"] = 'nextnonce="fred"' |
| 356 | content = b"" |
| 357 | d = httplib2.DigestAuthentication( |
| 358 | credentials, host, request_uri, headers, response, content, None |
| 359 | ) |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 360 | # Returns true to force a retry |
| 361 | assert not d.response(response, content) |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 362 | assert d.challenge["nonce"] == "fred" |
| 363 | assert d.challenge["nc"] == 1 |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 364 | |
| 365 | |
| 366 | def test_wsse_algorithm(): |
Alex Yu | aa1b95b | 2018-07-26 23:23:35 -0400 | [diff] [blame^] | 367 | digest = httplib2._wsse_username_token( |
| 368 | "d36e316282959a9ed4c89851497a717f", "2003-12-15T14:43:07Z", "taadtaadpstcsm" |
| 369 | ) |
| 370 | expected = b"quR/EWLAV4xLf9Zqyw4pDmfV9OY=" |
Sergey Shepelev | 0112eff | 2017-05-05 06:46:43 +0300 | [diff] [blame] | 371 | assert expected == digest |