1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.adservices.service.common;
18 
19 import static android.adservices.common.AdServicesStatusUtils.STATUS_CALLER_NOT_ALLOWED_PACKAGE_NOT_IN_ALLOWLIST;
20 
21 import static com.android.adservices.service.common.AppManifestConfigCall.API_AD_SELECTION;
22 import static com.android.adservices.service.common.AppManifestConfigCall.API_CUSTOM_AUDIENCES;
23 import static com.android.adservices.service.common.AppManifestConfigCall.API_PROTECTED_SIGNALS;
24 import static com.android.adservices.service.common.FledgeAuthorizationFilter.INVALID_API_TYPE;
25 
26 import android.adservices.common.AdServicesStatusUtils;
27 import android.annotation.NonNull;
28 
29 import com.android.adservices.LoggerFactory;
30 import com.android.adservices.service.Flags;
31 import com.android.adservices.service.stats.AdServicesLogger;
32 
33 import java.util.Locale;
34 import java.util.Objects;
35 
36 /** FLEDGE Security filter for {@link AllowLists}. */
37 public class FledgeAllowListsFilter {
38     private static final LoggerFactory.Logger sLogger = LoggerFactory.getFledgeLogger();
39     @NonNull private final Flags mFlags;
40     @NonNull private final AdServicesLogger mAdServicesLogger;
41 
FledgeAllowListsFilter( @onNull Flags flags, @NonNull AdServicesLogger adServicesLogger)42     public FledgeAllowListsFilter(
43             @NonNull Flags flags, @NonNull AdServicesLogger adServicesLogger) {
44         Objects.requireNonNull(flags);
45         Objects.requireNonNull(adServicesLogger);
46 
47         mFlags = flags;
48         mAdServicesLogger = adServicesLogger;
49     }
50 
51     /**
52      * Asserts the package is allowed to call PPAPI.
53      *
54      * <p>Do not use this method in the Binder thread; flags must not be called there.
55      *
56      * @param appPackageName the package name to be validated.
57      * @param apiNameLoggingId the id of the api being called
58      * @param apiType the type of the api being called
59      * @throws AppNotAllowedException if the package is not authorized.
60      */
assertAppInAllowlist( @onNull String appPackageName, int apiNameLoggingId, @AppManifestConfigCall.ApiType int apiType)61     public void assertAppInAllowlist(
62             @NonNull String appPackageName,
63             int apiNameLoggingId,
64             @AppManifestConfigCall.ApiType int apiType)
65             throws AppNotAllowedException {
66         Objects.requireNonNull(appPackageName);
67         if (!isInAllowList(appPackageName, apiType)) {
68             sLogger.v(
69                     "App package name \"%s\" not authorized to call API %d",
70                     appPackageName, apiNameLoggingId);
71             mAdServicesLogger.logFledgeApiCallStats(
72                     apiNameLoggingId,
73                     appPackageName,
74                     STATUS_CALLER_NOT_ALLOWED_PACKAGE_NOT_IN_ALLOWLIST,
75                     /*latencyMs=*/ 0);
76             throw new AppNotAllowedException();
77         }
78     }
79 
80     /**
81      * Internal exception for easy assertion catches specific to checking that an app is allowed to
82      * use the PP APIs.
83      *
84      * <p>This exception is not meant to be exposed externally and should not be passed outside of
85      * the service.
86      */
87     public static class AppNotAllowedException extends SecurityException {
88         /**
89          * Creates a {@link AppNotAllowedException}, used in cases where an app should have been
90          * allowed to use the PP APIs.
91          */
AppNotAllowedException()92         public AppNotAllowedException() {
93             super(AdServicesStatusUtils.SECURITY_EXCEPTION_CALLER_NOT_ALLOWED_ERROR_MESSAGE);
94         }
95     }
96 
isInAllowList( String appPackageName, @AppManifestConfigCall.ApiType int apiType)97     private boolean isInAllowList(
98             String appPackageName, @AppManifestConfigCall.ApiType int apiType) {
99         if (apiType == API_CUSTOM_AUDIENCES) {
100             return AllowLists.isPackageAllowListed(mFlags.getPpapiAppAllowList(), appPackageName);
101         } else if (apiType == API_PROTECTED_SIGNALS) {
102             return AllowLists.isPackageAllowListed(mFlags.getPasAppAllowList(), appPackageName);
103         } else if (apiType == API_AD_SELECTION) {
104             return AllowLists.isPackageAllowListed(mFlags.getPpapiAppAllowList(), appPackageName)
105                     || AllowLists.isPackageAllowListed(mFlags.getPasAppAllowList(), appPackageName);
106         } else {
107             throw new IllegalStateException(
108                     String.format(Locale.ENGLISH, INVALID_API_TYPE, apiType));
109         }
110     }
111 }
112