fix: what bandit and the remaining lint rules found

- The MD5 of the password is what the phone's login API expects, the wire
  format and no protection of ours (the session runs over HTTPS):
  hashlib.md5(..., usedforsecurity=False) (B324). The digest is the same.
- A failed logout in close() and an unreadable system info in get_facts()
  now log at debug level (B110), so a swallowed failure leaves a trace; the
  module gets its logger.
- The comment on the "yealink" fingerprint rule moves above it (ruff
  format had split the line around it) and is in English.
This commit is contained in:
Christian Manivong committed 2026-10-23 08:42:31 +02:00
1 parent 4a4f9378c5
commit 946dff5d08
1 file changed
+10 -6
+10 -6
View File
@@ -14,6 +14,7 @@ automatically) or via ``optional_args={"verify_ssl": False}``.
from __future__ import annotations
import hashlib
import logging
import socket
from typing import Any
@@ -22,6 +23,8 @@ from napalm.base.exceptions import ConnectionException
from napalm_device_types import FingerprintRule, PhoneDriver
from requests.exceptions import RequestException
logger = logging.getLogger(__name__)
class YealinkDriver(PhoneDriver):
"""NAPALM driver for Yealink IP phones (T-series, W-series, CP-series, VP-series)."""
@@ -35,9 +38,8 @@ class YealinkDriver(PhoneDriver):
"80:5E:0C", # YEALINK(XIAMEN) NETWORK TECHNOLOGY — IEEE, verifiziert an T58V
]
HTTP_FINGERPRINT = [
FingerprintRule(
"yealink", weight=10.0
), # nicht mandatory: Yealink/api redirect hat kein "yealink" im Body
# Not mandatory: the redirect of some models to their API page has no "yealink" in it.
FingerprintRule("yealink", weight=10.0),
FingerprintRule("sip-t", weight=5.0),
FingerprintRule("sip-w", weight=5.0),
FingerprintRule("sip-cp", weight=5.0),
@@ -70,7 +72,9 @@ class YealinkDriver(PhoneDriver):
def open(self) -> None:
self._session = requests.Session()
self._session.verify = self._verify_ssl
pw_hash = hashlib.md5(self.password.encode()).hexdigest()
# The login API takes the password as an MD5 hex digest: the wire format, not a
# protection (the session runs over HTTPS).
pw_hash = hashlib.md5(self.password.encode(), usedforsecurity=False).hexdigest()
try:
resp = self._session.post(
f"{self._base_url}{self._LOGIN_PATH}",
@@ -92,7 +96,7 @@ class YealinkDriver(PhoneDriver):
timeout=5,
)
except Exception:
pass
logger.debug("Logging out of the phone failed: ignored", exc_info=True)
self._session.close()
self._session = None
@@ -123,7 +127,7 @@ class YealinkDriver(PhoneDriver):
payload = data.get("data") or data.get("error") or {}
info = payload if isinstance(payload, dict) else {}
except Exception:
pass
logger.debug("Reading the system info failed: ignored", exc_info=True)
model = info.get("phoneName") or info.get("model") or "Yealink"
firmware = info.get("firmware") or info.get("firmwareVersion") or ""