From 443961222fbf9837d16af2311dd7e440c57e4e3a Mon Sep 17 00:00:00 2001 From: asus Date: Wed, 22 Apr 2026 19:11:24 +0330 Subject: [PATCH] fix cert --- cert_installer.py | 72 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/cert_installer.py b/cert_installer.py index 1c49762..7c75a29 100644 --- a/cert_installer.py +++ b/cert_installer.py @@ -40,6 +40,46 @@ def _has_cmd(name: str) -> bool: return shutil.which(name) is not None +def _is_termux() -> bool: + prefix = os.environ.get("PREFIX", "") + return ( + "com.termux/files/usr" in prefix + or "com.termux/files/usr" in os.environ.get("PATH", "") + or bool(os.environ.get("TERMUX_VERSION")) + or os.path.exists("/data/data/com.termux/files/usr") + ) + + +def _android_cert_hint() -> str: + return ( + "Import the certificate in Android Settings > Security > " + "Encryption & credentials > Install a certificate > CA certificate." + ) + + +def _stage_android_cert(cert_path: str, cert_name: str) -> str | None: + """ + Copy the CA cert to a user-visible location on Android/Termux so the user + can import it through Android's certificate installer UI. + """ + base = cert_name.replace(" ", "_") + candidates = [ + os.path.expanduser("~/storage/downloads"), + "/sdcard/Download", + "/storage/emulated/0/Download", + ] + for folder in candidates: + if not os.path.isdir(folder): + continue + dest = os.path.join(folder, f"{base}.crt") + try: + shutil.copy2(cert_path, dest) + return dest + except OSError: + continue + return None + + # ───────────────────────────────────────────────────────────────────────────── # Windows # ───────────────────────────────────────────────────────────────────────────── @@ -275,6 +315,31 @@ def _is_trusted_linux(cert_path: str) -> bool: return False +def _install_termux_android(cert_path: str, cert_name: str) -> bool: + """ + Android does not allow a normal user-space process to silently install a CA + into the OS/browser trust store. On Termux we can only stage the file and + guide the user to Android's certificate installer. + """ + staged = _stage_android_cert(cert_path, cert_name) + log.warning("Detected Termux/Android environment.") + log.warning( + "Automatic CA installation into Android's system/browser trust store " + "is not supported from Termux without user interaction." + ) + if staged: + log.warning("Certificate copied to: %s", staged) + else: + log.warning( + "Could not copy the certificate to shared storage automatically. " + "Run 'termux-setup-storage' in Termux first, then try again." + ) + log.warning("You can also import this file directly: %s", cert_path) + log.warning(_android_cert_hint()) + log.warning("After import, fully close and reopen the browser.") + return False + + # ───────────────────────────────────────────────────────────────────────────── # Firefox NSS (cross-platform) # ───────────────────────────────────────────────────────────────────────────── @@ -326,6 +391,9 @@ def is_ca_trusted(cert_path: str) -> bool: """Return True if the CA cert appears to be already installed.""" system = platform.system() try: + if _is_termux(): + # Android's user/system CA stores are not directly inspectable here. + return False if system == "Windows": return _is_trusted_windows(cert_path) if system == "Darwin": @@ -349,7 +417,9 @@ def install_ca(cert_path: str, cert_name: str = CERT_NAME) -> bool: system = platform.system() log.info("Installing CA certificate on %s…", system) - if system == "Windows": + if _is_termux(): + ok = _install_termux_android(cert_path, cert_name) + elif system == "Windows": ok = _install_windows(cert_path, cert_name) elif system == "Darwin": ok = _install_macos(cert_path, cert_name)