Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4ce81b71 authored by Oliver Scott's avatar Oliver Scott Committed by Michael Bestas
Browse files

Stop domain verification delegated from UIDs blocked by network policy

Issue: calyxos#889
Change-Id: I00278802bdf9e9d2ff2c8e94304a14cceb1a2c0d
parent 7d582627
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
    <uses-permission android:name="android.permission.INTENT_FILTER_VERIFICATION_AGENT"/>
    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.OBSERVE_NETWORK_POLICY"/>
    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    <uses-permission android:name="android.permission.UPDATE_DOMAIN_VERIFICATION_USER_SELECTION"/>
+1 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ class StatementServiceApplication : Application() {
        if (userManager.isUserUnlocked) {
            // WorkManager can only schedule when the user data directories are unencrypted (after
            // the user has entered their lock password.
            DomainVerificationUtils.registerNetworkPolicyListener(this)
            DomainVerificationUtils.schedulePeriodicCheckUnlocked(WorkManager.getInstance(this))
            DomainVerificationUtils.schedulePeriodicUpdateUnlocked(WorkManager.getInstance(this))
        }
+1 −0
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ class BootCompletedReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        if (intent.action != Intent.ACTION_BOOT_COMPLETED) return
        val workManager = WorkManager.getInstance(context)
        DomainVerificationUtils.registerNetworkPolicyListener(context)
        DomainVerificationUtils.schedulePeriodicCheckUnlocked(workManager)
        workManager.beginUniqueWork(
            PACKAGE_BOOT_REQUEST_KEY,
+32 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.statementservice.domain

import android.content.Context
import android.net.NetworkPolicyManager
import androidx.work.Constraints
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.NetworkType
@@ -36,6 +38,9 @@ object DomainVerificationUtils {

    private const val UPDATE_WORKER_ENABLED = false

    private val uidBlockedReasons = mutableMapOf<Int, Int>()
    private var networkPolicyListener: NetworkPolicyManager.Listener? = null

    /**
     * In a majority of cases, the initial requests will be enough to verify domains, since they
     * are also restricted to [NetworkType.CONNECTED], but for cases where they aren't sufficient,
@@ -113,4 +118,31 @@ object DomainVerificationUtils {
            }
        }
    }

    fun getUidBlockedReasons(uid: Int) : Int? {
        return uidBlockedReasons[uid]
    }

    fun registerNetworkPolicyListener(context: Context) {
        if (networkPolicyListener != null) {
            unregisterNetworkPolicyListener(context)
        }
        networkPolicyListener = object : NetworkPolicyManager.Listener() {
            override fun onBlockedReasonChanged(
                uid: Int,
                oldBlockedReasons: Int,
                newBlockedReasons: Int
            ) {
                uidBlockedReasons[uid] = newBlockedReasons
            }
        }
        val networkPolicyManager = context.getSystemService(NetworkPolicyManager::class.java)
        networkPolicyManager?.registerListener(networkPolicyListener)
    }

    private fun unregisterNetworkPolicyListener(context: Context) {
        val networkPolicyManager = context.getSystemService(NetworkPolicyManager::class.java)
        networkPolicyManager?.unregisterListener(networkPolicyListener)
        networkPolicyListener = null
    }
}
+12 −0
Original line number Diff line number Diff line
@@ -17,7 +17,10 @@
package com.android.statementservice.domain

import android.content.Context
import android.content.pm.PackageManager
import android.content.pm.verify.domain.DomainVerificationManager
import android.net.ConnectivityManager.BLOCKED_REASON_APP_BACKGROUND
import android.net.ConnectivityManager.BLOCKED_REASON_NONE
import android.net.Network
import android.util.Log
import androidx.collection.LruCache
@@ -92,6 +95,15 @@ class DomainVerifier private constructor(
        val assetMatcher = synchronized(targetAssetCache) { targetAssetCache[packageName] }
            .takeIf { it!!.isPresent }
            ?: return Triple(WorkResult.failure(), VerifyStatus.FAILURE_PACKAGE_MANAGER, null)
        val packageUid = appContext.packageManager.getPackageUid(
            packageName,
            PackageManager.PackageInfoFlags.of(0)
        )
        // Fail if no blocked reason is set or for any reason other than APP_BACKGROUND and NONE
        if (DomainVerificationUtils.getUidBlockedReasons(packageUid)
            ?.and(BLOCKED_REASON_APP_BACKGROUND.inv())?.and(BLOCKED_REASON_NONE.inv()) != 0) {
            return Triple(WorkResult.failure(), VerifyStatus.NO_RESPONSE, null)
        }
        return verifyHost(host, assetMatcher.get(), network)
    }