From 6eeac176aec52a9578b55a5f679cdd100da5e028 Mon Sep 17 00:00:00 2001 From: oxmc7769 Date: Sat, 25 Jul 2026 01:34:22 -0700 Subject: [PATCH] Remove native Android build: Android is now a separate priv-app repo The Android side is being rewritten as a platform-signed system app + device owner (android_packages_apps_PawletProfiled) instead of a native NDK Binder daemon -- most of what these payloads need on Android (DevicePolicyManager, VpnManager, WifiManager, WallpaperManager, KeyChain) is Java-SDK-first and awkward or impossible to reach cleanly from a native process. Drops: Android.bp, main_android.cpp, PawletProfileBinderService.*, platform/android/*.cpp, aidl/, sepolicy/, third_party/openssl-android/, pawletprofiled.rc/.xml. Also strips the now-dead __ANDROID__ branches from SignatureVerifier/ProfileStore. This repo is Linux-only from here on. --- Android.bp | 112 ------ README.md | 46 ++- .../profiled/IPawletProfileService.aidl | 45 --- pawletprofiled.rc | 30 -- pawletprofiled.xml | 14 - sepolicy/file_contexts | 11 - sepolicy/pawletprofiled.te | 69 ---- sepolicy/property_contexts | 4 - sepolicy/service_contexts | 6 - src/PawletProfileBinderService.cpp | 322 ------------------ src/PawletProfileBinderService.h | 57 ---- src/ProfileStore.h | 15 +- src/SignatureVerifier.cpp | 19 +- src/SignatureVerifier.h | 12 - src/main_android.cpp | 96 ------ src/platform/android/Cert.cpp | 20 -- src/platform/android/ContentCache.cpp | 52 --- src/platform/android/DnsProxy.cpp | 20 -- src/platform/android/Ethernet.cpp | 19 -- src/platform/android/Firewall.cpp | 20 -- src/platform/android/FirstBoot.cpp | 20 -- src/platform/android/Ldap.cpp | 21 -- src/platform/android/Mdm.cpp | 20 -- src/platform/android/Passcode.cpp | 20 -- src/platform/android/Pkcs12.cpp | 20 -- src/platform/android/Proxy.cpp | 20 -- src/platform/android/Screensaver.cpp | 21 -- src/platform/android/SoftwareUpdate.cpp | 22 -- src/platform/android/TimeServer.cpp | 20 -- src/platform/android/Vpn.cpp | 21 -- src/platform/android/Wallpaper.cpp | 20 -- src/platform/android/Wifi.cpp | 20 -- third_party/openssl-android/Android.bp | 32 -- third_party/openssl-android/README.md | 79 ----- .../openssl-android/include/PLACEHOLDER.txt | 1 - .../lib/arm64-v8a/PLACEHOLDER.txt | 1 - .../lib/armeabi-v7a/PLACEHOLDER.txt | 1 - .../openssl-android/lib/x86/PLACEHOLDER.txt | 1 - .../lib/x86_64/PLACEHOLDER.txt | 1 - 39 files changed, 31 insertions(+), 1319 deletions(-) delete mode 100644 Android.bp delete mode 100644 aidl/os/pawlet/profiled/IPawletProfileService.aidl delete mode 100644 pawletprofiled.rc delete mode 100644 pawletprofiled.xml delete mode 100644 sepolicy/file_contexts delete mode 100644 sepolicy/pawletprofiled.te delete mode 100644 sepolicy/property_contexts delete mode 100644 sepolicy/service_contexts delete mode 100644 src/PawletProfileBinderService.cpp delete mode 100644 src/PawletProfileBinderService.h delete mode 100644 src/main_android.cpp delete mode 100644 src/platform/android/Cert.cpp delete mode 100644 src/platform/android/ContentCache.cpp delete mode 100644 src/platform/android/DnsProxy.cpp delete mode 100644 src/platform/android/Ethernet.cpp delete mode 100644 src/platform/android/Firewall.cpp delete mode 100644 src/platform/android/FirstBoot.cpp delete mode 100644 src/platform/android/Ldap.cpp delete mode 100644 src/platform/android/Mdm.cpp delete mode 100644 src/platform/android/Passcode.cpp delete mode 100644 src/platform/android/Pkcs12.cpp delete mode 100644 src/platform/android/Proxy.cpp delete mode 100644 src/platform/android/Screensaver.cpp delete mode 100644 src/platform/android/SoftwareUpdate.cpp delete mode 100644 src/platform/android/TimeServer.cpp delete mode 100644 src/platform/android/Vpn.cpp delete mode 100644 src/platform/android/Wallpaper.cpp delete mode 100644 src/platform/android/Wifi.cpp delete mode 100644 third_party/openssl-android/Android.bp delete mode 100644 third_party/openssl-android/README.md delete mode 100644 third_party/openssl-android/include/PLACEHOLDER.txt delete mode 100644 third_party/openssl-android/lib/arm64-v8a/PLACEHOLDER.txt delete mode 100644 third_party/openssl-android/lib/armeabi-v7a/PLACEHOLDER.txt delete mode 100644 third_party/openssl-android/lib/x86/PLACEHOLDER.txt delete mode 100644 third_party/openssl-android/lib/x86_64/PLACEHOLDER.txt diff --git a/Android.bp b/Android.bp deleted file mode 100644 index 39de65f..0000000 --- a/Android.bp +++ /dev/null @@ -1,112 +0,0 @@ -// vendor/oxmc/pawletprofiled/Android.bp -// ───────────────────────────────────────────────────────────────────────── -// Drop this entire directory at vendor/oxmc/pawletprofiled/ and add -// "pawletprofiled" to PRODUCT_PACKAGES in your device makefile. -// -// m pawletprofiled — build the daemon -// m os.pawlet.profiled-V1-java — build Java stubs for system apps -// ───────────────────────────────────────────────────────────────────────── - -// ── AIDL interface ──────────────────────────────────────────────────────── - -aidl_interface { - name: "os.pawlet.profiled", - srcs: ["aidl/os/pawlet/profiled/IPawletProfileService.aidl"], - stability: "vintf", - vendor_available: false, - backend: { - ndk: { - enabled: true, - }, - java: { - enabled: true, - sdk_version: "system_current", - }, - cpp: { - enabled: false, - }, - }, - versions: ["1"], -} - -// ── Vendored OpenSSL (Android-only, static, this binary only) ───────────── -// See third_party/openssl-android/README.md — BoringSSL (the system -// libcrypto/libssl) has no CMS/PKCS#7 support, so SignatureVerifier.cpp -// links a private static copy instead of touching the platform's crypto -// libs. third_party/openssl-android/Android.bp is picked up automatically -// by Soong's normal recursive discovery — nothing to reference here beyond -// the module names ("libssl_pawlet_static" / "libcrypto_pawlet_static") -// used in static_libs below. - -// ── Native daemon ───────────────────────────────────────────────────────── -// -// This file is the Android/Soong build only — the Linux/D-Bus build lives -// in CMakeLists.txt and is entirely separate. Accordingly the source list -// below is the Android-specific set: main_android.cpp (Binder entry point) -// and PawletProfileBinderService.cpp instead of main.cpp/PawletProfileService.cpp -// (D-Bus), and no ZTE client (it watches NetworkManager over D-Bus, which -// doesn't exist on Android — separate follow-up work, see main_android.cpp's -// header comment). - -cc_binary { - name: "pawletprofiled", - - srcs: [ - "src/main_android.cpp", - "src/PawletProfileBinderService.cpp", - "src/ProfileParser.cpp", - "src/ProfileStore.cpp", - "src/SignatureVerifier.cpp", - "src/payloads/PayloadHandlers.cpp", // shared dispatch — see its header comment - "src/platform/android/Wifi.cpp", - "src/platform/android/Ethernet.cpp", - "src/platform/android/Vpn.cpp", - "src/platform/android/Cert.cpp", - "src/platform/android/Pkcs12.cpp", - "src/platform/android/Passcode.cpp", - "src/platform/android/Mdm.cpp", - "src/platform/android/SoftwareUpdate.cpp", - "src/platform/android/TimeServer.cpp", - "src/platform/android/Proxy.cpp", - "src/platform/android/DnsProxy.cpp", - "src/platform/android/Firewall.cpp", - "src/platform/android/Ldap.cpp", - "src/platform/android/Wallpaper.cpp", - "src/platform/android/Screensaver.cpp", - "src/platform/android/FirstBoot.cpp", - "src/platform/android/ContentCache.cpp", - ], - - shared_libs: [ - "libbinder_ndk", - "libbase", - "liblog", - "os.pawlet.profiled-V1-ndk", - ], - - static_libs: [ - "libyaml", - "libssl_pawlet_static", - "libcrypto_pawlet_static", - ], - - cflags: [ - "-Wall", - "-Wextra", - "-Werror", - "-std=c++17", - ], - - init_rc: ["pawletprofiled.rc"], - vintf_fragments: ["pawletprofiled.xml"], - - required: ["pawletprofiled_sepolicy"], -} - -// ── SELinux policy shim ─────────────────────────────────────────────────── - -prebuilt_etc { - name: "pawletprofiled_sepolicy", - src: "sepolicy/pawletprofiled.te", - sub_dir: "selinux", -} diff --git a/README.md b/README.md index dc09905..e87681d 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,14 @@ # pawletprofiled -PawletOS unified device management daemon. +PawletOS's Linux device management daemon — a native root-run systemd +service. One binary, two subsystems. -One binary. Two subsystems. Ships on every PawletOS device. +This repo is Linux-only. The Android implementation is a separate, +independently-written app (platform-signed priv-app + device owner, not a +native daemon — most of what these payloads need on Android is Java-SDK +first): [`android_packages_apps_PawletProfiled`](https://git.oxmc.me/PawletOS/android_packages_apps_PawletProfiled). +Same `.vconfig` profile format and payload types on both platforms; no +shared code between the two implementations. --- @@ -30,24 +36,21 @@ enrolls on the first successful connection later. ``` pawletprofiled/ -├── Android.bp AOSP Soong build ├── CMakeLists.txt Linux CMake build -├── pawletprofiled.rc Android init script -├── pawletprofiled.xml Android VINTF fragment ├── zte.conf.example ZTE client config │ -├── aidl/os/pawlet/profiled/ -│ └── IPawletProfileService.aidl Binder interface (Android) -│ ├── src/ │ ├── main.cpp Entry point -│ ├── PawletProfileService.h/.cpp D-Bus service (Linux) +│ ├── PawletProfileService.h/.cpp D-Bus service │ ├── ProfileParser.h/.cpp YAML parser (libyaml) │ ├── ProfileStore.h/.cpp Disk persistence + password hashing │ ├── SignatureVerifier.h/.cpp CMS/PKCS#7 verification (OpenSSL) -│ └── payloads/ -│ ├── PayloadHandler.h Base class + handler registry -│ └── PayloadHandlers.cpp All 55 payload implementations +│ ├── payloads/ +│ │ ├── PayloadHandler.h Handler contract + PayloadUtil.h helpers +│ │ └── PayloadHandlers.cpp Dispatch — forwards to platform/linux/*.cpp +│ └── platform/ +│ ├── .h Per-payload-type contract (apply/revert) +│ └── linux/.cpp One real implementation per payload type │ ├── src/zte/ │ ├── DeviceIdentity.h/.cpp Hardware identity collection @@ -57,7 +60,6 @@ pawletprofiled/ ├── systemd/pawletprofiled.service Systemd unit ├── dbus/os.pawlet.ProfiledService.conf D-Bus policy ├── apparmor/pawletprofiled AppArmor MAC profile -├── sepolicy/ Android SELinux policy └── debian/ Debian Trixie packaging ``` @@ -113,20 +115,12 @@ sudo cmake --install build --- -## Building — Android (AOSP) +## Android -```bash -cp -r pawletprofiled/ $AOSP_ROOT/vendor/oxmc/pawletprofiled/ - -# Add to device makefile -echo 'PRODUCT_PACKAGES += pawletprofiled' \ - >> device/oxmc/pawletos/pawletos.mk -echo 'BOARD_SEPOLICY_DIRS += vendor/oxmc/pawletprofiled/sepolicy' \ - >> device/oxmc/pawletos/BoardConfig.mk - -source build/envsetup.sh && lunch pawletos_arm64-userdebug -m pawletprofiled -``` +Not built from this repo — see +[`android_packages_apps_PawletProfiled`](https://git.oxmc.me/PawletOS/android_packages_apps_PawletProfiled), +a platform-signed priv-app + device owner with its own independent +implementation of every payload type in this daemon's schema. --- diff --git a/aidl/os/pawlet/profiled/IPawletProfileService.aidl b/aidl/os/pawlet/profiled/IPawletProfileService.aidl deleted file mode 100644 index 62686ba..0000000 --- a/aidl/os/pawlet/profiled/IPawletProfileService.aidl +++ /dev/null @@ -1,45 +0,0 @@ -package os.pawlet.profiled; - -// IPawletProfileService — Binder interface exposed by pawletprofiled. -// Clients (system apps, Settings, installer UI) talk to the daemon via this. -// NDK backend; link against libpawletprofiled-ndk. -@VintfStability -interface IPawletProfileService { - - // ── Profile lifecycle ───────────────────────────────────────────────── - - // Install a profile from raw YAML bytes (unsigned) or a CMS/PKCS#7 - // blob (signed). Returns the installed profile's UUID on success. - // Throws ServiceSpecificException on validation or signature failure. - String installProfile(in byte[] profileData); - - // Remove an installed profile by UUID. - // Throws if the profile is MDM-locked or removal-password protected - // and no password is supplied. - void removeProfile(in String uuid, in String removalPassword); - - // List all installed profile UUIDs. - String[] listProfiles(); - - // Return JSON-encoded metadata for a single profile. - String getProfileInfo(in String uuid); - - // ── MDM state ───────────────────────────────────────────────────────── - - // True if a valid MDM payload is enrolled. - boolean isDeviceManaged(); - - // Return the enrolled MDM server URL, or empty string if not managed. - String getMdmServerUrl(); - - // ── Supervised / kiosk state ────────────────────────────────────────── - - // True if a kiosk or ASAM payload is active. - boolean isSupervised(); - - // ── Payload query helpers ───────────────────────────────────────────── - - // Return JSON array of payloads of the given type across all profiles. - // e.g. getPayloadsOfType("wifi") → [{ssid:..., uuid:...}, ...] - String getPayloadsOfType(in String payloadType); -} diff --git a/pawletprofiled.rc b/pawletprofiled.rc deleted file mode 100644 index 3db5122..0000000 --- a/pawletprofiled.rc +++ /dev/null @@ -1,30 +0,0 @@ -# vendor/oxmc/pawletprofiled/pawletprofiled.rc -# ───────────────────────────────────────────────────────────────────────── -# Android init language script — starts pawletprofiled at boot. -# Placed in /system/etc/init/ by the build system via init_rc in Android.bp. -# ───────────────────────────────────────────────────────────────────────── - -service pawletprofiled /system/bin/pawletprofiled - class main - user system - group system - # Capabilities needed to write to /data/system/pawletos/ and to - # call privileged Binder services (DevicePolicyManager, KeyChain, etc.) - capabilities SETUID SETGID - # Restart automatically if the daemon crashes. - restart_period 5 - # SELinux domain (matches the type defined in pawletprofiled.te) - seclabel u:r:pawletprofiled:s0 - # Only start once the filesystem is decrypted and /data is available. - on_property:vold.decrypt=trigger_restart_framework - -# Create the data directory on first boot. -on post-fs-data - mkdir /data/system/pawletos 0700 system system - mkdir /data/system/pawletos/profiles 0700 system system - mkdir /data/system/pawletos/preinstalled 0700 system system - # content-cache payload's policy override — world-readable by design, - # PawletCacheService (a regular app UID) reads it directly. See - # PayloadHandlers.cpp's ContentCacheHandler and PolicyOverride.kt. - # PawletOS-fork-specific (see PayloadHandlers.cpp's header comment). - mkdir /data/misc/pawletcache 0755 system system diff --git a/pawletprofiled.xml b/pawletprofiled.xml deleted file mode 100644 index 7f4c3da..0000000 --- a/pawletprofiled.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - os.pawlet.profiled - 1 - IPawletProfileService/default - - diff --git a/sepolicy/file_contexts b/sepolicy/file_contexts deleted file mode 100644 index 208941a..0000000 --- a/sepolicy/file_contexts +++ /dev/null @@ -1,11 +0,0 @@ -# vendor/oxmc/pawletprofiled/sepolicy/file_contexts -# ───────────────────────────────────────────────────────────────────────── -# Maps filesystem paths to SELinux security contexts. -# Included automatically when BOARD_SEPOLICY_DIRS points here. -# ───────────────────────────────────────────────────────────────────────── - -# Daemon binary -/system/bin/pawletprofiled u:object_r:pawletprofiled_exec:s0 - -# Profile data directory and all contents -/data/system/pawletos(/.*)? u:object_r:pawletprofiled_data_file:s0 diff --git a/sepolicy/pawletprofiled.te b/sepolicy/pawletprofiled.te deleted file mode 100644 index 0a67740..0000000 --- a/sepolicy/pawletprofiled.te +++ /dev/null @@ -1,69 +0,0 @@ -# vendor/oxmc/pawletprofiled/sepolicy/pawletprofiled.te -# SELinux policy for the pawletprofiled system daemon (Android/AOSP). -# -# To activate, add to your device's BoardConfig.mk: -# BOARD_SEPOLICY_DIRS += vendor/oxmc/pawletprofiled/sepolicy - -# ── Type declarations ────────────────────────────────────────────────────── - -type pawletprofiled, domain; -type pawletprofiled_exec, exec_type, file_type, system_file_type; -type pawletprofiled_data_file, file_type, data_file_type; -type pawletprofiled_service, service_manager_type; - -# ── Domain transition ────────────────────────────────────────────────────── - -init_daemon_domain(pawletprofiled) - -# ── Binder IPC ──────────────────────────────────────────────────────────── - -binder_use(pawletprofiled) -add_service(pawletprofiled, pawletprofiled_service) - -# Allow system apps and shell to call into pawletprofiled via Binder -binder_call(system_app, pawletprofiled) -binder_call(shell, pawletprofiled) - -# ── Profile data directory ──────────────────────────────────────────────── - -allow pawletprofiled pawletprofiled_data_file:dir { create search getattr setattr add_name remove_name }; -allow pawletprofiled pawletprofiled_data_file:file { create open read write getattr setattr unlink rename }; - -# ── System file access (CA certs for signature chain validation) ────────── - -allow pawletprofiled system_file:dir { search getattr }; -allow pawletprofiled system_file:file { open read getattr }; - -# ── Network (ZTE HTTPS lookups) ─────────────────────────────────────────── - -allow pawletprofiled self:tcp_socket { create connect read write shutdown }; -allow pawletprofiled self:udp_socket { create connect read write }; -allow pawletprofiled port:tcp_socket name_connect; - -# ── Logging ─────────────────────────────────────────────────────────────── - -allow pawletprofiled log_device:chr_file { open read write }; - -# ── System properties (ZTE state and MDM enrollment state) ─────────────── - -set_prop(pawletprofiled, pawletos_prop) -get_prop(pawletprofiled, pawletos_prop) - -# ── DevicePolicyManager / KeyStore Binder calls ─────────────────────────── - -allow pawletprofiled device_policy_service:service_manager { find }; -allow pawletprofiled keystore_service:service_manager { find }; -binder_call(pawletprofiled, system_server) -binder_call(pawletprofiled, keystore) - -# ── Process self-permissions ────────────────────────────────────────────── - -allow pawletprofiled self:process { fork sigchld }; -allow pawletprofiled self:unix_stream_socket { create connect read write }; - -# ── content-cache payload's policy override file (PawletOS-fork-specific) ── -# Type declared in android_packages_apps_PawletCache/sepolicy/pawlet_cache.te -# (both dirs land in BOARD_SEPOLICY_DIRS) — see ContentCacheHandler and -# PolicyOverride.kt for the read/write contract on this file. -allow pawletprofiled pawletcache_policy_file:dir { create search getattr add_name }; -allow pawletprofiled pawletcache_policy_file:file create_file_perms; diff --git a/sepolicy/property_contexts b/sepolicy/property_contexts deleted file mode 100644 index e851ef2..0000000 --- a/sepolicy/property_contexts +++ /dev/null @@ -1,4 +0,0 @@ -# vendor/oxmc/pawletprofiled/sepolicy/property_contexts -# Declares the persist.pawletos.* property namespace. - -persist.pawletos. u:object_r:pawletos_prop:s0 diff --git a/sepolicy/service_contexts b/sepolicy/service_contexts deleted file mode 100644 index 3a14cd3..0000000 --- a/sepolicy/service_contexts +++ /dev/null @@ -1,6 +0,0 @@ -# vendor/oxmc/pawletprofiled/sepolicy/service_contexts -# Maps the Binder service name to its SELinux type. -# This is what allows AServiceManager_addService / getService to work -# under SELinux enforcement. - -os.pawlet.profiled.IPawletProfileService/default u:object_r:pawletprofiled_service:s0 diff --git a/src/PawletProfileBinderService.cpp b/src/PawletProfileBinderService.cpp deleted file mode 100644 index e6d0a52..0000000 --- a/src/PawletProfileBinderService.cpp +++ /dev/null @@ -1,322 +0,0 @@ -#include "PawletProfileBinderService.h" -#include "payloads/PayloadHandler.h" - -#include -#include -#include - -namespace pawletos::profile { - -using ::ndk::ScopedAStatus; - -// Service-specific error codes returned via ScopedAStatus — mirrors -// PawletProfileService's D-Bus error domain (kErrNotFound etc.) one-for-one -// so a future shared client-side error mapping stays simple. -namespace { -constexpr int kErrNotFound = 1; -constexpr int kErrSignature = 2; -constexpr int kErrParse = 3; -constexpr int kErrLocked = 4; -constexpr int kErrWrongPassword = 5; -constexpr int kErrSigningRequired = 6; -} // namespace - -ScopedAStatus PawletProfileBinderService::serviceError(const char* name, const std::string& message) { - syslog(LOG_WARNING, "pawletprofiled: %s: %s", name, message.c_str()); - int code = 0; - if (strcmp(name, "NotFound") == 0) code = kErrNotFound; - else if (strcmp(name, "Signature") == 0) code = kErrSignature; - else if (strcmp(name, "Parse") == 0) code = kErrParse; - else if (strcmp(name, "Locked") == 0) code = kErrLocked; - else if (strcmp(name, "WrongPassword") == 0) code = kErrWrongPassword; - else if (strcmp(name, "SigningRequired") == 0) code = kErrSigningRequired; - return ScopedAStatus::fromServiceSpecificErrorWithMessage(code, message.c_str()); -} - -PawletProfileBinderService::PawletProfileBinderService() { - syslog(LOG_INFO, "pawletprofiled: Binder service starting"); - mStore.load(); -} - -// ── installProfileDirect (preinstalled profiles, same as D-Bus version) ──── - -bool PawletProfileBinderService::installProfileDirect( - const std::vector& profileData, std::string& outUuid) { - std::lock_guard lock(mLock); - - std::vector yamlBytes; - bool isSigned = false; - SignatureVerifier::TrustLevel trust = SignatureVerifier::TrustLevel::UNSIGNED; - - if (mVerifier.isCmsWrapped(profileData)) { - auto result = mVerifier.verify(profileData, yamlBytes); - if (result == SignatureVerifier::VerifyResult::INVALID) { - syslog(LOG_ERR, "[installProfileDirect] signature invalid"); - return false; - } - isSigned = true; - trust = (result == SignatureVerifier::VerifyResult::TRUSTED) - ? SignatureVerifier::TrustLevel::TRUSTED - : SignatureVerifier::TrustLevel::UNVERIFIED; - } else { - yamlBytes = profileData; - } - - ParsedProfile profile; - if (!mParser.parse(yamlBytes, profile)) { - syslog(LOG_ERR, "[installProfileDirect] parse failed"); - return false; - } - - ParsedProfile existing; - if (mStore.load(profile.uuid, existing)) { - syslog(LOG_INFO, "[installProfileDirect] already installed uuid=%s, skipping", - profile.uuid.c_str()); - outUuid = profile.uuid; - return true; - } - - for (const auto& payload : profile.payloads) { - bool sigRequired = - payload.type == "mdm" || - payload.type == "removal-password" || - payload.type == "kiosk" || - payload.type == "asam"; - if (sigRequired && !isSigned) { - syslog(LOG_ERR, "[installProfileDirect] type=%s requires signed profile", - payload.type.c_str()); - return false; - } - } - - profile.trustLevel = trust; - if (!mStore.save(profile)) { - syslog(LOG_ERR, "[installProfileDirect] save failed uuid=%s", profile.uuid.c_str()); - return false; - } - - applyProfile(profile); - outUuid = profile.uuid; - syslog(LOG_INFO, "[installProfileDirect] installed uuid=%s", profile.uuid.c_str()); - return true; -} - -// ── installProfile ────────────────────────────────────────────────────── - -ScopedAStatus PawletProfileBinderService::installProfile( - const std::vector& in_profileData, std::string* _aidl_return) { - std::lock_guard lock(mLock); - - std::vector yamlBytes; - bool isSigned = false; - SignatureVerifier::TrustLevel trust = SignatureVerifier::TrustLevel::UNSIGNED; - - if (mVerifier.isCmsWrapped(in_profileData)) { - auto result = mVerifier.verify(in_profileData, yamlBytes); - if (result == SignatureVerifier::VerifyResult::INVALID) { - return serviceError("Signature", "Profile signature is invalid or tampered."); - } - isSigned = true; - trust = (result == SignatureVerifier::VerifyResult::TRUSTED) - ? SignatureVerifier::TrustLevel::TRUSTED - : SignatureVerifier::TrustLevel::UNVERIFIED; - } else { - yamlBytes = in_profileData; - } - - ParsedProfile profile; - if (!mParser.parse(yamlBytes, profile)) { - return serviceError("Parse", "Profile YAML is malformed or schema-invalid."); - } - - for (const auto& payload : profile.payloads) { - bool sigRequired = - payload.type == "mdm" || - payload.type == "removal-password" || - payload.type == "kiosk" || - payload.type == "asam"; - if (sigRequired && !isSigned) { - return serviceError("SigningRequired", - "Payload type '" + payload.type + "' requires a signed profile."); - } - } - - profile.trustLevel = trust; - if (!mStore.save(profile)) { - return serviceError("Parse", "Failed to persist profile."); - } - - applyProfile(profile); - syslog(LOG_INFO, "pawletprofiled: installed profile uuid=%s", profile.uuid.c_str()); - - *_aidl_return = profile.uuid; - return ScopedAStatus::ok(); -} - -// ── removeProfile ──────────────────────────────────────────────────────── - -ScopedAStatus PawletProfileBinderService::removeProfile( - const std::string& in_uuid, const std::string& in_removalPassword) { - std::lock_guard lock(mLock); - - ParsedProfile profile; - if (!mStore.load(in_uuid, profile)) { - return serviceError("NotFound", "Profile not found: " + in_uuid); - } - - if (profile.lifecycle.removal == "locked") { - return serviceError("Locked", "This profile can only be removed by the MDM server."); - } - if (profile.lifecycle.removal == "password") { - if (in_removalPassword.empty() || !mStore.checkRemovalPassword(in_uuid, in_removalPassword)) { - return serviceError("WrongPassword", "Incorrect removal password."); - } - } - - revertProfile(profile); - mStore.remove(in_uuid); - syslog(LOG_INFO, "pawletprofiled: removed profile uuid=%s", in_uuid.c_str()); - return ScopedAStatus::ok(); -} - -// ── listProfiles ───────────────────────────────────────────────────────── - -ScopedAStatus PawletProfileBinderService::listProfiles(std::vector* _aidl_return) { - std::lock_guard lock(mLock); - *_aidl_return = mStore.listUuids(); - return ScopedAStatus::ok(); -} - -// ── getProfileInfo ─────────────────────────────────────────────────────── - -ScopedAStatus PawletProfileBinderService::getProfileInfo( - const std::string& in_uuid, std::string* _aidl_return) { - std::lock_guard lock(mLock); - - ParsedProfile profile; - if (!mStore.load(in_uuid, profile)) { - return serviceError("NotFound", "Not found: " + in_uuid); - } - - std::ostringstream j; - j << "{" - << "\"uuid\":\"" << profile.uuid << "\"," - << "\"id\":\"" << profile.id << "\"," - << "\"name\":\"" << profile.meta.name << "\"," - << "\"organization\":\"" << profile.meta.organization << "\"," - << "\"scope\":\"" << profile.scope << "\"," - << "\"removal\":\"" << profile.lifecycle.removal << "\"," - << "\"trusted\":" << (profile.trustLevel != SignatureVerifier::TrustLevel::UNSIGNED ? "true" : "false") << "," - << "\"payloadCount\":" << profile.payloads.size() - << "}"; - - *_aidl_return = j.str(); - return ScopedAStatus::ok(); -} - -// ── isDeviceManaged ────────────────────────────────────────────────────── - -ScopedAStatus PawletProfileBinderService::isDeviceManaged(bool* _aidl_return) { - std::lock_guard lock(mLock); - bool managed = false; - for (const auto& uuid : mStore.listUuids()) { - ParsedProfile p; - if (mStore.load(uuid, p)) - for (const auto& pl : p.payloads) - if (pl.type == "mdm") { managed = true; break; } - if (managed) break; - } - *_aidl_return = managed; - return ScopedAStatus::ok(); -} - -// ── getMdmServerUrl ────────────────────────────────────────────────────── - -ScopedAStatus PawletProfileBinderService::getMdmServerUrl(std::string* _aidl_return) { - std::lock_guard lock(mLock); - std::string url; - for (const auto& uuid : mStore.listUuids()) { - ParsedProfile p; - if (!mStore.load(uuid, p)) continue; - for (const auto& pl : p.payloads) { - if (pl.type == "mdm") { - auto it = pl.fields.find("server-url"); - if (it != pl.fields.end()) url = it->second; - if (url.size() >= 2 && url.front() == '"') url = url.substr(1, url.size() - 2); - break; - } - } - if (!url.empty()) break; - } - *_aidl_return = url; - return ScopedAStatus::ok(); -} - -// ── isSupervised ───────────────────────────────────────────────────────── - -ScopedAStatus PawletProfileBinderService::isSupervised(bool* _aidl_return) { - std::lock_guard lock(mLock); - bool supervised = false; - for (const auto& uuid : mStore.listUuids()) { - ParsedProfile p; - if (!mStore.load(uuid, p)) continue; - for (const auto& pl : p.payloads) - if (pl.type == "kiosk" || pl.type == "asam") { supervised = true; break; } - if (supervised) break; - } - *_aidl_return = supervised; - return ScopedAStatus::ok(); -} - -// ── getPayloadsOfType ──────────────────────────────────────────────────── - -ScopedAStatus PawletProfileBinderService::getPayloadsOfType( - const std::string& in_payloadType, std::string* _aidl_return) { - std::lock_guard lock(mLock); - - std::ostringstream j; - j << "["; - bool first = true; - for (const auto& uuid : mStore.listUuids()) { - ParsedProfile p; - if (!mStore.load(uuid, p)) continue; - for (const auto& pl : p.payloads) { - if (pl.type != in_payloadType) continue; - if (!first) j << ","; - first = false; - j << "{\"profileUuid\":\"" << p.uuid << "\"," - << "\"payloadUuid\":\"" << pl.uuid << "\""; - for (const auto& [k, v] : pl.fields) - j << ",\"" << k << "\":" << v; - j << "}"; - } - } - j << "]"; - - *_aidl_return = j.str(); - return ScopedAStatus::ok(); -} - -// ── applyProfile / revertProfile ───────────────────────────────────────── - -void PawletProfileBinderService::applyProfile(const ParsedProfile& profile) { - for (const auto& payload : profile.payloads) { - auto* handler = PayloadHandlerRegistry::get(payload.type); - if (handler) { - if (!handler->apply(payload)) - syslog(LOG_WARNING, "pawletprofiled: handler failed type=%s uuid=%s", - payload.type.c_str(), payload.uuid.c_str()); - } else { - syslog(LOG_WARNING, "pawletprofiled: no handler for type=%s", payload.type.c_str()); - } - } -} - -void PawletProfileBinderService::revertProfile(const ParsedProfile& profile) { - for (auto it = profile.payloads.rbegin(); it != profile.payloads.rend(); ++it) { - auto* handler = PayloadHandlerRegistry::get(it->type); - if (handler) handler->revert(*it); - } -} - -} // namespace pawletos::profile diff --git a/src/PawletProfileBinderService.h b/src/PawletProfileBinderService.h deleted file mode 100644 index e9cb946..0000000 --- a/src/PawletProfileBinderService.h +++ /dev/null @@ -1,57 +0,0 @@ -#pragma once - -#include "ProfileParser.h" -#include "ProfileStore.h" -#include "SignatureVerifier.h" - -#include - -#include -#include -#include - -namespace pawletos::profile { - -// ── Android Binder counterpart to PawletProfileService (D-Bus) ───────────── -// Same install/remove/query logic, same ProfileStore/ProfileParser/ -// PayloadHandlerRegistry underneath — only the transport differs. See -// main_android.cpp for how this gets registered with servicemanager. -// -// Registered service name: "os.pawlet.profiled.IPawletProfileService/default" -// (must match pawletprofiled.xml's VINTF fragment and sepolicy/service_contexts). -class PawletProfileBinderService - : public aidl::me::oxmc::pawletos::profile::BnPawletProfileService { -public: - PawletProfileBinderService(); - - // Same direct-install path PawletProfileService exposes for main.cpp's - // preinstalled-profile loader — see applyPreinstalledProfiles() in - // main_android.cpp. - bool installProfileDirect(const std::vector& data, std::string& outUuid); - - ::ndk::ScopedAStatus installProfile( - const std::vector& in_profileData, std::string* _aidl_return) override; - ::ndk::ScopedAStatus removeProfile( - const std::string& in_uuid, const std::string& in_removalPassword) override; - ::ndk::ScopedAStatus listProfiles(std::vector* _aidl_return) override; - ::ndk::ScopedAStatus getProfileInfo( - const std::string& in_uuid, std::string* _aidl_return) override; - ::ndk::ScopedAStatus isDeviceManaged(bool* _aidl_return) override; - ::ndk::ScopedAStatus getMdmServerUrl(std::string* _aidl_return) override; - ::ndk::ScopedAStatus isSupervised(bool* _aidl_return) override; - ::ndk::ScopedAStatus getPayloadsOfType( - const std::string& in_payloadType, std::string* _aidl_return) override; - -private: - void applyProfile(const ParsedProfile& profile); - void revertProfile(const ParsedProfile& profile); - - static ::ndk::ScopedAStatus serviceError(const char* name, const std::string& message); - - std::mutex mLock; - ProfileStore mStore; - ProfileParser mParser; - SignatureVerifier mVerifier; -}; - -} // namespace pawletos::profile diff --git a/src/ProfileStore.h b/src/ProfileStore.h index ba664eb..83168c6 100644 --- a/src/ProfileStore.h +++ b/src/ProfileStore.h @@ -18,21 +18,14 @@ namespace pawletos::profile { // meta.json install time, trust level, payload count // removal_hash.bin PBKDF2-SHA256 hash of removal password (if set) // -// Android's path matches what pawletprofiled.rc already mkdir's at -// post-fs-data and what sepolicy/file_contexts already labels -// pawletprofiled_data_file — see android_packages_apps_PawletCache's -// equivalent PolicyOverride.kt contract for the analogous device-side path. -#if defined(__ANDROID__) -static constexpr const char* kProfilesDir = - "/data/system/pawletos/profiles"; -static constexpr const char* kIndexFile = - "/data/system/pawletos/profiles/index.json"; -#else +// The Android implementation (git.oxmc.me/PawletOS/android_packages_apps_PawletProfiled's +// ProfileStore.kt) uses the same /data/system/pawletos/profiles path and +// on-disk layout, for whatever a shared UUID/profile means across both +// platforms — but it's an independent implementation, not shared code. static constexpr const char* kProfilesDir = "/var/lib/pawletprofiled/profiles"; static constexpr const char* kIndexFile = "/var/lib/pawletprofiled/profiles/index.json"; -#endif class ProfileStore { public: diff --git a/src/SignatureVerifier.cpp b/src/SignatureVerifier.cpp index abe4a8e..9bf57b1 100644 --- a/src/SignatureVerifier.cpp +++ b/src/SignatureVerifier.cpp @@ -1,12 +1,12 @@ #include "SignatureVerifier.h" -// AOSP's system libcrypto/libssl is BoringSSL, which has no CMS/PKCS#7 -// support — so this file links against a vendored, statically-linked real -// OpenSSL on Android instead of the system one (see -// third_party/openssl-android/ and Android.bp's Android-target static_libs). -// The Linux build (CMakeLists.txt) links Debian's system OpenSSL the normal -// way. Either way, the code below is the same real CMS_verify() — no -// platform split needed here, only at the link-config level. +// Links Debian's system OpenSSL (libcrypto/libssl) for real CMS_verify(). +// The Android implementation lives in a separate app now +// (git.oxmc.me/PawletOS/android_packages_apps_PawletProfiled's +// SignatureVerifier.kt, via Bouncy Castle — BoringSSL has no CMS/PKCS#7 +// support, the same gap that used to be solved here by vendoring a static +// OpenSSL for the Android build; a pure-Java CMS library sidesteps that +// entirely instead). #include #include #include @@ -43,13 +43,8 @@ static StorePtr buildTrustStore() { X509_STORE* store = X509_STORE_new(); if (!store) return nullptr; -#if defined(__ANDROID__) - // AOSP's cacerts dir is CApath-style (hash-named PEM files), not one bundle. - X509_STORE_load_locations(store, nullptr, SignatureVerifier::kTrustStorePath); -#else // Debian's ca-certificates.crt is a single CAfile bundle. X509_STORE_load_locations(store, SignatureVerifier::kTrustStorePath, nullptr); -#endif // Load PawletOS profile signing CA if installed struct stat st{}; diff --git a/src/SignatureVerifier.h b/src/SignatureVerifier.h index ccdbb40..1a84f4c 100644 --- a/src/SignatureVerifier.h +++ b/src/SignatureVerifier.h @@ -25,24 +25,12 @@ public: VerifyResult verify(const std::vector& cmsData, std::vector& outPayload); -#if defined(__ANDROID__) - // AOSP's system CA store is a *directory* of hash-named PEM files - // (c_rehash layout), not one bundle file — buildTrustStore() loads it - // via X509_STORE's CApath, not CAfile. See SignatureVerifier.cpp. - static constexpr const char* kTrustStorePath = - "/system/etc/security/cacerts"; - // PawletOS profile signing CA (optional) — writable partition, covered - // by sepolicy's pawletprofiled_data_file type. - static constexpr const char* kPawletCaPath = - "/data/system/pawletos/profile_ca.pem"; -#else // System CA trust bundle static constexpr const char* kTrustStorePath = "/etc/ssl/certs/ca-certificates.crt"; // PawletOS profile signing CA (optional; installed by the pawletos-ca package) static constexpr const char* kPawletCaPath = "/etc/pawletprofiled/profile_ca.pem"; -#endif }; } // namespace pawletos::profile diff --git a/src/main_android.cpp b/src/main_android.cpp deleted file mode 100644 index abd8383..0000000 --- a/src/main_android.cpp +++ /dev/null @@ -1,96 +0,0 @@ -#include "PawletProfileBinderService.h" -#include "payloads/PayloadHandler.h" - -#include -#include - -#include -#include -#include -#include -#include - -// ───────────────────────────────────────────────────────────────────────── -// pawletprofiled — Android entry point -// -// Counterpart to main.cpp (Linux/D-Bus). Registers PawletProfileBinderService -// as "os.pawlet.profiled.IPawletProfileService/default" — the exact -// name pawletprofiled.xml's VINTF fragment and sepolicy/service_contexts -// already declare — and applies preinstalled profiles the same way -// main.cpp does, from an Android-appropriate path. -// -// Not ported here: the ZTE ConnectivityWatcher (main.cpp's background -// thread) — it watches NetworkManager over D-Bus, which doesn't exist on -// Android. Zero-touch enrollment on PawletOS is separate follow-up work, -// not silently dropped-but-unmentioned. -// ───────────────────────────────────────────────────────────────────────── - -static constexpr const char* kPreinstalledDir = - "/data/system/pawletos/preinstalled"; - -static bool fileExists(const std::string& path) { - struct stat st{}; - return ::stat(path.c_str(), &st) == 0; -} - -static void applyPreinstalledProfiles(pawletos::profile::PawletProfileBinderService& svc) { - DIR* d = opendir(kPreinstalledDir); - if (!d) return; - - syslog(LOG_INFO, "pawletprofiled: scanning %s for preinstalled profiles", kPreinstalledDir); - - struct dirent* ent; - while ((ent = readdir(d)) != nullptr) { - std::string name = ent->d_name; - if (name == "." || name == "..") continue; - if (name.find(".vconfig") == std::string::npos) continue; - - std::string path = std::string(kPreinstalledDir) + "/" + name; - std::ifstream f(path, std::ios::binary); - if (!f) { - syslog(LOG_WARNING, "pawletprofiled: cannot read %s", path.c_str()); - continue; - } - std::ostringstream buf; - buf << f.rdbuf(); - std::string content = buf.str(); - std::vector data(content.begin(), content.end()); - - std::string uuid; - bool ok = svc.installProfileDirect(data, uuid); - if (ok) - syslog(LOG_INFO, "pawletprofiled: preinstalled %s -> uuid=%s", name.c_str(), uuid.c_str()); - else - syslog(LOG_WARNING, "pawletprofiled: failed to apply %s", name.c_str()); - } - closedir(d); -} - -int main() { - openlog("pawletprofiled", LOG_PID | LOG_CONS, LOG_DAEMON); - syslog(LOG_INFO, "pawletprofiled starting (Android/Binder)"); - - pawletos::profile::PayloadHandlerRegistry::registerAll(); - - auto service = ndk::SharedRefBase::make(); - - if (fileExists(kPreinstalledDir)) { - applyPreinstalledProfiles(*service); - } - - const char* instanceName = "os.pawlet.profiled.IPawletProfileService/default"; - binder_status_t status = AServiceManager_addService(service->asBinder().get(), instanceName); - if (status != STATUS_OK) { - syslog(LOG_ERR, "pawletprofiled: AServiceManager_addService failed: %d", status); - return 1; - } - syslog(LOG_INFO, "pawletprofiled: registered as %s", instanceName); - - ABinderProcess_setThreadPoolMaxThreadCount(4); - ABinderProcess_startThreadPool(); - ABinderProcess_joinThreadPool(); // blocks forever - - syslog(LOG_INFO, "pawletprofiled stopped"); - closelog(); - return 0; -} diff --git a/src/platform/android/Cert.cpp b/src/platform/android/Cert.cpp deleted file mode 100644 index eb07ece..0000000 --- a/src/platform/android/Cert.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "../Cert.h" - -#include - -// Not yet implemented on Android. A real port needs DevicePolicyManager's -// installCaCert() (device-owner) or the KeyChain install-cert intent flow — -// AOSP has no /etc/ssl/certs-equivalent a daemon can just write files into. - -namespace pawletos::profile::platform::cert { - -bool apply(const ParsedPayload& p) { - syslog(LOG_WARNING, "[cert] not implemented on Android yet, uuid=%s", p.uuid.c_str()); - return false; -} - -void revert(const ParsedPayload& p) { - syslog(LOG_WARNING, "[cert] not implemented on Android yet, uuid=%s", p.uuid.c_str()); -} - -} // namespace pawletos::profile::platform::cert diff --git a/src/platform/android/ContentCache.cpp b/src/platform/android/ContentCache.cpp deleted file mode 100644 index 397c96f..0000000 --- a/src/platform/android/ContentCache.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "../ContentCache.h" -#include "../../payloads/PayloadUtil.h" - -#include -#include - -// ═══════════════════════════════════════════════════════════════════════════ -// CONTENT CACHE HANDLER (Android) -// PawletOS-fork-specific — pawletprofiled's default PawletOS build doesn't -// register this handler at all (see PayloadHandlers.cpp). Writes the -// local-network-cache discovery override PawletCacheService reads — see -// pawletcache-server/README.md and -// android_packages_apps_PawletCache/src/os/pawlet/cache/PolicyOverride.kt. -// ═══════════════════════════════════════════════════════════════════════════ - -namespace pawletos::profile::platform::content_cache { - -using namespace pawletos::profile::util; - -namespace { -constexpr const char* kPolicyDir = "/data/misc/pawletcache"; -constexpr const char* kPolicyFile = "/data/misc/pawletcache/policy.json"; -} - -bool apply(const ParsedPayload& p) { - std::string mode = field(p, "mode", "both"); - - std::ostringstream json; - json << "{\n \"mode\": \"" << mode << "\""; - - auto pinned = p.fields.find("pinned-server"); - if (pinned != p.fields.end()) { - // Already valid JSON text (ProfileParser re-serializes nested - // objects) — relay it verbatim under the camelCase key - // PolicyOverride.kt expects, no reparsing needed here. - json << ",\n \"pinnedServer\": " << pinned->second; - } - json << "\n}\n"; - - ensureDir(kPolicyDir); - // World-readable by design — PawletCacheService reads this as a - // regular app UID, and it's policy, not a secret (see PolicyOverride.kt). - writeFile(kPolicyFile, json.str(), 0644); - syslog(LOG_INFO, "[content-cache] applied mode=%s", mode.c_str()); - return true; -} - -void revert(const ParsedPayload& /*p*/) { - removeFile(kPolicyFile); -} - -} // namespace pawletos::profile::platform::content_cache diff --git a/src/platform/android/DnsProxy.cpp b/src/platform/android/DnsProxy.cpp deleted file mode 100644 index a3ec714..0000000 --- a/src/platform/android/DnsProxy.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "../DnsProxy.h" - -#include - -// Not yet implemented on Android. A real port would write -// Settings.Global.PRIVATE_DNS_MODE / PRIVATE_DNS_SPECIFIER (needs -// WRITE_SECURE_SETTINGS) — no systemd-resolved.conf.d equivalent. - -namespace pawletos::profile::platform::dns_proxy { - -bool apply(const ParsedPayload& p) { - syslog(LOG_WARNING, "[dns-proxy] not implemented on Android yet, uuid=%s", p.uuid.c_str()); - return false; -} - -void revert(const ParsedPayload& p) { - syslog(LOG_WARNING, "[dns-proxy] not implemented on Android yet, uuid=%s", p.uuid.c_str()); -} - -} // namespace pawletos::profile::platform::dns_proxy diff --git a/src/platform/android/Ethernet.cpp b/src/platform/android/Ethernet.cpp deleted file mode 100644 index 79ab91d..0000000 --- a/src/platform/android/Ethernet.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "../Ethernet.h" - -#include - -// Not yet implemented on Android. A real port would use the hidden/system -// android.net.EthernetManager API — no NetworkManager equivalent exists. - -namespace pawletos::profile::platform::ethernet { - -bool apply(const ParsedPayload& p) { - syslog(LOG_WARNING, "[ethernet] not implemented on Android yet, uuid=%s", p.uuid.c_str()); - return false; -} - -void revert(const ParsedPayload& p) { - syslog(LOG_WARNING, "[ethernet] not implemented on Android yet, uuid=%s", p.uuid.c_str()); -} - -} // namespace pawletos::profile::platform::ethernet diff --git a/src/platform/android/Firewall.cpp b/src/platform/android/Firewall.cpp deleted file mode 100644 index f452fff..0000000 --- a/src/platform/android/Firewall.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "../Firewall.h" - -#include - -// Not yet implemented on Android. There's no nftables/nft CLI on stock -// AOSP — a real port would need NetworkPolicyManager rules or a local -// VpnService-based firewall, a fundamentally different mechanism. - -namespace pawletos::profile::platform::firewall { - -bool apply(const ParsedPayload& p) { - syslog(LOG_WARNING, "[firewall] not implemented on Android yet, uuid=%s", p.uuid.c_str()); - return false; -} - -void revert(const ParsedPayload& p) { - syslog(LOG_WARNING, "[firewall] not implemented on Android yet, uuid=%s", p.uuid.c_str()); -} - -} // namespace pawletos::profile::platform::firewall diff --git a/src/platform/android/FirstBoot.cpp b/src/platform/android/FirstBoot.cpp deleted file mode 100644 index 2a16fd7..0000000 --- a/src/platform/android/FirstBoot.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "../FirstBoot.h" - -#include - -// Not yet implemented on Android. A real port would suppress AOSP's -// SetupWizard (Settings.Global DEVICE_PROVISIONED / USER_SETUP_COMPLETE) — -// no cloud-init/GNOME Initial Setup equivalent here. - -namespace pawletos::profile::platform::first_boot { - -bool apply(const ParsedPayload& p) { - syslog(LOG_WARNING, "[first-boot] not implemented on Android yet, uuid=%s", p.uuid.c_str()); - return false; -} - -void revert(const ParsedPayload& p) { - syslog(LOG_WARNING, "[first-boot] not implemented on Android yet, uuid=%s", p.uuid.c_str()); -} - -} // namespace pawletos::profile::platform::first_boot diff --git a/src/platform/android/Ldap.cpp b/src/platform/android/Ldap.cpp deleted file mode 100644 index e85f0d5..0000000 --- a/src/platform/android/Ldap.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "../Ldap.h" - -#include - -// Not yet implemented on Android — and likely never will be as a direct -// port. Android has no system LDAP client at all (no nslcd/libnss-ldapd -// equivalent); this payload type doesn't map onto anything the platform -// exposes. Logged for visibility rather than silently accepted. - -namespace pawletos::profile::platform::ldap { - -bool apply(const ParsedPayload& p) { - syslog(LOG_WARNING, "[ldap] not supported on Android (no system LDAP client), uuid=%s", p.uuid.c_str()); - return false; -} - -void revert(const ParsedPayload& p) { - syslog(LOG_WARNING, "[ldap] not supported on Android (no system LDAP client), uuid=%s", p.uuid.c_str()); -} - -} // namespace pawletos::profile::platform::ldap diff --git a/src/platform/android/Mdm.cpp b/src/platform/android/Mdm.cpp deleted file mode 100644 index 5e30126..0000000 --- a/src/platform/android/Mdm.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "../Mdm.h" - -#include - -// Not yet implemented on Android. A real port needs Android's own -// device-owner/EMM provisioning flow (DevicePolicyManager), a fundamentally -// different enrollment model than cloud-init drop-ins. - -namespace pawletos::profile::platform::mdm { - -bool apply(const ParsedPayload& p) { - syslog(LOG_WARNING, "[mdm] not implemented on Android yet, uuid=%s", p.uuid.c_str()); - return false; -} - -void revert(const ParsedPayload& p) { - syslog(LOG_WARNING, "[mdm] not implemented on Android yet, uuid=%s", p.uuid.c_str()); -} - -} // namespace pawletos::profile::platform::mdm diff --git a/src/platform/android/Passcode.cpp b/src/platform/android/Passcode.cpp deleted file mode 100644 index ec184f6..0000000 --- a/src/platform/android/Passcode.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "../Passcode.h" - -#include - -// Not yet implemented on Android. A real port needs -// DevicePolicyManager.setPasswordQuality()/setPasswordMinimumLength() etc -// (device-owner) — no pam_pwquality-equivalent config file to write. - -namespace pawletos::profile::platform::passcode { - -bool apply(const ParsedPayload& p) { - syslog(LOG_WARNING, "[passcode] not implemented on Android yet, uuid=%s", p.uuid.c_str()); - return false; -} - -void revert(const ParsedPayload& p) { - syslog(LOG_WARNING, "[passcode] not implemented on Android yet, uuid=%s", p.uuid.c_str()); -} - -} // namespace pawletos::profile::platform::passcode diff --git a/src/platform/android/Pkcs12.cpp b/src/platform/android/Pkcs12.cpp deleted file mode 100644 index a28492c..0000000 --- a/src/platform/android/Pkcs12.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "../Pkcs12.h" - -#include - -// Not yet implemented on Android. A real port needs -// DevicePolicyManager.installKeyPair() (device-owner) — no system NSSDB -// equivalent a daemon can write a .p12 into directly. - -namespace pawletos::profile::platform::pkcs12 { - -bool apply(const ParsedPayload& p) { - syslog(LOG_WARNING, "[pkcs12] not implemented on Android yet, uuid=%s", p.uuid.c_str()); - return false; -} - -void revert(const ParsedPayload& p) { - syslog(LOG_WARNING, "[pkcs12] not implemented on Android yet, uuid=%s", p.uuid.c_str()); -} - -} // namespace pawletos::profile::platform::pkcs12 diff --git a/src/platform/android/Proxy.cpp b/src/platform/android/Proxy.cpp deleted file mode 100644 index 29433b4..0000000 --- a/src/platform/android/Proxy.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "../Proxy.h" - -#include - -// Not yet implemented on Android. A real port would use -// DevicePolicyManager.setRecommendedGlobalProxy()/ProxyInfo (device-owner) — -// no /etc/environment-equivalent to write. - -namespace pawletos::profile::platform::proxy { - -bool apply(const ParsedPayload& p) { - syslog(LOG_WARNING, "[proxy] not implemented on Android yet, uuid=%s", p.uuid.c_str()); - return false; -} - -void revert(const ParsedPayload& p) { - syslog(LOG_WARNING, "[proxy] not implemented on Android yet, uuid=%s", p.uuid.c_str()); -} - -} // namespace pawletos::profile::platform::proxy diff --git a/src/platform/android/Screensaver.cpp b/src/platform/android/Screensaver.cpp deleted file mode 100644 index 88a03f3..0000000 --- a/src/platform/android/Screensaver.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "../Screensaver.h" - -#include - -// Not yet implemented on Android. A real port would map to Daydream -// (Settings.Secure SCREENSAVER_ENABLED / SCREENSAVER_COMPONENTS) plus -// Settings.System SCREEN_OFF_TIMEOUT for the idle delay — no dconf profile -// to write. - -namespace pawletos::profile::platform::screensaver { - -bool apply(const ParsedPayload& p) { - syslog(LOG_WARNING, "[screensaver] not implemented on Android yet, uuid=%s", p.uuid.c_str()); - return false; -} - -void revert(const ParsedPayload& p) { - syslog(LOG_WARNING, "[screensaver] not implemented on Android yet, uuid=%s", p.uuid.c_str()); -} - -} // namespace pawletos::profile::platform::screensaver diff --git a/src/platform/android/SoftwareUpdate.cpp b/src/platform/android/SoftwareUpdate.cpp deleted file mode 100644 index a6b65cf..0000000 --- a/src/platform/android/SoftwareUpdate.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "../SoftwareUpdate.h" - -#include - -// Not yet implemented on Android. PawletOS already has a dedicated update -// policy path — BgUpd's install_mode ("silent"/"manual" per component, see -// android_packages_apps_BgUpd) — a real port would translate this payload's -// automatic/deferral fields into BgUpd's manifest/policy rather than apt -// settings, which don't apply here at all. - -namespace pawletos::profile::platform::software_update { - -bool apply(const ParsedPayload& p) { - syslog(LOG_WARNING, "[software-update] not implemented on Android yet, uuid=%s", p.uuid.c_str()); - return false; -} - -void revert(const ParsedPayload& p) { - syslog(LOG_WARNING, "[software-update] not implemented on Android yet, uuid=%s", p.uuid.c_str()); -} - -} // namespace pawletos::profile::platform::software_update diff --git a/src/platform/android/TimeServer.cpp b/src/platform/android/TimeServer.cpp deleted file mode 100644 index 37414f8..0000000 --- a/src/platform/android/TimeServer.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "../TimeServer.h" - -#include - -// Not yet implemented on Android. A real port would write -// Settings.Global.NTP_SERVER (requires WRITE_SECURE_SETTINGS, same -// permission pattern BgUpd already holds for its own settings writes). - -namespace pawletos::profile::platform::time_server { - -bool apply(const ParsedPayload& p) { - syslog(LOG_WARNING, "[time-server] not implemented on Android yet, uuid=%s", p.uuid.c_str()); - return false; -} - -void revert(const ParsedPayload& p) { - syslog(LOG_WARNING, "[time-server] not implemented on Android yet, uuid=%s", p.uuid.c_str()); -} - -} // namespace pawletos::profile::platform::time_server diff --git a/src/platform/android/Vpn.cpp b/src/platform/android/Vpn.cpp deleted file mode 100644 index 4de5c9e..0000000 --- a/src/platform/android/Vpn.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "../Vpn.h" - -#include - -// Not yet implemented on Android. A real port needs an android.net.VpnService -// component (IKEv2/L2TP have no NetworkManager-plugin equivalent on Android; -// this would mean shipping a companion VPN app or a system VpnService, not -// just writing a config file). - -namespace pawletos::profile::platform::vpn { - -bool apply(const ParsedPayload& p) { - syslog(LOG_WARNING, "[vpn] not implemented on Android yet, uuid=%s", p.uuid.c_str()); - return false; -} - -void revert(const ParsedPayload& p) { - syslog(LOG_WARNING, "[vpn] not implemented on Android yet, uuid=%s", p.uuid.c_str()); -} - -} // namespace pawletos::profile::platform::vpn diff --git a/src/platform/android/Wallpaper.cpp b/src/platform/android/Wallpaper.cpp deleted file mode 100644 index e4cfafe..0000000 --- a/src/platform/android/Wallpaper.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "../Wallpaper.h" - -#include - -// Not yet implemented on Android. A real port would use -// android.app.WallpaperManager (setStream/setResource) — no dconf profile -// to write. - -namespace pawletos::profile::platform::wallpaper { - -bool apply(const ParsedPayload& p) { - syslog(LOG_WARNING, "[wallpaper] not implemented on Android yet, uuid=%s", p.uuid.c_str()); - return false; -} - -void revert(const ParsedPayload& p) { - syslog(LOG_WARNING, "[wallpaper] not implemented on Android yet, uuid=%s", p.uuid.c_str()); -} - -} // namespace pawletos::profile::platform::wallpaper diff --git a/src/platform/android/Wifi.cpp b/src/platform/android/Wifi.cpp deleted file mode 100644 index 68ada08..0000000 --- a/src/platform/android/Wifi.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "../Wifi.h" - -#include - -// Not yet implemented on Android. A real port needs WifiManager / -// WifiNetworkSuggestion (API 29+) or a privileged wpa_supplicant config -// write — NetworkManager keyfiles (the Linux implementation) don't apply. - -namespace pawletos::profile::platform::wifi { - -bool apply(const ParsedPayload& p) { - syslog(LOG_WARNING, "[wifi] not implemented on Android yet, uuid=%s", p.uuid.c_str()); - return false; -} - -void revert(const ParsedPayload& p) { - syslog(LOG_WARNING, "[wifi] not implemented on Android yet, uuid=%s", p.uuid.c_str()); -} - -} // namespace pawletos::profile::platform::wifi diff --git a/third_party/openssl-android/Android.bp b/third_party/openssl-android/Android.bp deleted file mode 100644 index c2ee0b8..0000000 --- a/third_party/openssl-android/Android.bp +++ /dev/null @@ -1,32 +0,0 @@ -// -// Vendored, statically-linked real OpenSSL — pawletprofiled's Android build -// only, nothing else on the system links against these. See README.md for -// why (BoringSSL has no CMS support) and how to populate lib/*/*.a. -// - -cc_prebuilt_library_static { - name: "libcrypto_pawlet_static", - arch: { - arm64: { srcs: ["lib/arm64-v8a/libcrypto.a"] }, - arm: { srcs: ["lib/armeabi-v7a/libcrypto.a"] }, - x86_64: { srcs: ["lib/x86_64/libcrypto.a"] }, - x86: { srcs: ["lib/x86/libcrypto.a"] }, - }, - export_include_dirs: ["include"], - strip: { none: true }, -} - -cc_prebuilt_library_static { - name: "libssl_pawlet_static", - arch: { - arm64: { srcs: ["lib/arm64-v8a/libssl.a"] }, - arm: { srcs: ["lib/armeabi-v7a/libssl.a"] }, - x86_64: { srcs: ["lib/x86_64/libssl.a"] }, - x86: { srcs: ["lib/x86/libssl.a"] }, - }, - export_include_dirs: ["include"], - strip: { none: true }, - // libssl depends on libcrypto symbols; Soong needs this to order the - // static link correctly. - whole_static_libs: ["libcrypto_pawlet_static"], -} diff --git a/third_party/openssl-android/README.md b/third_party/openssl-android/README.md deleted file mode 100644 index 814f54a..0000000 --- a/third_party/openssl-android/README.md +++ /dev/null @@ -1,79 +0,0 @@ -# Vendored OpenSSL (Android, static, pawletprofiled-only) - -AOSP's system `libcrypto`/`libssl` is BoringSSL, which has no CMS/PKCS#7 -support. Rather than touch the platform's crypto stack (used by Keystore, -the TLS stack, other HALs — swapping it breaks far more than it fixes), -pawletprofiled statically links its **own** copy of real OpenSSL, scoped to -just this one binary. Nothing else on the system links against it or even -knows it's there. - -This directory holds the prebuilt static libs + headers and the Soong -modules that expose them. **The `lib/*/` and `include/` directories are -empty placeholders** — populate them by cross-compiling OpenSSL yourself -(steps below) before `m pawletprofiled` will link on Android. Nothing here -fabricates or ships a prebuilt binary sight-unseen. - ---- - -## Building OpenSSL for Android - -Needs the Android NDK (r26+) on your PATH as `$ANDROID_NDK_ROOT`, and -OpenSSL source (3.x recommended — CMS support is stable there). - -```bash -git clone --branch openssl-3.2 --depth 1 https://github.com/openssl/openssl.git -cd openssl - -export ANDROID_NDK_ROOT=/path/to/android-ndk -export PATH="$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH" - -# Repeat per ABI. android-arm64 shown; swap target/API for the others. -for target in android-arm64 android-arm android-x86_64 android-x86; do - case $target in - android-arm64) abi=arm64-v8a ;; - android-arm) abi=armeabi-v7a ;; - android-x86_64) abi=x86_64 ;; - android-x86) abi=x86 ;; - esac - - ./Configure "$target" -D__ANDROID_API__=26 no-shared no-tests \ - --prefix="$(pwd)/build-$abi" - make clean - make -j"$(nproc)" - make install_sw - - mkdir -p "../lib/$abi" - cp "build-$abi/lib/libcrypto.a" "../lib/$abi/" - cp "build-$abi/lib/libssl.a" "../lib/$abi/" -done - -# Headers are identical across ABIs — copy from any one build. -cp -r build-arm64-v8a/include/openssl ../include/ -``` - -`no-shared` is what makes these static (`.a`) — deliberate, so nothing -depends on an OpenSSL `.so` being present on-device at runtime. `no-tests` -just skips building OpenSSL's own test suite to save time. - -## Verifying - -``` -third_party/openssl-android/ -├── include/openssl/*.h (same for every ABI) -└── lib/ - ├── arm64-v8a/{libcrypto,libssl}.a - ├── armeabi-v7a/{libcrypto,libssl}.a - ├── x86_64/{libcrypto,libssl}.a - └── x86/{libcrypto,libssl}.a -``` - -Once populated, `m pawletprofiled` picks these up via `Android.bp` in this -directory — see `libcrypto_pawlet_static` / `libssl_pawlet_static` / -`pawletprofiled_openssl_headers`, referenced from -`pawletprofiled/Android.bp`'s Android `static_libs`. - -## Updating - -OpenSSL ships security fixes regularly — treat these `.a` files as a -dependency you're responsible for rebuilding on new releases, same as any -other vendored library. Nothing here auto-updates them. diff --git a/third_party/openssl-android/include/PLACEHOLDER.txt b/third_party/openssl-android/include/PLACEHOLDER.txt deleted file mode 100644 index c3c5848..0000000 --- a/third_party/openssl-android/include/PLACEHOLDER.txt +++ /dev/null @@ -1 +0,0 @@ -Not populated. Copy the openssl/ header directory from any one ABI build per ../README.md — headers are identical across ABIs. diff --git a/third_party/openssl-android/lib/arm64-v8a/PLACEHOLDER.txt b/third_party/openssl-android/lib/arm64-v8a/PLACEHOLDER.txt deleted file mode 100644 index 1f69047..0000000 --- a/third_party/openssl-android/lib/arm64-v8a/PLACEHOLDER.txt +++ /dev/null @@ -1 +0,0 @@ -Not populated. Build libcrypto.a and libssl.a for arm64-v8a per ../../README.md and drop them in this directory. diff --git a/third_party/openssl-android/lib/armeabi-v7a/PLACEHOLDER.txt b/third_party/openssl-android/lib/armeabi-v7a/PLACEHOLDER.txt deleted file mode 100644 index 8de76c5..0000000 --- a/third_party/openssl-android/lib/armeabi-v7a/PLACEHOLDER.txt +++ /dev/null @@ -1 +0,0 @@ -Not populated. Build libcrypto.a and libssl.a for armeabi-v7a per ../../README.md and drop them in this directory. diff --git a/third_party/openssl-android/lib/x86/PLACEHOLDER.txt b/third_party/openssl-android/lib/x86/PLACEHOLDER.txt deleted file mode 100644 index cb9391a..0000000 --- a/third_party/openssl-android/lib/x86/PLACEHOLDER.txt +++ /dev/null @@ -1 +0,0 @@ -Not populated. Build libcrypto.a and libssl.a for x86 per ../../README.md and drop them in this directory. diff --git a/third_party/openssl-android/lib/x86_64/PLACEHOLDER.txt b/third_party/openssl-android/lib/x86_64/PLACEHOLDER.txt deleted file mode 100644 index f797cf3..0000000 --- a/third_party/openssl-android/lib/x86_64/PLACEHOLDER.txt +++ /dev/null @@ -1 +0,0 @@ -Not populated. Build libcrypto.a and libssl.a for x86_64 per ../../README.md and drop them in this directory.