#!/usr/bin/env python3 """ Debug script to examine the exact WWW-Authenticate header that Monero wallet RPC sends and how urllib handles it. """ import urllib.request import urllib.error import json def examine_auth_challenge(): """Look at the WWW-Authenticate header from the server""" print("=== Examining Authentication Challenge ===") rpc_url = "http://127.0.0.1:18083/json_rpc" payload = {"jsonrpc": "2.0", "id": 1, "method": "get_height"} data = json.dumps(payload).encode() # Make request without auth to get the challenge req = urllib.request.Request( rpc_url, data=data, headers={"Content-Type": "application/json"} ) try: with urllib.request.urlopen(req) as resp: print("Unexpected: No auth required") return None except urllib.error.HTTPError as e: if e.code == 401: www_auth = e.headers.get("WWW-Authenticate", "") print(f"WWW-Authenticate header: {www_auth!r}") # Parse it if www_auth.startswith("Digest "): challenge = www_auth[7:].strip() print(f"Challenge details: {challenge}") # Parse individual components import re pattern = r'(\w+)=(?:"([^"]*)"|([^,\s]+))' matches = re.findall(pattern, challenge) print("Parsed components:") for key, quoted_val, unquoted_val in matches: val = quoted_val if quoted_val else unquoted_val print(f" {key} = {val!r}") return dict( (key, quoted_val if quoted_val else unquoted_val) for key, quoted_val, unquoted_val in matches ) else: print(f"Not Digest auth: {www_auth}") return None else: print(f"Unexpected error: {e.code} {e.reason}") return None if __name__ == "__main__": challenge = examine_auth_challenge() if challenge: print() print("=== Analysis ===") print(f"Realm: {challenge.get('realm', 'NOT SET')}") print(f"Nonce: {challenge.get('nonce', 'NOT SET')}") print(f"QOP: {challenge.get('qop', 'NOT SET')}") print(f"Algorithm: {challenge.get('algorithm', 'NOT SET (defaults to MD5)')}") # Check for any unusual parameters standard_params = {"realm", "nonce", "qop", "algorithm", "opaque"} extra_params = set(challenge.keys()) - standard_params if extra_params: print(f"Extra parameters: {extra_params}")