Changeset d510103 in trunk
- Timestamp:
- 2023-05-23T18:53:22Z (2 years ago)
- Branches:
- master
- Children:
- 839140c, 96670de, f4a099c
- Parents:
- 41131ca (diff), b03db14 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent. - git-author:
- Itamar Turner-Trauring <itamar@…> (2023-05-23 18:53:22)
- git-committer:
- GitHub <noreply@…> (2023-05-23 18:53:22)
- Files:
-
- 1 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified src/allmydata/storage/http_server.py ¶
r41131ca rd510103 5 5 from __future__ import annotations 6 6 7 from typing import Any, Callable, Union, cast 7 from typing import Any, Callable, Union, cast, Optional 8 8 from functools import wraps 9 9 from base64 import b64decode … … 76 76 77 77 If too few secrets were given, or too many, a ``ClientSecretsException`` is 78 raised .78 raised; its text is sent in the HTTP response. 79 79 """ 80 80 string_key_to_enum = {e.value: e for e in Secrets} … … 85 85 key = string_key_to_enum[string_key] 86 86 value = b64decode(string_value) 87 if value == b"": 88 raise ClientSecretsException( 89 "Failed to decode secret {}".format(string_key) 90 ) 87 91 if key in (Secrets.LEASE_CANCEL, Secrets.LEASE_RENEW) and len(value) != 32: 88 92 raise ClientSecretsException("Lease secrets must be 32 bytes long") … … 92 96 if result.keys() != required_secrets: 93 97 raise ClientSecretsException( 94 "Expected {} secrets, got {}".format(required_secrets, result.keys()) 98 "Expected {} in X-Tahoe-Authorization headers, got {}".format( 99 [r.value for r in required_secrets], list(result.keys()) 100 ) 95 101 ) 96 102 return result … … 117 123 try: 118 124 # Check Authorization header: 125 try: 126 auth_header = request.requestHeaders.getRawHeaders( 127 "Authorization", [""] 128 )[0].encode("utf-8") 129 except UnicodeError: 130 raise _HTTPError(http.BAD_REQUEST, "Bad Authorization header") 119 131 if not timing_safe_compare( 120 request.requestHeaders.getRawHeaders("Authorization", [""])[ 121 0 122 ].encode("utf-8"), 132 auth_header, 123 133 swissnum_auth_header(self._swissnum), 124 134 ): 125 raise _HTTPError(http.UNAUTHORIZED) 135 raise _HTTPError( 136 http.UNAUTHORIZED, "Wrong Authorization header" 137 ) 126 138 127 139 # Check secrets: … … 131 143 try: 132 144 secrets = _extract_secrets(authorization, required_secrets) 133 except ClientSecretsException :134 raise _HTTPError(http.BAD_REQUEST )145 except ClientSecretsException as e: 146 raise _HTTPError(http.BAD_REQUEST, str(e)) 135 147 136 148 # Run the business logic: … … 273 285 """ 274 286 275 def __init__(self, code: int): 287 def __init__(self, code: int, body: Optional[str] = None): 288 Exception.__init__(self, (code, body)) 276 289 self.code = code 290 self.body = body 277 291 278 292 … … 500 514 """Handle ``_HTTPError`` exceptions.""" 501 515 request.setResponseCode(failure.value.code) 502 return b"" 516 if failure.value.body is not None: 517 return failure.value.body 518 else: 519 return b"" 503 520 504 521 @app.handle_errors(CDDLValidationError) -
TabularUnified src/allmydata/test/test_storage_http.py ¶
r41131ca rd510103 258 258 _swissnum = SWISSNUM_FOR_TEST # Match what the test client is using 259 259 260 @_authorized_route(_app, {}, "/noop", methods=["GET"]) 261 def noop(self, request, authorization): 262 return "noop" 263 260 264 @_authorized_route(_app, {Secrets.UPLOAD}, "/upload_secret", methods=["GET"]) 261 265 def validate_upload_secret(self, request, authorization): … … 341 345 self._http_server.clock = self.client._clock 342 346 347 def test_bad_swissnum_from_client(self) -> None: 348 """ 349 If the swissnum is invalid, a BAD REQUEST response code is returned. 350 """ 351 headers = Headers() 352 # The value is not UTF-8. 353 headers.addRawHeader("Authorization", b"\x00\xFF\x00\xFF") 354 response = result_of( 355 self.client._treq.request( 356 "GET", 357 DecodedURL.from_text("http://127.0.0.1/noop"), 358 headers=headers, 359 ) 360 ) 361 self.assertEqual(response.code, 400) 362 363 def test_bad_secret(self) -> None: 364 """ 365 If the secret is invalid (not base64), a BAD REQUEST 366 response code is returned. 367 """ 368 bad_secret = b"upload-secret []<>" 369 headers = Headers() 370 headers.addRawHeader( 371 "X-Tahoe-Authorization", 372 bad_secret, 373 ) 374 response = result_of( 375 self.client.request( 376 "GET", 377 DecodedURL.from_text("http://127.0.0.1/upload_secret"), 378 headers=headers, 379 ) 380 ) 381 self.assertEqual(response.code, 400) 382 343 383 def test_authorization_enforcement(self): 344 384 """ 345 385 The requirement for secrets is enforced by the ``_authorized_route`` 346 386 decorator; if they are not given, a 400 response code is returned. 387 388 Note that this refers to ``X-Tahoe-Authorization``, not the 389 ``Authorization`` header used for the swissnum. 347 390 """ 348 391 # Without secret, get a 400 error.
Note: See TracChangeset
for help on using the changeset viewer.