diff options
author | Miguel Jacq <mig@mig5.net> | 2021-08-27 15:52:29 +1000 |
---|---|---|
committer | Miguel Jacq <mig@mig5.net> | 2021-08-27 15:52:29 +1000 |
commit | 0bf8f53d30ded17dde0b3ebf66d98ea7d8e5313d (patch) | |
tree | f90e773c3951188248ac3085de31db71f29451cf /cli | |
parent | f63e0c37d10dda759554321e7bf36a64477daaaa (diff) | |
download | onionshare-0bf8f53d30ded17dde0b3ebf66d98ea7d8e5313d.tar.gz onionshare-0bf8f53d30ded17dde0b3ebf66d98ea7d8e5313d.zip |
ClientAuthV3 fixes
* Remove Client Auth as an explicit option (it's on by default).
* Update wording about Public mode
* Fix tuple error when raising TorTooOldStealth exception in CLI
* Move Private Key button next to URL button in GUI
* Replace visual references of ClientAuth to Private Key
* Remove HTTPAuth Flask dependency and remove a lot of code to do with password generation,
401 auth triggers/invalid password rate limit detection etc
* Test updates
* Remove obsolete locale keys
Diffstat (limited to 'cli')
-rw-r--r-- | cli/onionshare_cli/__init__.py | 64 | ||||
-rw-r--r-- | cli/onionshare_cli/mode_settings.py | 3 | ||||
-rw-r--r-- | cli/onionshare_cli/onion.py | 10 | ||||
-rw-r--r-- | cli/onionshare_cli/onionshare.py | 4 | ||||
-rw-r--r-- | cli/onionshare_cli/resources/templates/401.html | 21 | ||||
-rw-r--r-- | cli/onionshare_cli/web/web.py | 88 | ||||
-rw-r--r-- | cli/poetry.lock | 18 | ||||
-rw-r--r-- | cli/pyproject.toml | 3 | ||||
-rw-r--r-- | cli/tests/test_cli_web.py | 90 |
9 files changed, 43 insertions, 258 deletions
diff --git a/cli/onionshare_cli/__init__.py b/cli/onionshare_cli/__init__.py index b5595367..a359f770 100644 --- a/cli/onionshare_cli/__init__.py +++ b/cli/onionshare_cli/__init__.py @@ -38,14 +38,6 @@ from .onionshare import OnionShare from .mode_settings import ModeSettings -def build_url(mode_settings, app, web): - # Build the URL - if mode_settings.get("general", "public"): - return f"http://{app.onion_host}" - else: - return f"http://onionshare:{web.password}@{app.onion_host}" - - def main(cwd=None): """ The main() function implements all of the logic that the command-line version of @@ -113,7 +105,7 @@ def main(cwd=None): action="store_true", dest="public", default=False, - help="Don't use a password", + help="Don't use a private key", ) parser.add_argument( "--auto-start-timer", @@ -129,13 +121,6 @@ def main(cwd=None): default=0, help="Stop onion service at schedule time (N seconds from now)", ) - parser.add_argument( - "--client-auth", - action="store_true", - dest="client_auth", - default=False, - help="Use client authorization", - ) # Share args parser.add_argument( "--no-autostop-sharing", @@ -208,7 +193,6 @@ def main(cwd=None): public = bool(args.public) autostart_timer = int(args.autostart_timer) autostop_timer = int(args.autostop_timer) - client_auth = bool(args.client_auth) autostop_sharing = not bool(args.no_autostop_sharing) data_dir = args.data_dir webhook_url = args.webhook_url @@ -249,7 +233,6 @@ def main(cwd=None): mode_settings.set("general", "public", public) mode_settings.set("general", "autostart_timer", autostart_timer) mode_settings.set("general", "autostop_timer", autostop_timer) - mode_settings.set("general", "client_auth", client_auth) if mode == "share": mode_settings.set("share", "autostop_sharing", autostop_sharing) if mode == "receive": @@ -336,11 +319,6 @@ def main(cwd=None): try: common.settings.load() - if mode_settings.get("general", "public"): - web.password = None - else: - web.generate_password(mode_settings.get("onion", "password")) - # Receive mode needs to know the tor proxy details for webhooks if mode == "receive": if local_only: @@ -365,7 +343,7 @@ def main(cwd=None): sys.exit() app.start_onion_service(mode, mode_settings, False) - url = build_url(mode_settings, app, web) + url = f"http://{app.onion_host}" schedule = datetime.now() + timedelta(seconds=autostart_timer) if mode == "receive": print( @@ -378,21 +356,21 @@ def main(cwd=None): "what you are doing." ) print("") - if mode_settings.get("general", "client_auth"): + if not mode_settings.get("general", "public"): print( - f"Give this address and ClientAuth line to your sender, and tell them it won't be accessible until: {schedule.strftime('%I:%M:%S%p, %b %d, %y')}" + f"Give this address and private key to your sender, and tell them it won't be accessible until: {schedule.strftime('%I:%M:%S%p, %b %d, %y')}" ) - print(f"ClientAuth: {app.auth_string}") + print(f"Private key: {app.auth_string}") else: print( f"Give this address to your sender, and tell them it won't be accessible until: {schedule.strftime('%I:%M:%S%p, %b %d, %y')}" ) else: - if mode_settings.get("general", "client_auth"): + if not mode_settings.get("general", "public"): print( - f"Give this address and ClientAuth line to your recipient, and tell them it won't be accessible until: {schedule.strftime('%I:%M:%S%p, %b %d, %y')}" + f"Give this address and private key to your recipient, and tell them it won't be accessible until: {schedule.strftime('%I:%M:%S%p, %b %d, %y')}" ) - print(f"ClientAuth: {app.auth_string}") + print(f"Private key: {app.auth_string}") else: print( f"Give this address to your recipient, and tell them it won't be accessible until: {schedule.strftime('%I:%M:%S%p, %b %d, %y')}" @@ -410,7 +388,6 @@ def main(cwd=None): sys.exit() except (TorTooOldEphemeral, TorTooOldStealth, TorErrorProtocolError) as e: print("") - print(e.args[0]) sys.exit() if mode == "website": @@ -442,21 +419,14 @@ def main(cwd=None): t.start() try: # Trap Ctrl-C - # Wait for web.generate_password() to finish running time.sleep(0.2) # start auto-stop timer thread if app.autostop_timer > 0: app.autostop_timer_thread.start() - # Save the web password if we are using a persistent private key - if mode_settings.get("persistent", "enabled"): - if not mode_settings.get("onion", "password"): - mode_settings.set("onion", "password", web.password) - # mode_settings.save() - # Build the URL - url = build_url(mode_settings, app, web) + url = f"http://{app.onion_host}" print("") if autostart_timer > 0: @@ -474,21 +444,21 @@ def main(cwd=None): ) print("") - if mode_settings.get("general", "client_auth"): - print("Give this address and ClientAuth to the sender:") + if mode_settings.get("general", "public"): + print("Give this address to the sender:") print(url) - print(f"ClientAuth: {app.auth_string}") else: - print("Give this address to the sender:") + print("Give this address and private key to the sender:") print(url) + print(f"Private key: {app.auth_string}") else: - if mode_settings.get("general", "client_auth"): - print("Give this address and ClientAuth line to the recipient:") + if mode_settings.get("general", "public"): + print("Give this address to the recipient:") print(url) - print(f"ClientAuth: {app.auth_string}") else: - print("Give this address to the recipient:") + print("Give this address and private key to the recipient:") print(url) + print(f"Private key: {app.auth_string}") print("") print("Press Ctrl+C to stop the server") diff --git a/cli/onionshare_cli/mode_settings.py b/cli/onionshare_cli/mode_settings.py index 89ca00ea..47ff1c63 100644 --- a/cli/onionshare_cli/mode_settings.py +++ b/cli/onionshare_cli/mode_settings.py @@ -37,8 +37,6 @@ class ModeSettings: self.default_settings = { "onion": { "private_key": None, - "hidservauth_string": None, - "password": None, "client_auth_priv_key": None, "client_auth_pub_key": None, }, @@ -48,7 +46,6 @@ class ModeSettings: "public": False, "autostart_timer": False, "autostop_timer": False, - "client_auth": False, "service_id": None, }, "share": {"autostop_sharing": True, "filenames": []}, diff --git a/cli/onionshare_cli/onion.py b/cli/onionshare_cli/onion.py index 198f05c3..7f6faa17 100644 --- a/cli/onionshare_cli/onion.py +++ b/cli/onionshare_cli/onion.py @@ -640,7 +640,10 @@ class Onion(object): debug_message += f", key_content={key_content}" self.common.log("Onion", "start_onion_service", debug_message) - if mode_settings.get("general", "client_auth"): + if mode_settings.get("general", "public"): + client_auth_priv_key = None + client_auth_pub_key = None + else: if not self.supports_stealth: print( "Your version of Tor is too old, stealth onion services are not supported" @@ -657,9 +660,6 @@ class Onion(object): # These should have been saved in settings from the previous run of a persistent onion client_auth_priv_key = mode_settings.get("onion", "client_auth_priv_key") client_auth_pub_key = mode_settings.get("onion", "client_auth_pub_key") - else: - client_auth_priv_key = None - client_auth_pub_key = None try: if not self.supports_stealth: @@ -701,7 +701,7 @@ class Onion(object): # because we need to send the public key to ADD_ONION (if we restart this # same share at a later date), and the private key to the other user for # their Tor Browser. - if mode_settings.get("general", "client_auth"): + if not mode_settings.get("general", "public"): mode_settings.set("onion", "client_auth_priv_key", client_auth_priv_key) mode_settings.set("onion", "client_auth_pub_key", client_auth_pub_key) # If we were pasting the client auth directly into the filesystem behind a Tor client, diff --git a/cli/onionshare_cli/onionshare.py b/cli/onionshare_cli/onionshare.py index d055b639..c2711b89 100644 --- a/cli/onionshare_cli/onionshare.py +++ b/cli/onionshare_cli/onionshare.py @@ -74,7 +74,7 @@ class OnionShare(object): if self.local_only: self.onion_host = f"127.0.0.1:{self.port}" - if mode_settings.get("general", "client_auth"): + if not mode_settings.get("general", "public"): self.auth_string = "E2GOT5LTUTP3OAMRCRXO4GSH6VKJEUOXZQUC336SRKAHTTT5OVSA" return @@ -82,7 +82,7 @@ class OnionShare(object): mode, mode_settings, self.port, await_publication ) - if mode_settings.get("general", "client_auth"): + if not mode_settings.get("general", "public"): self.auth_string = self.onion.auth_string def stop_onion_service(self, mode_settings): diff --git a/cli/onionshare_cli/resources/templates/401.html b/cli/onionshare_cli/resources/templates/401.html deleted file mode 100644 index 5e43ca01..00000000 --- a/cli/onionshare_cli/resources/templates/401.html +++ /dev/null @@ -1,21 +0,0 @@ -<!DOCTYPE html> -<html> - -<head> - <title>OnionShare: 401 Unauthorized Access</title> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <link href="{{ static_url_path }}/img/favicon.ico" rel="icon" type="image/x-icon" /> - <link rel="stylesheet" rel="subresource" type="text/css" href="{{ static_url_path }}/css/style.css" media="all"> -</head> - -<body> - <div class="info-wrapper"> - <div class="info"> - <p><img class="logo" src="{{ static_url_path }}/img/logo_large.png" title="OnionShare"></p> - <p class="info-header">401 Unauthorized Access</p> - </div> - </div> -</body> - -</html> diff --git a/cli/onionshare_cli/web/web.py b/cli/onionshare_cli/web/web.py index 04919185..b33e0ee1 100644 --- a/cli/onionshare_cli/web/web.py +++ b/cli/onionshare_cli/web/web.py @@ -34,7 +34,6 @@ from flask import ( send_file, __version__ as flask_version, ) -from flask_httpauth import HTTPBasicAuth from flask_socketio import SocketIO from .share_mode import ShareModeWeb @@ -75,7 +74,6 @@ class Web: REQUEST_INDIVIDUAL_FILE_CANCELED = 12 REQUEST_ERROR_DATA_DIR_CANNOT_CREATE = 13 REQUEST_OTHER = 14 - REQUEST_INVALID_PASSWORD = 15 def __init__(self, common, is_gui, mode_settings, mode="share"): self.common = common @@ -92,8 +90,6 @@ class Web: ) self.app.secret_key = self.common.random_string(8) self.generate_static_url_path() - self.auth = HTTPBasicAuth() - self.auth.error_handler(self.error401) # Verbose mode? if self.common.verbose: @@ -132,9 +128,6 @@ class Web: ] self.q = queue.Queue() - self.password = None - - self.reset_invalid_passwords() self.done = False @@ -199,28 +192,6 @@ class Web: Common web app routes between all modes. """ - @self.auth.get_password - def get_pw(username): - if username == "onionshare": - return self.password - else: - return None - - @self.app.before_request - def conditional_auth_check(): - # Allow static files without basic authentication - if request.path.startswith(self.static_url_path + "/"): - return None - - # If public mode is disabled, require authentication - if not self.settings.get("general", "public"): - - @self.auth.login_required - def _check_login(): - return None - - return _check_login() - @self.app.errorhandler(404) def not_found(e): mode = self.get_mode() @@ -260,31 +231,6 @@ class Web: f"{self.common.get_resource_path('static')}/img/favicon.ico" ) - def error401(self): - auth = request.authorization - if auth: - if ( - auth["username"] == "onionshare" - and auth["password"] not in self.invalid_passwords - ): - print(f"Invalid password guess: {auth['password']}") - self.add_request(Web.REQUEST_INVALID_PASSWORD, data=auth["password"]) - - self.invalid_passwords.append(auth["password"]) - self.invalid_passwords_count += 1 - - if self.invalid_passwords_count == 20: - self.add_request(Web.REQUEST_RATE_LIMIT) - self.force_shutdown() - print( - "Someone has made too many wrong attempts to guess your password, so OnionShare has stopped the server. Start sharing again and send the recipient a new address to share." - ) - - r = make_response( - render_template("401.html", static_url_path=self.static_url_path), 401 - ) - return self.add_security_headers(r) - def error403(self): self.add_request(Web.REQUEST_OTHER, request.path) r = make_response( @@ -362,21 +308,6 @@ class Web: """ self.q.put({"type": request_type, "path": path, "data": data}) - def generate_password(self, saved_password=None): - self.common.log("Web", "generate_password", f"saved_password={saved_password}") - if saved_password is not None and saved_password != "": - self.password = saved_password - self.common.log( - "Web", - "generate_password", - f'saved_password sent, so password is: "{self.password}"', - ) - else: - self.password = self.common.build_password() - self.common.log( - "Web", "generate_password", f'built random password: "{self.password}"' - ) - def verbose_mode(self): """ Turn on verbose mode, which will log flask errors to a file. @@ -386,10 +317,6 @@ class Web: log_handler.setLevel(logging.WARNING) self.app.logger.addHandler(log_handler) - def reset_invalid_passwords(self): - self.invalid_passwords_count = 0 - self.invalid_passwords = [] - def force_shutdown(self): """ Stop the flask web server, from the context of the flask app. @@ -446,18 +373,9 @@ class Web: # To stop flask, load http://shutdown:[shutdown_password]@127.0.0.1/[shutdown_password]/shutdown # (We're putting the shutdown_password in the path as well to make routing simpler) if self.running: - if self.password: - requests.get( - f"http://127.0.0.1:{port}/{self.shutdown_password}/shutdown", - auth=requests.auth.HTTPBasicAuth("onionshare", self.password), - ) - else: - requests.get( - f"http://127.0.0.1:{port}/{self.shutdown_password}/shutdown" - ) - - # Reset any password that was in use - self.password = None + requests.get( + f"http://127.0.0.1:{port}/{self.shutdown_password}/shutdown" + ) def cleanup(self): """ diff --git a/cli/poetry.lock b/cli/poetry.lock index 56280b59..c51e1d62 100644 --- a/cli/poetry.lock +++ b/cli/poetry.lock @@ -125,17 +125,6 @@ dotenv = ["python-dotenv"] [[package]] category = "main" -description = "Basic and Digest HTTP authentication for Flask routes" -name = "flask-httpauth" -optional = false -python-versions = "*" -version = "4.4.0" - -[package.dependencies] -Flask = "*" - -[[package]] -category = "main" description = "Socket.IO integration for Flask applications" name = "flask-socketio" optional = false @@ -404,6 +393,7 @@ version = "1.8.1" reference = "de3d03a03c7ee57c74c80e9c63cb88072d833717" type = "git" url = "https://github.com/onionshare/stem.git" + [[package]] category = "dev" description = "Python Library for Tom's Obvious, Minimal Language" @@ -468,7 +458,7 @@ docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] testing = ["pytest (>=4.6)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "pytest-enabler", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"] [metadata] -content-hash = "ff0a546f5801be6b68336dfe7ade607ec2dd8c456fe17938be964f36bbe7d193" +content-hash = "181891640e59dac730905019444d42ef8e99da0c34c96fb8a616781661bae537" python-versions = "^3.6" [metadata.files] @@ -559,10 +549,6 @@ flask = [ {file = "Flask-1.1.4-py2.py3-none-any.whl", hash = "sha256:c34f04500f2cbbea882b1acb02002ad6fe6b7ffa64a6164577995657f50aed22"}, {file = "Flask-1.1.4.tar.gz", hash = "sha256:0fbeb6180d383a9186d0d6ed954e0042ad9f18e0e8de088b2b419d526927d196"}, ] -flask-httpauth = [ - {file = "Flask-HTTPAuth-4.4.0.tar.gz", hash = "sha256:bcaaa7a35a3cba0b2eafd4f113b3016bf70eb78087456d96484c3c18928b813a"}, - {file = "Flask_HTTPAuth-4.4.0-py2.py3-none-any.whl", hash = "sha256:d9131122cdc5709dda63790f6e9b3142d8101447d424b0b95ffd4ee279f49539"}, -] flask-socketio = [ {file = "Flask-SocketIO-5.0.1.tar.gz", hash = "sha256:5c4319f5214ada20807857dc8fdf3dc7d2afe8d6dd38f5c516c72e2be47d2227"}, {file = "Flask_SocketIO-5.0.1-py2.py3-none-any.whl", hash = "sha256:5d9a4438bafd806c5a3b832e74b69758781a8ee26fb6c9b1dbdda9b4fced432e"}, diff --git a/cli/pyproject.toml b/cli/pyproject.toml index a60428e0..e0c0f55f 100644 --- a/cli/pyproject.toml +++ b/cli/pyproject.toml @@ -19,7 +19,6 @@ classifiers = [ python = "^3.6" click = "*" flask = "1.1.4" -flask-httpauth = "*" flask-socketio = "5.0.1" psutil = "*" pysocks = "*" @@ -30,7 +29,7 @@ eventlet = "*" setuptools = "*" pynacl = "^1.4.0" colorama = "*" -stem = {git = "https://github.com/onionshare/stem.git", rev = "maint"} +stem = {git = "https://github.com/onionshare/stem.git", rev = "1.8.1"} [tool.poetry.dev-dependencies] pytest = "*" diff --git a/cli/tests/test_cli_web.py b/cli/tests/test_cli_web.py index f8c96f9c..f2b1af62 100644 --- a/cli/tests/test_cli_web.py +++ b/cli/tests/test_cli_web.py @@ -48,7 +48,6 @@ def web_obj(temp_dir, common_obj, mode, num_files=0): common_obj.settings = Settings(common_obj) mode_settings = ModeSettings(common_obj) web = Web(common_obj, False, mode_settings, mode) - web.generate_password() web.running = True web.cleanup_filenames == [] @@ -75,23 +74,13 @@ class TestWeb: web = web_obj(temp_dir, common_obj, "share", 3) assert web.mode == "share" with web.app.test_client() as c: - # Load / without auth + # Load / res = c.get("/") res.get_data() - assert res.status_code == 401 - - # Load / with invalid auth - res = c.get("/", headers=self._make_auth_headers("invalid")) - res.get_data() - assert res.status_code == 401 - - # Load / with valid auth - res = c.get("/", headers=self._make_auth_headers(web.password)) - res.get_data() assert res.status_code == 200 # Download - res = c.get("/download", headers=self._make_auth_headers(web.password)) + res = c.get("/download") res.get_data() assert res.status_code == 200 assert ( @@ -107,7 +96,7 @@ class TestWeb: with web.app.test_client() as c: # Download the first time - res = c.get("/download", headers=self._make_auth_headers(web.password)) + res = c.get("/download") res.get_data() assert res.status_code == 200 assert ( @@ -127,7 +116,7 @@ class TestWeb: with web.app.test_client() as c: # Download the first time - res = c.get("/download", headers=self._make_auth_headers(web.password)) + res = c.get("/download") res.get_data() assert res.status_code == 200 assert ( @@ -141,18 +130,8 @@ class TestWeb: assert web.mode == "receive" with web.app.test_client() as c: - # Load / without auth - res = c.get("/") - res.get_data() - assert res.status_code == 401 - - # Load / with invalid auth - res = c.get("/", headers=self._make_auth_headers("invalid")) - res.get_data() - assert res.status_code == 401 - # Load / with valid auth - res = c.get("/", headers=self._make_auth_headers(web.password)) + res = c.get("/",) res.get_data() assert res.status_code == 200 @@ -171,7 +150,7 @@ class TestWeb: ) with web.app.test_client() as c: - res = c.get("/", headers=self._make_auth_headers(web.password)) + res = c.get("/") res.get_data() assert res.status_code == 200 @@ -180,7 +159,6 @@ class TestWeb: buffered=True, content_type="multipart/form-data", data={"file[]": (BytesIO(b"THIS IS A TEST FILE"), "new_york.jpg")}, - headers=self._make_auth_headers(web.password), ) res.get_data() assert res.status_code == 200 @@ -202,7 +180,6 @@ class TestWeb: buffered=True, content_type="multipart/form-data", data={"text": "you know just sending an anonymous message"}, - headers=self._make_auth_headers(web.password), ) content = res.get_data() assert res.status_code == 200 @@ -237,7 +214,6 @@ class TestWeb: "file[]": (BytesIO(b"THIS IS A TEST FILE"), "new_york.jpg"), "text": "you know just sending an anonymous message", }, - headers=self._make_auth_headers(web.password), ) content = res.get_data() assert res.status_code == 200 @@ -270,7 +246,6 @@ class TestWeb: buffered=True, content_type="multipart/form-data", data={"file[]": (BytesIO(b"THIS IS A TEST FILE"), "new_york.jpg")}, - headers=self._make_auth_headers(web.password), ) content = res.get_data() assert res.status_code == 200 @@ -303,7 +278,6 @@ class TestWeb: buffered=True, content_type="multipart/form-data", data={}, - headers=self._make_auth_headers(web.password), ) content = res.get_data() assert res.status_code == 200 @@ -326,26 +300,6 @@ class TestWeb: res.get_data() assert res.status_code == 200 - def test_public_mode_off(self, temp_dir, common_obj): - web = web_obj(temp_dir, common_obj, "receive") - web.settings.set("general", "public", False) - - with web.app.test_client() as c: - # Load / without auth - res = c.get("/") - res.get_data() - assert res.status_code == 401 - - # But static resources should work without auth - res = c.get(f"{web.static_url_path}/css/style.css") - res.get_data() - assert res.status_code == 200 - - # Load / with valid auth - res = c.get("/", headers=self._make_auth_headers(web.password)) - res.get_data() - assert res.status_code == 200 - def test_cleanup(self, common_obj, temp_dir_1024, temp_file_1024): web = web_obj(temp_dir_1024, common_obj, "share", 3) @@ -356,12 +310,6 @@ class TestWeb: assert os.path.exists(temp_dir_1024) is False assert web.cleanup_filenames == [] - def _make_auth_headers(self, password): - auth = base64.b64encode(b"onionshare:" + password.encode()).decode() - h = Headers() - h.add("Authorization", "Basic " + auth) - return h - class TestZipWriterDefault: @pytest.mark.parametrize( @@ -450,8 +398,7 @@ def live_server(web): proc.start() url = "http://127.0.0.1:{}".format(port) - auth = base64.b64encode(b"onionshare:" + web.password.encode()).decode() - req = Request(url, headers={"Authorization": "Basic {}".format(auth)}) + req = Request(url) attempts = 20 while True: @@ -509,7 +456,7 @@ class TestRangeRequests: url = "/download" with web.app.test_client() as client: - resp = client.get(url, headers=self._make_auth_headers(web.password)) + resp = client.get(url) assert resp.headers["ETag"].startswith('"sha256:') assert resp.headers["Accept-Ranges"] == "bytes" assert resp.headers.get("Last-Modified") is not None @@ -524,7 +471,7 @@ class TestRangeRequests: contents = f.read() with web.app.test_client() as client: - resp = client.get(url, headers=self._make_auth_headers(web.password)) + resp = client.get(url) assert resp.status_code == 200 assert resp.data == contents @@ -536,7 +483,7 @@ class TestRangeRequests: contents = f.read() with web.app.test_client() as client: - headers = self._make_auth_headers(web.password) + headers = Headers() headers.extend({"Range": "bytes=0-10"}) resp = client.get(url, headers=headers) assert resp.status_code == 206 @@ -572,7 +519,7 @@ class TestRangeRequests: contents = f.read() with web.app.test_client() as client: - headers = self._make_auth_headers(web.password) + headers = Headers() resp = client.get(url, headers=headers) assert resp.status_code == 200 @@ -587,7 +534,7 @@ class TestRangeRequests: url = "/download" with web.app.test_client() as client: - headers = self._make_auth_headers(web.password) + headers = Headers() resp = client.get(url, headers=headers) assert resp.status_code == 200 last_mod = resp.headers["Last-Modified"] @@ -602,7 +549,7 @@ class TestRangeRequests: url = "/download" with web.app.test_client() as client: - headers = self._make_auth_headers(web.password) + headers = Headers() resp = client.get(url, headers=headers) assert resp.status_code == 200 @@ -621,11 +568,6 @@ class TestRangeRequests: resp = client.get(url, headers=headers) assert resp.status_code == 206 - def _make_auth_headers(self, password): - auth = base64.b64encode(b"onionshare:" + password.encode()).decode() - h = Headers() - h.add("Authorization", "Basic " + auth) - return h @pytest.mark.skipif(sys.platform != "Linux", reason="requires Linux") @check_unsupported("curl", ["--version"]) @@ -638,12 +580,9 @@ class TestRangeRequests: with live_server(web) as url: # Debugging help from `man curl`, on error 33 # 33 HTTP range error. The range "command" didn't work. - auth_header = self._make_auth_headers(web.password) subprocess.check_call( [ "curl", - "-H", - str(auth_header).strip(), "--output", str(download), "--continue-at", @@ -663,12 +602,9 @@ class TestRangeRequests: download.write("x" * 10) with live_server(web) as url: - auth_header = self._make_auth_headers(web.password) subprocess.check_call( [ "wget", - "--header", - str(auth_header).strip(), "--continue", "-O", str(download), |