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

Commit 5519d7cf authored by Jeremy Joslin's avatar Jeremy Joslin
Browse files

Check for REQUEST_NETWORK_SCORES instead of BROADCAST_NETWORK_PRIVILEGED.

Test: runtest frameworks-services -c com.android.server.NetworkScoreServiceTest
BUG: 33752149
Change-Id: I7d91fa9a4f6ef4f9170c6af98567ce443c805e74
parent eb2d14b8
Loading
Loading
Loading
Loading
+9 −22
Original line number Diff line number Diff line
@@ -16,18 +16,15 @@

package android.net;

import android.Manifest;
import android.annotation.IntDef;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.content.Context;
import android.content.Intent;
import android.net.NetworkScorerAppManager.NetworkScorerAppData;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
import android.os.UserHandle;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -44,19 +41,11 @@ import java.lang.annotation.RetentionPolicy;
 * <p>A network scorer is any application which:
 * <ul>
 * <li>Declares the {@link android.Manifest.permission#SCORE_NETWORKS} permission.
 * <li>Includes a receiver for {@link #ACTION_SCORE_NETWORKS} guarded by the
 *     {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission which scores
 *     networks and (eventually) calls {@link #updateScores} with the results. If this receiver
 *     specifies an android:label attribute, this label will be used when referring to the
 *     application throughout system settings; otherwise, the application label will be used.
 * <li>Include a Service for the {@link #ACTION_RECOMMEND_NETWORKS} action
 *     protected by the {@link android.Manifest.permission#BIND_NETWORK_RECOMMENDATION_SERVICE}
 *     permission.
 * </ul>
 *
 * <p>The system keeps track of an active scorer application; at any time, only this application
 * will receive {@link #ACTION_SCORE_NETWORKS} broadcasts and will be permitted to call
 * {@link #updateScores}. Applications may determine the current active scorer with
 * {@link #getActiveScorerPackage()} and request to change the active scorer by sending an
 * {@link #ACTION_CHANGE_ACTIVE} broadcast with another scorer.
 *
 * @hide
 */
@SystemApi
@@ -263,12 +252,9 @@ public class NetworkScoreManager {
    /**
     * Request scoring for networks.
     *
     * <p>Note that this is just a helper method to assemble the broadcast, and will run in the
     * calling process.
     *
     * @return true if the broadcast was sent, or false if there is no active scorer.
     * @throws SecurityException if the caller does not hold the
     *         {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission.
     *         {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission.
     * @hide
     */
    public boolean requestScores(NetworkKey[] networks) throws SecurityException {
@@ -285,7 +271,7 @@ public class NetworkScoreManager {
     * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}.
     * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores.
     * @throws SecurityException if the caller does not hold the
     *         {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission.
     *         {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission.
     * @throws IllegalArgumentException if a score cache is already registered for this type.
     * @deprecated equivalent to registering for cache updates with CACHE_FILTER_NONE.
     * @hide
@@ -302,7 +288,7 @@ public class NetworkScoreManager {
     * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores
     * @param filterType the {@link CacheUpdateFilter} to apply
     * @throws SecurityException if the caller does not hold the
     *         {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission.
     *         {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission.
     * @throws IllegalArgumentException if a score cache is already registered for this type.
     * @hide
     */
@@ -321,7 +307,7 @@ public class NetworkScoreManager {
     * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}.
     * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores.
     * @throws SecurityException if the caller does not hold the
     *         {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission.
     *         {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission.
     * @throws IllegalArgumentException if a score cache is already registered for this type.
     * @hide
     */
@@ -342,7 +328,8 @@ public class NetworkScoreManager {
     *                request details
     * @return a {@link RecommendationResult} instance containing the recommended network
     *         to connect to
     * @throws SecurityException
     * @throws SecurityException if the caller does not hold the
     *         {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission.
     */
    public RecommendationResult requestRecommendation(RecommendationRequest request)
            throws SecurityException {
+2 −3
Original line number Diff line number Diff line
@@ -1260,9 +1260,8 @@
    <!-- A list of potential packages, in priority order, that may contain a
         network recommendation provider. A network recommendation provider must:
             * Be granted the SCORE_NETWORKS permission.
             * Include a Receiver for the android.net.scoring.SCORE_NETWORKS action guarded by the
               BROADCAST_NETWORK_PRIVILEGED permission.
             * Include a Service for the android.net.scoring.RECOMMEND_NETWORKS action.
             * Include a Service for the android.net.scoring.RECOMMEND_NETWORKS action
               protected by the BIND_NETWORK_RECOMMENDATION_SERVICE permission.

         This may be empty if network scoring and recommending isn't supported.
         -->
+15 −16
Original line number Diff line number Diff line
@@ -34,9 +34,9 @@ import android.net.INetworkRecommendationProvider;
import android.net.INetworkScoreCache;
import android.net.INetworkScoreService;
import android.net.NetworkKey;
import android.net.NetworkScoreManager;
import android.net.NetworkScorerAppManager;
import android.net.NetworkScorerAppManager.NetworkScorerAppData;
import android.net.NetworkScoreManager;
import android.net.RecommendationRequest;
import android.net.RecommendationResult;
import android.net.ScoredNetwork;
@@ -380,13 +380,16 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
        }
    }

    private boolean isCallerSystemUid() {
        // REQUEST_NETWORK_SCORES is a signature only permission.
        return mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES) ==
                 PackageManager.PERMISSION_GRANTED;
    }

    @Override
    public boolean clearScores() {
        // Only the active scorer or the system (who can broadcast BROADCAST_NETWORK_PRIVILEGED)
        // should be allowed to flush all scores.
        if (mNetworkScorerAppManager.isCallerActiveScorer(getCallingUid()) ||
                mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED) ==
                        PackageManager.PERMISSION_GRANTED) {
        // Only the active scorer or the system should be allowed to flush all scores.
        if (mNetworkScorerAppManager.isCallerActiveScorer(getCallingUid()) || isCallerSystemUid()) {
            final long token = Binder.clearCallingIdentity();
            try {
                clearInternal();
@@ -409,7 +412,6 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
        // In the future, should this API be opened to 3p apps, we will need to lock this down and
        // figure out another way to streamline the UX.

        // mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG);
        mContext.enforceCallingOrSelfPermission(permission.SCORE_NETWORKS, TAG);

        // Scorers (recommendation providers) are selected and no longer set.
@@ -418,11 +420,8 @@ public class NetworkScoreService extends INetworkScoreService.Stub {

    @Override
    public void disableScoring() {
        // Only the active scorer or the system (who can broadcast BROADCAST_NETWORK_PRIVILEGED)
        // should be allowed to disable scoring.
        if (mNetworkScorerAppManager.isCallerActiveScorer(getCallingUid()) ||
                mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED) ==
                        PackageManager.PERMISSION_GRANTED) {
        // Only the active scorer or the system should be allowed to disable scoring.
        if (mNetworkScorerAppManager.isCallerActiveScorer(getCallingUid()) || isCallerSystemUid()) {
            // no-op for now but we could write to the setting if needed.
        } else {
            throw new SecurityException(
@@ -450,7 +449,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
    public void registerNetworkScoreCache(int networkType,
                                          INetworkScoreCache scoreCache,
                                          int filterType) {
        mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG);
        mContext.enforceCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES, TAG);
        final long token = Binder.clearCallingIdentity();
        try {
            synchronized (mScoreCaches) {
@@ -475,7 +474,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub {

    @Override
    public void unregisterNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) {
        mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG);
        mContext.enforceCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES, TAG);
        final long token = Binder.clearCallingIdentity();
        try {
            synchronized (mScoreCaches) {
@@ -496,7 +495,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub {

    @Override
    public RecommendationResult requestRecommendation(RecommendationRequest request) {
        mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG);
        mContext.enforceCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES, TAG);
        throwIfCalledOnMainThread();
        final long token = Binder.clearCallingIdentity();
        try {
@@ -526,7 +525,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub {

    @Override
    public boolean requestScores(NetworkKey[] networks) {
        mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG);
        mContext.enforceCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES, TAG);
        final long token = Binder.clearCallingIdentity();
        try {
            final INetworkRecommendationProvider provider = getRecommendationProvider();
+10 −10
Original line number Diff line number Diff line
@@ -147,11 +147,11 @@ public class NetworkScoreServiceTest {
    @Test
    public void testRequestScores_noPermission() throws Exception {
        doThrow(new SecurityException()).when(mContext)
            .enforceCallingOrSelfPermission(eq(permission.BROADCAST_NETWORK_PRIVILEGED),
            .enforceCallingOrSelfPermission(eq(permission.REQUEST_NETWORK_SCORES),
                anyString());
        try {
            mNetworkScoreService.requestScores(null);
            fail("BROADCAST_NETWORK_PRIVILEGED not enforced.");
            fail("REQUEST_NETWORK_SCORES not enforced.");
        } catch (SecurityException e) {
            // expected
        }
@@ -184,11 +184,11 @@ public class NetworkScoreServiceTest {
    @Test
    public void testRequestRecommendation_noPermission() throws Exception {
        doThrow(new SecurityException()).when(mContext)
            .enforceCallingOrSelfPermission(eq(permission.BROADCAST_NETWORK_PRIVILEGED),
            .enforceCallingOrSelfPermission(eq(permission.REQUEST_NETWORK_SCORES),
                anyString());
        try {
            mNetworkScoreService.requestRecommendation(mRecommendationRequest);
            fail("BROADCAST_NETWORK_PRIVILEGED not enforced.");
            fail("REQUEST_NETWORK_SCORES not enforced.");
        } catch (SecurityException e) {
            // expected
        }
@@ -324,7 +324,7 @@ public class NetworkScoreServiceTest {
    @Test
    public void testClearScores_notActiveScorer_noBroadcastNetworkPermission() {
        when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false);
        when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED))
        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
            .thenReturn(PackageManager.PERMISSION_DENIED);
        try {
            mNetworkScoreService.clearScores();
@@ -337,7 +337,7 @@ public class NetworkScoreServiceTest {
    @Test
    public void testClearScores_activeScorer_noBroadcastNetworkPermission() {
        when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true);
        when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED))
        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
            .thenReturn(PackageManager.PERMISSION_DENIED);

        mNetworkScoreService.clearScores();
@@ -358,7 +358,7 @@ public class NetworkScoreServiceTest {
    public void testClearScores_notActiveScorer_hasBroadcastNetworkPermission()
            throws RemoteException {
        when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false);
        when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED))
        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
                .thenReturn(PackageManager.PERMISSION_GRANTED);

        mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
@@ -384,7 +384,7 @@ public class NetworkScoreServiceTest {
    @Test
    public void testDisableScoring_notActiveScorer_noBroadcastNetworkPermission() {
        when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false);
        when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED))
        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
                .thenReturn(PackageManager.PERMISSION_DENIED);

        try {
@@ -398,7 +398,7 @@ public class NetworkScoreServiceTest {
    @Test
    public void testRegisterNetworkScoreCache_noBroadcastNetworkPermission() {
        doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
                eq(permission.BROADCAST_NETWORK_PRIVILEGED), anyString());
                eq(permission.REQUEST_NETWORK_SCORES), anyString());

        try {
            mNetworkScoreService.registerNetworkScoreCache(
@@ -412,7 +412,7 @@ public class NetworkScoreServiceTest {
    @Test
    public void testUnregisterNetworkScoreCache_noBroadcastNetworkPermission() {
        doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
                eq(permission.BROADCAST_NETWORK_PRIVILEGED), anyString());
                eq(permission.REQUEST_NETWORK_SCORES), anyString());

        try {
            mNetworkScoreService.unregisterNetworkScoreCache(