1 /*
2  * Copyright (C) 2018 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 android.app.admin;
18 
19 import static android.app.admin.DeviceAdminReceiver.ACTION_CHOOSE_PRIVATE_KEY_ALIAS;
20 import static android.app.admin.DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE;
21 import static android.app.admin.DeviceAdminReceiver.ACTION_SECURITY_LOGS_AVAILABLE;
22 import static android.app.admin.DeviceAdminReceiver.EXTRA_CHOOSE_PRIVATE_KEY_ALIAS;
23 import static android.app.admin.DeviceAdminReceiver.EXTRA_CHOOSE_PRIVATE_KEY_SENDER_UID;
24 import static android.app.admin.DeviceAdminReceiver.EXTRA_CHOOSE_PRIVATE_KEY_URI;
25 import static android.app.admin.DeviceAdminReceiver.EXTRA_NETWORK_LOGS_COUNT;
26 import static android.app.admin.DeviceAdminReceiver.EXTRA_NETWORK_LOGS_TOKEN;
27 
28 import android.annotation.IntRange;
29 import android.annotation.NonNull;
30 import android.annotation.Nullable;
31 import android.app.Service;
32 import android.content.BroadcastReceiver;
33 import android.content.Context;
34 import android.content.Intent;
35 import android.net.Uri;
36 import android.security.KeyChain;
37 import android.util.Log;
38 
39 /**
40  * Base class for delegated apps to handle callbacks related to their delegated capabilities.
41  *
42  * <p>Delegated apps are apps that receive additional capabilities from the profile owner or
43  * device owner apps. Some of these capabilities involve the framework calling into the apps.
44  * To receive these callbacks, delegated apps should subclass this class and override the
45  * appropriate methods here. The subclassed receiver needs to be published in the app's
46  * manifest, with appropriate intent filters to mark which callbacks the receiver is interested
47  * in. An app can have multiple receivers as long as they listen for disjoint set of callbacks.
48  * For the manifest definitions, it must be protected by the
49  * {@link android.Manifest.permission#BIND_DEVICE_ADMIN} permission to ensure only
50  * the system can trigger these callbacks.
51  *
52  * <p>The callback methods happen on the main thread of the process.  Thus long running
53  * operations must be done on another thread.  Note that because a receiver
54  * is done once returning from its onReceive function, such long-running operations
55  * should probably be done in a {@link Service}.
56  *
57  * @see DevicePolicyManager#setDelegatedScopes
58  * @see DeviceAdminReceiver
59  */
60 public class DelegatedAdminReceiver extends BroadcastReceiver {
61     private static final String TAG = "DelegatedAdminReceiver";
62 
63     /**
64      * Allows this receiver to select the alias for a private key and certificate pair for
65      * authentication.  If this method returns null, the default {@link android.app.Activity} will
66      * be shown that lets the user pick a private key and certificate pair.
67      * If this method returns {@link KeyChain#KEY_ALIAS_SELECTION_DENIED},
68      * the default {@link android.app.Activity} will not be shown and the user will not be allowed
69      * to pick anything. And the app, that called {@link KeyChain#choosePrivateKeyAlias}, will
70      * receive {@code null} back.
71      *
72      * <p> This callback is only applicable if the delegated app has
73      * {@link DevicePolicyManager#DELEGATION_CERT_SELECTION} capability. Additionally, it must
74      * declare an intent filter for {@link DeviceAdminReceiver#ACTION_CHOOSE_PRIVATE_KEY_ALIAS}
75      * in the receiver's manifest in order to receive this callback. The default implementation
76      * simply throws {@link UnsupportedOperationException}.
77      *
78      * @param context The running context as per {@link #onReceive}.
79      * @param intent The received intent as per {@link #onReceive}.
80      * @param uid The uid of the app asking for the private key and certificate pair.
81      * @param uri The URI to authenticate, may be null.
82      * @param alias The alias preselected by the client, or null.
83      * @return The private key alias to return and grant access to.
84      * @see KeyChain#choosePrivateKeyAlias
85      */
onChoosePrivateKeyAlias(@onNull Context context, @NonNull Intent intent, int uid, @Nullable Uri uri, @Nullable String alias)86     public @Nullable String onChoosePrivateKeyAlias(@NonNull Context context,
87             @NonNull Intent intent, int uid, @Nullable Uri uri, @Nullable String alias) {
88         throw new UnsupportedOperationException("onChoosePrivateKeyAlias should be implemented");
89     }
90 
91     /**
92      * Called each time a new batch of network logs can be retrieved. This callback method will only
93      * ever be called when network logging is enabled. The logs can only be retrieved while network
94      * logging is enabled.
95      *
96      * <p>If a secondary user or profile is created, this callback won't be received until all users
97      * become affiliated again (even if network logging is enabled). It will also no longer be
98      * possible to retrieve the network logs batch with the most recent {@code batchToken} provided
99      * by this callback. See {@link DevicePolicyManager#setAffiliationIds}.
100      *
101      * <p> This callback is only applicable if the delegated app has
102      * {@link DevicePolicyManager#DELEGATION_NETWORK_LOGGING} capability. Additionally, it must
103      * declare an intent filter for {@link DeviceAdminReceiver#ACTION_NETWORK_LOGS_AVAILABLE} in the
104      * receiver's manifest in order to receive this callback. The default implementation
105      * simply throws {@link UnsupportedOperationException}.
106      *
107      * <p>
108      * This callback is triggered by a foreground broadcast and the app should ensure that any
109      * long-running work is not executed synchronously inside the callback.
110      *
111      * @param context The running context as per {@link #onReceive}.
112      * @param intent The received intent as per {@link #onReceive}.
113      * @param batchToken The token representing the current batch of network logs.
114      * @param networkLogsCount The total count of events in the current batch of network logs.
115      * @see DevicePolicyManager#retrieveNetworkLogs
116      */
onNetworkLogsAvailable(@onNull Context context, @NonNull Intent intent, long batchToken, @IntRange(from = 1) int networkLogsCount)117     public void onNetworkLogsAvailable(@NonNull Context context, @NonNull Intent intent,
118             long batchToken, @IntRange(from = 1) int networkLogsCount) {
119         throw new UnsupportedOperationException("onNetworkLogsAvailable should be implemented");
120     }
121 
122     /**
123      * Called each time a new batch of security logs can be retrieved. This callback method will
124      * only ever be called when security logging is enabled. The logs can only be retrieved while
125      * security logging is enabled.
126      *
127      * <p>If a secondary user or profile is created, this callback won't be received until all users
128      * become affiliated again (even if security logging is enabled). It will also no longer be
129      * possible to retrieve the security logs. See {@link DevicePolicyManager#setAffiliationIds}.
130      *
131      * <p> This callback is only applicable if the delegated app has
132      * {@link DevicePolicyManager#DELEGATION_SECURITY_LOGGING} capability. Additionally, it must
133      * declare an intent filter for {@link DeviceAdminReceiver#ACTION_SECURITY_LOGS_AVAILABLE} in
134      * the receiver's manifest in order to receive this callback. The default implementation
135      * simply throws {@link UnsupportedOperationException}.
136      *
137      * <p>
138      * This callback is triggered by a foreground broadcast and the app should ensure that any
139      * long-running work is not executed synchronously inside the callback.
140      *
141      * @param context The running context as per {@link #onReceive}.
142      * @param intent The received intent as per {@link #onReceive}.
143      * @see DevicePolicyManager#retrieveSecurityLogs
144      */
onSecurityLogsAvailable(@onNull Context context, @NonNull Intent intent)145     public void onSecurityLogsAvailable(@NonNull Context context, @NonNull Intent intent) {
146         throw new UnsupportedOperationException("onSecurityLogsAvailable should be implemented");
147     }
148 
149     /**
150      * Intercept delegated device administrator broadcasts. Implementations should not override
151      * this method; implement the convenience callbacks for each action instead.
152      */
153     @Override
onReceive(@onNull Context context, @NonNull Intent intent)154     public final void onReceive(@NonNull Context context, @NonNull Intent intent) {
155         String action = intent.getAction();
156 
157         if (ACTION_CHOOSE_PRIVATE_KEY_ALIAS.equals(action)) {
158             int uid = intent.getIntExtra(EXTRA_CHOOSE_PRIVATE_KEY_SENDER_UID, -1);
159             Uri uri = intent.getParcelableExtra(EXTRA_CHOOSE_PRIVATE_KEY_URI, android.net.Uri.class);
160             String alias = intent.getStringExtra(EXTRA_CHOOSE_PRIVATE_KEY_ALIAS);
161             String chosenAlias = onChoosePrivateKeyAlias(context, intent, uid, uri, alias);
162             setResultData(chosenAlias);
163         } else if (ACTION_NETWORK_LOGS_AVAILABLE.equals(action)) {
164             long batchToken = intent.getLongExtra(EXTRA_NETWORK_LOGS_TOKEN, -1);
165             int networkLogsCount = intent.getIntExtra(EXTRA_NETWORK_LOGS_COUNT, 0);
166             onNetworkLogsAvailable(context, intent, batchToken, networkLogsCount);
167         } else if (ACTION_SECURITY_LOGS_AVAILABLE.equals(action)) {
168             onSecurityLogsAvailable(context, intent);
169         } else {
170             Log.w(TAG, "Unhandled broadcast: " + action);
171         }
172     }
173 }
174