Fix robustness issues in Fritz!Box plugin before PR

Two independent reliability problems were identified during PR readiness
review. First, FritzConnection had no explicit timeout, meaning an
unreachable or slow Fritz!Box would block the plugin process indefinitely
until the OS TCP timeout fired (typically 2+ minutes), making the 60s
RUN_TIMEOUT in config.json ineffective. Second, hashlib.md5() called
without usedforsecurity=False raises ValueError on FIPS-enforced systems
(common in enterprise Docker hosts), silently breaking the guest WiFi
synthetic device feature for those users.

Changes:
- Add timeout=10 to FritzConnection(...) call (fritzbox.py:57)
  The fritzconnection library accepts a timeout parameter directly in
  __init__; it applies per individual HTTP request to the Fritz!Box,
  bounding each TR-064 call including the initial connection handshake.

- Add usedforsecurity=False to hashlib.md5() call (fritzbox.py:191)
  The MD5 hash is used only for deterministic MAC derivation (not for
  any security purpose), so the flag is semantically correct and lifts
  the FIPS restriction without changing the computed value.

- Update test assertion to include timeout=10 (test_fritzbox.py:307)
  assert_called_once_with checks the exact call signature; the test
  expectation must match the updated production code.

The plugin now fails fast on unreachable Fritz!Box (within 10s per
request) and works correctly on FIPS-enabled hosts. Default behavior
for standard deployments is unchanged.
This commit is contained in:
sebingel
2026-04-06 07:48:59 +00:00
parent 0648e8217c
commit 1d4fd09444
2 changed files with 3 additions and 2 deletions

View File

@@ -54,6 +54,7 @@ def get_fritzbox_connection(host, port, user, password, use_tls):
user=user,
password=password,
use_tls=use_tls,
timeout=10,
)
mylog('verbose', [f'[{pluginName}] Successfully connected to Fritz!Box'])
@@ -188,7 +189,7 @@ def create_guest_wifi_device(fc):
# The 02 prefix sets the locally-administered bit, ensuring no collision
# with real OUI-assigned MACs. The remaining 5 bytes come from an MD5
# hash of the Fritz!Box MAC so the guest MAC is stable across runs.
digest = hashlib.md5(f'GUEST:{normalize_mac(fritzbox_mac)}'.encode()).digest()
digest = hashlib.md5(f'GUEST:{normalize_mac(fritzbox_mac)}'.encode(), usedforsecurity=False).digest()
guest_mac = '02:' + ':'.join(f'{b:02x}' for b in digest[:5])
else:
# Fallback if we can't get Fritz!Box MAC