| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 
 | def get_pin_and_cookie_name(app: WSGIApplication,
 ) -> tuple[] | tuple[]:
 """Given an application object this returns a semi-stable 9 digit pin
 code and a random key.  The hope is that this is stable between
 restarts to not make debugging particularly frustrating.  If the pin
 was forcefully disabled this returns `None`.
 
 Second item in the resulting tuple is the cookie name for remembering.
 """
 pin = os.environ.get("WERKZEUG_DEBUG_PIN")
 rv = None
 num = None
 
 # Pin was explicitly disabled
 if pin == "off":
 return None, None
 
 # Pin was provided explicitly
 if pin is not None and pin.replace("-", "").isdecimal():
 # If there are separators in the pin, return it directly
 if "-" in pin:
 rv = pin
 else:
 num = pin
 
 modname = getattr(app, "__module__", t.cast(object, app).__class__.__module__)
 username: str | None
 
 try:
 # getuser imports the pwd module, which does not exist in Google
 # App Engine. It may also raise a KeyError if the UID does not
 # have a username, such as in Docker.
 username = getpass.getuser()
 except (ImportError, KeyError):
 username = None
 
 mod = sys.modules.get(modname)
 
 # This information only exists to make the cookie unique on the
 # computer, not as a security feature.
 probably_public_bits = [
 username,
 modname,
 getattr(app, "__name__", type(app).__name__),
 getattr(mod, "__file__", None),
 ]
 
 # This information is here to make it harder for an attacker to
 # guess the cookie name.  They are unlikely to be contained anywhere
 # within the unauthenticated debug page.
 private_bits = []
 
 h = hashlib.sha1()
 for bit in chain(probably_public_bits, private_bits):
 if not bit:
 continue
 if isinstance(bit, str):
 bit = bit.encode()
 h.update(bit)
 h.update(b"cookiesalt")
 
 cookie_name = f"__wzd{h.hexdigest()[]}"
 
 # If we need to generate a pin we salt it a bit more so that we don't
 # end up with the same value and generate out 9 digits
 if num is None:
 h.update(b"pinsalt")
 num = f"{int(h.hexdigest(), 16):09d}"[]
 
 # Format the pincode in groups of digits for easier remembering if
 # we don't have a result yet.
 if rv is None:
 for group_size in 5, 4, 3:
 if len(num) % group_size == 0:
 rv = "-".join(
 num[].rjust(group_size, "0")
 for x in range(0, len(num), group_size)
 )
 break
 else:
 rv = num
 
 return rv, cookie_name
 
 
 |