Version 2.7.2: Umlaute in der Oberflaeche, Einbindungen an der Sitzung
This commit is contained in:
1 parent
11a55b20f8
commit
dcb4f57eeb
83 files changed
+1224
-658
No files matched your search
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "tesm-licensing"
|
||||
version = "2.7.1"
|
||||
version = "2.7.2"
|
||||
description = "Ed25519-basiertes Lizenz- und Aktivierungsprotokoll fuer TESM und TESM-Lizenzserver"
|
||||
requires-python = ">=3.11"
|
||||
dependencies = ["cryptography>=42"]
|
||||
|
||||
@@ -42,7 +42,7 @@ def _b64d(value: str, *, field: str) -> bytes:
|
||||
try:
|
||||
return base64.b64decode(value, validate=True)
|
||||
except (binascii.Error, ValueError, TypeError) as exc: # pragma: no cover - defensiv
|
||||
raise ValueError(f"{field} ist kein gueltiges Base64") from exc
|
||||
raise ValueError(f"{field} ist kein gültiges Base64") from exc
|
||||
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ def decode_code(code: str) -> dict[str, Any]:
|
||||
try:
|
||||
data = json.loads(base64.urlsafe_b64decode(cleaned.encode("ascii")).decode("utf-8"))
|
||||
except (binascii.Error, ValueError, UnicodeDecodeError) as exc:
|
||||
raise ValueError("Code ist unlesbar oder beschaedigt") from exc
|
||||
raise ValueError("Code ist unlesbar oder beschädigt") from exc
|
||||
if not isinstance(data, dict):
|
||||
raise ValueError("Code enthaelt kein Objekt")
|
||||
raise ValueError("Code enthält kein Objekt")
|
||||
return data
|
||||
@@ -161,7 +161,7 @@ def split_bundle(bundle: Mapping[str, Any]) -> tuple[dict[str, Any], str]:
|
||||
eingebettetem ``license_privkey``.
|
||||
"""
|
||||
if not isinstance(bundle, Mapping):
|
||||
raise InvalidLicenseFile("Lizenzdatei enthaelt kein Objekt")
|
||||
raise InvalidLicenseFile("Lizenzdatei enthält kein Objekt")
|
||||
|
||||
inner = bundle.get("license")
|
||||
if isinstance(inner, Mapping):
|
||||
@@ -194,10 +194,10 @@ def verify_license(
|
||||
|
||||
missing = [name for name in _PAYLOAD_FIELDS if name not in document]
|
||||
if missing:
|
||||
raise InvalidLicenseFile(f"Lizenzdokument unvollstaendig: {', '.join(missing)}")
|
||||
raise InvalidLicenseFile(f"Lizenzdokument unvollständig: {', '.join(missing)}")
|
||||
if int(document.get("fmt") or 0) != FORMAT_VERSION:
|
||||
raise InvalidLicenseFile(
|
||||
f"Nicht unterstuetzte Formatversion: {document.get('fmt')!r}"
|
||||
f"Nicht unterstützte Formatversion: {document.get('fmt')!r}"
|
||||
f" (erwartet {FORMAT_VERSION})"
|
||||
)
|
||||
if document.get("type") not in LICENSE_TYPES:
|
||||
@@ -207,17 +207,17 @@ def verify_license(
|
||||
|
||||
master_pubkey = str(document.get("master_pubkey") or "")
|
||||
if key_id(master_pubkey) != str(document.get("master_key_id") or ""):
|
||||
raise InvalidLicenseFile("master_key_id passt nicht zum eingebetteten Schluessel")
|
||||
raise InvalidLicenseFile("master_key_id passt nicht zum eingebetteten Schlüssel")
|
||||
|
||||
payload = {k: v for k, v in document.items() if k != "signature"}
|
||||
if not verify(
|
||||
payload, str(document.get("signature") or ""), master_pubkey, SIG_CONTEXT_LICENSE
|
||||
):
|
||||
raise SignatureInvalid("Signatur der Lizenzdatei ist ungueltig")
|
||||
raise SignatureInvalid("Signatur der Lizenzdatei ist ungültig")
|
||||
|
||||
if trusted_master_keys and master_pubkey not in set(trusted_master_keys):
|
||||
raise UntrustedIssuer(
|
||||
"Die Lizenz wurde nicht von einem vertrauenswuerdigen Lizenzserver ausgestellt"
|
||||
"Die Lizenz wurde nicht von einem vertrauenswürdigen Lizenzserver ausgestellt"
|
||||
)
|
||||
|
||||
|
||||
@@ -236,7 +236,7 @@ def license_status(
|
||||
lifetime = bool(document.get("lifetime"))
|
||||
warnings: list[str] = []
|
||||
if not issuer_pinned:
|
||||
warnings.append("Aussteller nicht gepinnt -- nur innere Konsistenz geprueft")
|
||||
warnings.append("Aussteller nicht gepinnt – nur innere Konsistenz geprüft")
|
||||
|
||||
issued_at: datetime | None = None
|
||||
expires_at: datetime | None = None
|
||||
@@ -248,7 +248,7 @@ def license_status(
|
||||
try:
|
||||
parsed = parse_iso(str(raw))
|
||||
except ValueError:
|
||||
warnings.append(f"Feld {name} ist kein gueltiges Datum")
|
||||
warnings.append(f"Feld {name} ist kein gültiges Datum")
|
||||
continue
|
||||
if name == "issued_at":
|
||||
issued_at = parsed
|
||||
|
||||
@@ -77,7 +77,7 @@ def build_client_request(
|
||||
if action not in ACTIONS:
|
||||
raise ProtocolViolation(f"Unbekannte Aktion: {action!r}")
|
||||
if not client_private_key:
|
||||
raise ProtocolViolation("Kein Client-Schluessel vorhanden -- Lizenz unvollstaendig importiert")
|
||||
raise ProtocolViolation("Kein Client-Schlüssel vorhanden | Lizenz unvollständig importiert")
|
||||
|
||||
payload: dict[str, Any] = {
|
||||
"fmt": FORMAT_VERSION,
|
||||
@@ -130,22 +130,22 @@ def verify_master_response(
|
||||
if not isinstance(response, Mapping):
|
||||
raise ProtocolViolation("Antwort ist kein Objekt")
|
||||
if int(response.get("fmt") or 0) != FORMAT_VERSION:
|
||||
raise ProtocolViolation("Nicht unterstuetzte Protokollversion")
|
||||
raise ProtocolViolation("Nicht unterstützte Protokollversion")
|
||||
|
||||
payload = {k: v for k, v in response.items() if k != "signature"}
|
||||
if not verify(
|
||||
payload, str(response.get("signature") or ""), master_public_key, SIG_CONTEXT_RESPONSE
|
||||
):
|
||||
raise SignatureInvalid("Signatur der Antwort ist ungueltig")
|
||||
raise SignatureInvalid("Signatur der Antwort ist ungültig")
|
||||
|
||||
if str(response.get("license_id") or "") != expected_license_id:
|
||||
raise ProtocolViolation("Antwort gehoert zu einer anderen Lizenz")
|
||||
raise ProtocolViolation("Antwort gehört zu einer anderen Lizenz")
|
||||
if str(response.get("fingerprint") or "") != expected_fingerprint:
|
||||
raise ProtocolViolation("Antwort gehoert zu einer anderen Maschine")
|
||||
raise ProtocolViolation("Antwort gehört zu einer anderen Maschine")
|
||||
if str(response.get("action") or "") != expected_action:
|
||||
raise ProtocolViolation("Antwort gehoert zu einer anderen Aktion")
|
||||
raise ProtocolViolation("Antwort gehört zu einer anderen Aktion")
|
||||
if str(response.get("nonce") or "") != expected_nonce:
|
||||
raise ReplayDetected("Antwort gehoert nicht zu dieser Anfrage")
|
||||
raise ReplayDetected("Antwort gehört nicht zu dieser Anfrage")
|
||||
if str(response.get("status") or "") not in RESPONSE_STATES:
|
||||
raise ProtocolViolation("Unbekannter Antwortstatus")
|
||||
|
||||
@@ -156,4 +156,4 @@ def verify_master_response(
|
||||
if not isinstance(update, Mapping):
|
||||
raise ProtocolViolation("license_update ist kein Objekt")
|
||||
if int(update.get("seq") or 0) < int(current_seq or 0):
|
||||
raise ReplayDetected("license_update ist aelter als die installierte Lizenz")
|
||||
raise ReplayDetected("license_update ist älter als die installierte Lizenz")
|
||||
Reference in new issue
Block a user