From 650481972fbab9e9d8f0b1af23c4fb6a88b4e8c0 Mon Sep 17 00:00:00 2001 From: David Lord Date: Wed, 21 Aug 2024 07:16:19 -0700 Subject: [PATCH] synchronize failed pin entry --- CHANGES.rst | 2 ++ src/werkzeug/debug/__init__.py | 14 +++++++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 2150ad299..b39cf5cf2 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -10,6 +10,8 @@ Unreleased 413 error. :issue:`2930` - Improve ``parse_options_header`` performance when parsing unterminated quoted string values. :issue:`2907` +- Debugger pin auth is synchronized across threads/processes when tracking + failed entries. :issue:`2916` Version 3.0.3 diff --git a/src/werkzeug/debug/__init__.py b/src/werkzeug/debug/__init__.py index 2eebd38a8..69ad3f4f4 100644 --- a/src/werkzeug/debug/__init__.py +++ b/src/werkzeug/debug/__init__.py @@ -13,6 +13,7 @@ from contextlib import ExitStack from io import BytesIO from itertools import chain +from multiprocessing import Value from os.path import basename from os.path import join from zlib import adler32 @@ -286,7 +287,7 @@ def __init__( self.console_init_func = console_init_func self.show_hidden_frames = show_hidden_frames self.secret = gen_salt(20) - self._failed_pin_auth = 0 + self._failed_pin_auth = Value("B") self.pin_logging = pin_logging if pin_security: @@ -454,8 +455,11 @@ def check_host_trust(self, environ: WSGIEnvironment) -> bool: return host_is_trusted(environ.get("HTTP_HOST"), self.trusted_hosts) def _fail_pin_auth(self) -> None: - time.sleep(5.0 if self._failed_pin_auth > 5 else 0.5) - self._failed_pin_auth += 1 + with self._failed_pin_auth.get_lock(): + count = self._failed_pin_auth.value + self._failed_pin_auth.value = count + 1 + + time.sleep(5.0 if count > 5 else 0.5) def pin_auth(self, request: Request) -> Response: """Authenticates with the pin.""" @@ -482,7 +486,7 @@ def pin_auth(self, request: Request) -> Response: auth = True # If we failed too many times, then we're locked out. - elif self._failed_pin_auth > 10: + elif self._failed_pin_auth.value > 10: exhausted = True # Otherwise go through pin based authentication @@ -490,7 +494,7 @@ def pin_auth(self, request: Request) -> Response: entered_pin = request.args["pin"] if entered_pin.strip().replace("-", "") == pin.replace("-", ""): - self._failed_pin_auth = 0 + self._failed_pin_auth.value = 0 auth = True else: self._fail_pin_auth()