""" Java javax.security APIs implemented in Python. javax.security package - Subject, Principal, Policy, Permission, etc. Desktop stub implementation. """ from __future__ import annotations from .._core import Stub, AndroidOnlyError from typing import List, Set, Optional __all__ = [ "AuthProvider", "Subject", "Principal", "Policy", "PrivateCredentialPermission", "SubjectDomainCombiner", "Refreshable", "Destroyable", "RefreshFailedException", "DestroyFailedException", "CredentialException", "CredentialExpiredException", "CredentialNotFoundException", "UnrecoverableKeyException", "UnrecoverableEntryException", "KeyStoreCallbackHandler", "DomainLoadStoreParameter", "Certificate", "CodeSource", "ProtectionDomain", "Permissions", "AllPermission", "BasicPermission", "Permission", "PermissionCollection", "UnresolvedPermission", "PermissionsEnumerator", "Guard", "GuardedObject", ] # ============================================================ # Principal # ============================================================ class Principal(Stub): """ java.security.Principal Represents a principal (entity) such as a user or group. """ def __init__(self, name: str = ""): super().__init__() self._name = name def getName(self) -> str: return self._name def implies(self, subject: "Subject") -> bool: return False def toString(self) -> str: return self._name def equals(self, other) -> bool: if isinstance(other, Principal): return self._name == other._name return False def hashCode(self) -> int: return hash(self._name) & 0x7FFFFFFF # ============================================================ # Subject # ============================================================ class Subject(Stub): """ javax.security.auth.Subject Represents a grouping of related information for a single entity. """ def __init__(self, read_only: bool = False, principals: Set[Principal] = None, pub_creds: Set = None, priv_creds: Set = None): super().__init__() self._read_only = read_only self._principals = set(principals) if principals else set() self._public_credentials = set(pub_creds) if pub_creds else set() self._private_credentials = set(priv_creds) if priv_creds else set() def getPrincipals(self) -> Set[Principal]: return set(self._principals) def getPrivateCredentials(self) -> Set: return set(self._private_credentials) def getPublicCredentials(self) -> Set: return set(self._public_credentials) def setReadOnly(self): self._read_only = True def isReadOnly(self) -> bool: return self._read_only @staticmethod def doAs(subject: "Subject", action: callable) -> Any: return action() @staticmethod def doAsPrivileged(subject: "Subject", action: callable, access: Any) -> Any: return action() def toString(self) -> str: return (f"Subject@{hex(id(self))}[principals={len(self._principals)}, " f"read_only={self._read_only}]") def equals(self, other) -> bool: if not isinstance(other, Subject): return False return (self._principals == other._principals and self._read_only == other._read_only) def hashCode(self) -> int: return hash(frozenset(self._principals)) & 0x7FFFFFFF # ============================================================ # Policy # ============================================================ class Policy(Stub): """ java.security.Policy Policy for permissions (stub). """ _policy = None def __init__(self): super().__init__() self._parameters = None @staticmethod def getPolicy() -> "Policy": if Policy._policy is None: Policy._policy = Policy() return Policy._policy @staticmethod def setPolicy(policy: "Policy"): Policy._policy = policy def getParameters(self): return self._parameters def setParameters(self, params): self._parameters = params def implies(self, domain: "ProtectionDomain", permission: "Permission") -> bool: return True def toString(self) -> str: return f"Policy@{hex(id(self))}" def equals(self, other) -> bool: return self is other def hashCode(self) -> int: return hash(self) & 0x7FFFFFFF # ============================================================ # AuthProvider # ============================================================ class AuthProvider(Stub): """ javax.security.auth.AuthProvider Provider for authentication services. """ def __init__(self): super().__init__() def login(self, subject: Subject, handler: Any): pass def logout(self, subject: Subject): pass def setCallbackHandler(self, handler: Any): pass def toString(self) -> str: return f"AuthProvider@{hex(id(self))}" def equals(self, other) -> bool: return self is other def hashCode(self) -> int: return hash(self) & 0x7FFFFFFF # ============================================================ # PrivateCredentialPermission # ============================================================ class PrivateCredentialPermission(Stub): """ javax.security.auth.PrivateCredentialPermission Permission to access private credentials. """ def __init__(self, name: str = "", actions: str = "read"): super().__init__() self._name = name self._actions = actions def getName(self) -> str: return self._name def getActions(self) -> str: return self._actions def getCredentialClass(self) -> str: return self._name def getPrincipals(self) -> List[List]: return [] def implies(self, permission: "Permission") -> bool: return isinstance(permission, PrivateCredentialPermission) and self._name == permission._name def toString(self) -> str: return f'PrivateCredentialPermission "{self._name}" "{self._actions}"' def equals(self, other) -> bool: if isinstance(other, PrivateCredentialPermission): return self._name == other._name and self._actions == other._actions return False def hashCode(self) -> int: return hash((self._name, self._actions)) & 0x7FFFFFFF # ============================================================ # SubjectDomainCombiner # ============================================================ class SubjectDomainCombiner(Stub): """ javax.security.auth.SubjectDomainCombiner Combines ProtectionDomains with Subject context. """ def __init__(self, subject: Subject): super().__init__() self._subject = subject def combine(self, current_domains: List, assigned_domains: List) -> List: return list(current_domains or []) + list(assigned_domains or []) def getSubject(self) -> Subject: return self._subject def toString(self) -> str: return f"SubjectDomainCombiner@{hex(id(self))}" def equals(self, other) -> bool: return self is other def hashCode(self) -> int: return hash(self) & 0x7FFFFFFF # ============================================================ # Refreshable / Destroyable interfaces # ============================================================ class Refreshable(Stub): """ javax.security.auth.Refreshable Interface for refreshable credentials. """ def isCurrent(self) -> bool: return True def refresh(self): raise AndroidOnlyError("refresh not supported on desktop") class Destroyable(Stub): """ javax.security.auth.Destroyable Interface for destroyable credentials. """ def isDestroyed(self) -> bool: return False def destroy(self): pass # ============================================================ # Exceptions # ============================================================ class RefreshFailedException(Exception, Stub): def __init__(self, message: str = None): super().__init__(message or "Refresh failed") self._message = message def toString(self) -> str: return f"RefreshFailedException: {self._message}" def equals(self, other) -> bool: return isinstance(other, RefreshFailedException) and self._message == other._message def hashCode(self) -> int: return hash(self._message) & 0x7FFFFFFF class DestroyFailedException(Exception, Stub): def __init__(self, message: str = None): super().__init__(message or "Destroy failed") self._message = message def toString(self) -> str: return f"DestroyFailedException: {self._message}" def equals(self, other) -> bool: return isinstance(other, DestroyFailedException) and self._message == other._message def hashCode(self) -> int: return hash(self._message) & 0x7FFFFFFF class CredentialException(Exception, Stub): def __init__(self, message: str = None): super().__init__(message or "Credential error") self._message = message def toString(self) -> str: return f"CredentialException: {self._message}" class CredentialExpiredException(CredentialException): def __init__(self, message: str = None): super().__init__(message or "Credential expired") class CredentialNotFoundException(CredentialException): def __init__(self, message: str = None): super().__init__(message or "Credential not found") class UnrecoverableKeyException(Exception, Stub): def __init__(self, message: str = None): super().__init__(message or "Unrecoverable key") self._message = message def toString(self) -> str: return f"UnrecoverableKeyException: {self._message}" class UnrecoverableEntryException(Exception, Stub): def __init__(self, message: str = None): super().__init__(message or "Unrecoverable entry") self._message = message def toString(self) -> str: return f"UnrecoverableEntryException: {self._message}" # ============================================================ # KeyStoreCallbackHandler # ============================================================ class KeyStoreCallbackHandler(Stub): """ javax.security.auth.callback.KeyStoreCallbackHandler Handler for key store callbacks. """ def __init__(self): super().__init__() def handle(self, callbacks: List): pass def toString(self) -> str: return f"KeyStoreCallbackHandler@{hex(id(self))}" def equals(self, other) -> bool: return self is other def hashCode(self) -> int: return hash(self) & 0x7FFFFFFF # ============================================================ # DomainLoadStoreParameter # ============================================================ class DomainLoadStoreParameter(Stub): """ java.security.DomainLoadStoreParameter Configuration data for loading/storing keystore domains. """ def __init__(self, config: dict = None): super().__init__() self._config = config or {} def getConfiguration(self) -> dict: return self._config def toString(self) -> str: return f"DomainLoadStoreParameter@{hex(id(self))}" def equals(self, other) -> bool: return self is other def hashCode(self) -> int: return hash(self) & 0x7FFFFFFF # ============================================================ # Certificate # ============================================================ class Certificate(Stub): """ java.security.cert.Certificate Abstract class for managing certificates. """ def __init__(self, cert_type: str = "X.509", encoded: bytes = None): super().__init__() self._cert_type = cert_type self._encoded = encoded or b'' def getType(self) -> str: return self._cert_type def getEncoded(self) -> bytes: return self._encoded def getPublicKey(self): return None def toString(self) -> str: return f"Certificate@{hex(id(self))}[type={self._cert_type}]" def equals(self, other) -> bool: if isinstance(other, Certificate): return self._encoded == other._encoded return False def hashCode(self) -> int: return hash(bytes(self._encoded)) & 0x7FFFFFFF # ============================================================ # Permission & PermissionCollection # ============================================================ class Permission(Stub): """ java.security.Permission Abstract class for representing access to a system resource. """ def __init__(self, name: str = ""): super().__init__() self._name = name def getName(self) -> str: return self._name def getActions(self) -> str: return "" def implies(self, permission: "Permission") -> bool: return self.equals(permission) def toString(self) -> str: return f'Permission "{self._name}"' def equals(self, other) -> bool: if isinstance(other, Permission): return self._name == other._name return False def hashCode(self) -> int: return hash(self._name) & 0x7FFFFFFF class PermissionCollection(Stub): """ java.security.PermissionCollection Abstract class for holding a collection of Permission objects. """ def __init__(self): super().__init__() self._permissions = [] self._read_only = False def add(self, permission: Permission): if not self._read_only: self._permissions.append(permission) def implies(self, permission: Permission) -> bool: for p in self._permissions: if p.implies(permission): return True return False def elements(self): return iter(self._permissions) def isReadOnly(self) -> bool: return self._read_only def setReadOnly(self): self._read_only = True def toString(self) -> str: return f"PermissionCollection@{hex(id(self))}[size={len(self._permissions)}]" def equals(self, other) -> bool: return self is other def hashCode(self) -> int: return hash(self) & 0x7FFFFFFF class Permissions(PermissionCollection): """ java.security.Permissions A collection of Permission objects. """ def add(self, permission: Permission): super().add(permission) def implies(self, permission: Permission) -> bool: return super().implies(permission) def elements(self): return super().elements() def toString(self) -> str: return f"Permissions@{hex(id(self))}[size={len(self._permissions)}]" class AllPermission(Permission): """ java.security.AllPermission A permission that implies all other permissions. """ def __init__(self): super().__init__("") def implies(self, permission: Permission) -> bool: return True def getActions(self) -> str: return "" def toString(self) -> str: return "AllPermission" class BasicPermission(Permission): """ java.security.BasicPermission Base class for basic permissions. """ def __init__(self, name: str = "", actions: str = ""): super().__init__(name) self._actions = actions def implies(self, permission: Permission) -> bool: if isinstance(permission, BasicPermission): return self._name == permission._name or permission._name.startswith(self._name + ".") return False def getActions(self) -> str: return self._actions def toString(self) -> str: return f'BasicPermission "{self._name}"' def equals(self, other) -> bool: if isinstance(other, BasicPermission): return self._name == other._name return False def hashCode(self) -> int: return hash(self._name) & 0x7FFFFFFF class UnresolvedPermission(Permission): """ java.security.UnresolvedPermission A permission that was not resolved when the PermissionCollection was built. """ def __init__(self, perm_type: str = "", name: str = "", actions: str = "", certs: List = None): super().__init__(name) self._unresolved_type = perm_type self._unresolved_actions = actions self._unresolved_certs = certs or [] def getUnresolvedType(self) -> str: return self._unresolved_type def getUnresolvedName(self) -> str: return self._name def getUnresolvedActions(self) -> str: return self._unresolved_actions def getUnresolvedCerts(self) -> List: return list(self._unresolved_certs) def implies(self, permission: Permission) -> bool: return False def toString(self) -> str: return f'UnresolvedPermission "{self._unresolved_type}" "{self._name}" "{self._unresolved_actions}"' def equals(self, other) -> bool: if isinstance(other, UnresolvedPermission): return (self._unresolved_type == other._unresolved_type and self._name == other._name) return False def hashCode(self) -> int: return hash((self._unresolved_type, self._name)) & 0x7FFFFFFF class PermissionsEnumerator(Stub): """ java.security.PermissionsEnumerator Enumerator over Permission objects. """ def __init__(self, permissions: List): super().__init__() self._permissions = list(permissions) self._index = 0 def hasMoreElements(self) -> bool: return self._index < len(self._permissions) def nextElement(self) -> Permission: if self._index < len(self._permissions): p = self._permissions[self._index] self._index += 1 return p return None def toString(self) -> str: return f"PermissionsEnumerator@{hex(id(self))}" # ============================================================ # CodeSource # ============================================================ class CodeSource(Stub): """ java.security.CodeSource Represents the codebase and certificates from which code originated. """ def __init__(self, location: str = None, certs: List = None, code_signers: List = None): super().__init__() self._location = location self._certificates = certs or [] self._code_signers = code_signers or [] def getCertificates(self) -> List: return list(self._certificates) def getCodeSigners(self) -> List: return list(self._code_signers) def getLocation(self) -> str: return self._location def implies(self, codesource: "CodeSource") -> bool: return self._location == codesource._location def toString(self) -> str: return f"CodeSource@{hex(id(self))}[location={self._location}]" def equals(self, other) -> bool: if isinstance(other, CodeSource): return self._location == other._location return False def hashCode(self) -> int: return hash(self._location) & 0x7FFFFFFF # ============================================================ # ProtectionDomain # ============================================================ class ProtectionDomain(Stub): """ java.security.ProtectionDomain Groups a CodeSource and Permissions for code access control. """ def __init__(self, codesource: CodeSource = None, permissions: PermissionCollection = None, principals: List[Principal] = None, static_permissions: bool = False): super().__init__() self._codesource = codesource self._permissions = permissions or Permissions() self._principals = principals or [] self._static_permissions = static_permissions def getCodeSource(self) -> CodeSource: return self._codesource def getPermissions(self) -> PermissionCollection: return self._permissions def getPrincipals(self) -> List[Principal]: return list(self._principals) def implies(self, permission: Permission) -> bool: return self._permissions.implies(permission) if self._permissions else False def toString(self) -> str: return f"ProtectionDomain@{hex(id(self))}[codesource={self._codesource}]" def equals(self, other) -> bool: return self is other def hashCode(self) -> int: return hash(self) & 0x7FFFFFFF # ============================================================ # Guard & GuardedObject # ============================================================ class Guard(Stub): """ java.security.Guard Interface for objects that guard access to another object. """ def checkGuard(self, obj: Any): raise NotImplementedError def toString(self) -> str: return f"Guard@{hex(id(self))}" def equals(self, other) -> bool: return self is other def hashCode(self) -> int: return hash(self) & 0x7FFFFFFF class GuardedObject(Stub): """ java.security.GuardedObject Wraps an object and guards access to it with a Guard. """ def __init__(self, obj: Any = None, guard: Guard = None): super().__init__() self._object = obj self._guard = guard def getObject(self) -> Any: if self._guard: self._guard.checkGuard(self._object) return self._object def setGuard(self, guard: Guard): self._guard = guard def toString(self) -> str: return f"GuardedObject@{hex(id(self))}[guarded={self._guard is not None}]" def equals(self, other) -> bool: return self is other def hashCode(self) -> int: return hash(self) & 0x7FFFFFFF