142 lines
5.4 KiB
Python
142 lines
5.4 KiB
Python
"""Authorized, fail-closed Firebird connection boundary."""
|
|
|
|
import os
|
|
from pathlib import Path
|
|
from types import MappingProxyType
|
|
from typing import Any
|
|
|
|
from .catalog import FirebirdCatalog
|
|
from .firebird_queries import _ADAPTER_REGISTRATION_TOKEN, _register_approved_adapter
|
|
|
|
|
|
AUTHORIZED_DATABASE_PATH = Path(
|
|
r"D:\PROJETOS\GTISISTEMAS\Projeto\TESTESOFICIAIS.FDB"
|
|
)
|
|
|
|
|
|
class _FirebirdAdapter:
|
|
"""Sealed adapter implementation used by the authorized connection."""
|
|
|
|
__slots__ = ("_connection", "_read_only_evidence", "_seal")
|
|
|
|
def __init__(self, connection: Any, read_only_evidence: dict[str, Any], seal: object):
|
|
if seal is not _ADAPTER_CREATION_TOKEN:
|
|
raise TypeError("adapter construction is private")
|
|
self._connection = connection
|
|
self._read_only_evidence = MappingProxyType(dict(read_only_evidence))
|
|
self._seal = seal
|
|
|
|
@property
|
|
def read_only(self) -> bool:
|
|
return self.read_only_evidence.get("accepted") is True
|
|
|
|
@property
|
|
def read_only_evidence(self):
|
|
return self._read_only_evidence
|
|
|
|
def execute(self, sql: str, params: tuple = ()):
|
|
cursor = self._connection.cursor()
|
|
cursor.execute(sql, params)
|
|
return cursor
|
|
|
|
def close(self):
|
|
self._connection.close()
|
|
|
|
|
|
_register_approved_adapter(_FirebirdAdapter, _ADAPTER_REGISTRATION_TOKEN)
|
|
_ADAPTER_CREATION_TOKEN = object()
|
|
|
|
|
|
def _create_firebird_adapter(connection: Any, read_only_evidence: dict[str, Any], seal: object) -> _FirebirdAdapter:
|
|
if seal is not _ADAPTER_CREATION_TOKEN:
|
|
raise TypeError("adapter construction is private")
|
|
return _FirebirdAdapter(connection, read_only_evidence, seal)
|
|
|
|
|
|
def _normalized_path(path: Path) -> str:
|
|
return os.path.normcase(os.path.normpath(str(path.resolve(strict=False))))
|
|
|
|
|
|
def validate_authorized_database_path(path: os.PathLike[str] | str) -> Path:
|
|
"""Return the resolved authorized target or reject it before driver use."""
|
|
candidate = Path(path).resolve(strict=False)
|
|
authorized = AUTHORIZED_DATABASE_PATH.resolve(strict=False)
|
|
if _normalized_path(candidate) != _normalized_path(authorized):
|
|
raise ValueError("database path is not the authorized target")
|
|
if not authorized.is_file() or not candidate.is_file():
|
|
raise ValueError("authorized database path must be a regular file")
|
|
return authorized
|
|
|
|
|
|
def validate_authorized_database_identity(
|
|
identity: Any, path: os.PathLike[str] | str = AUTHORIZED_DATABASE_PATH
|
|
) -> str:
|
|
"""Reject an engine identity that does not identify the authorized target."""
|
|
reported = str(identity or "").strip().strip('"')
|
|
if not reported:
|
|
raise ValueError("database identity is unavailable")
|
|
authorized = Path(path).resolve(strict=False)
|
|
if any(separator in reported for separator in ("/", "\\")) or ":" in reported:
|
|
if _normalized_path(Path(reported)) != _normalized_path(authorized):
|
|
raise ValueError("database identity does not match authorized target")
|
|
elif os.path.normcase(reported) != os.path.normcase(authorized.name):
|
|
raise ValueError("database identity does not match authorized target")
|
|
return reported
|
|
|
|
|
|
def connect_authorized_read_only(
|
|
path: os.PathLike[str] | str,
|
|
driver: Any,
|
|
client_library: str | None = None,
|
|
) -> FirebirdCatalog:
|
|
"""Connect only to the authorized file with proven driver read-only mode.
|
|
|
|
Returns a ``FirebirdCatalog`` -- the closed, structured read-only API
|
|
(Mission 00D). No object with a public ``execute(sql)`` is ever handed
|
|
back to the caller; there is no arbitrary-SQL path from here on.
|
|
"""
|
|
database = validate_authorized_database_path(path)
|
|
options = {"database": str(database), "read_only": True}
|
|
if client_library is not None:
|
|
options["client_library"] = client_library
|
|
raw_connection = driver.connect(**options)
|
|
try:
|
|
if not isinstance(raw_connection, _FirebirdAdapter) or raw_connection._seal is not _ADAPTER_CREATION_TOKEN:
|
|
raise ValueError("driver did not return a trusted sealed read-only adapter")
|
|
evidence = raw_connection.read_only_evidence
|
|
if (
|
|
raw_connection.read_only is not True
|
|
or not isinstance(evidence, MappingProxyType)
|
|
or evidence.get("accepted") is not True
|
|
or evidence.get("driver_api") != "fdb.Connection.default_tpb"
|
|
or evidence.get("configured_tpb") != b"\x03\x08\x06\x0f\x11"
|
|
or evidence.get("observed_default_tpb") != evidence.get("configured_tpb")
|
|
or getattr(raw_connection._connection, "default_tpb", None) != evidence.get("configured_tpb")
|
|
):
|
|
raise ValueError("driver did not prove read-only enforcement")
|
|
return FirebirdCatalog(raw_connection)
|
|
except BaseException:
|
|
try:
|
|
close = getattr(raw_connection, "close", None)
|
|
if callable(close):
|
|
close()
|
|
except BaseException:
|
|
pass
|
|
raise
|
|
|
|
|
|
def get_database_identity(catalog: FirebirdCatalog) -> Any:
|
|
"""Read the database identity through the closed catalog API."""
|
|
if not isinstance(catalog, FirebirdCatalog):
|
|
raise TypeError("catalog must be FirebirdCatalog")
|
|
rows = catalog.get_database_info()
|
|
if not rows:
|
|
return None
|
|
row = rows[0]
|
|
if isinstance(row, dict):
|
|
for key, value in row.items():
|
|
if str(key).upper() == "MON$DATABASE_NAME":
|
|
return value
|
|
return None
|
|
return row[0] if row else None
|