1 /*
2  * Copyright (C) 2020 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 package com.android.server.devicepolicy;
17 
18 import android.app.ActivityManager;
19 import android.app.admin.DevicePolicyManager;
20 import android.content.ComponentName;
21 import android.os.ShellCommand;
22 import android.os.SystemClock;
23 import android.os.UserHandle;
24 
25 import java.io.PrintWriter;
26 import java.util.Collection;
27 import java.util.List;
28 import java.util.Objects;
29 
30 final class DevicePolicyManagerServiceShellCommand extends ShellCommand {
31 
32     private static final String CMD_IS_SAFE_OPERATION = "is-operation-safe";
33     private static final String CMD_IS_SAFE_OPERATION_BY_REASON = "is-operation-safe-by-reason";
34     private static final String CMD_SET_SAFE_OPERATION = "set-operation-safe";
35     private static final String CMD_LIST_OWNERS = "list-owners";
36     private static final String CMD_LIST_POLICY_EXEMPT_APPS = "list-policy-exempt-apps";
37     private static final String CMD_SET_ACTIVE_ADMIN = "set-active-admin";
38     private static final String CMD_SET_DEVICE_OWNER = "set-device-owner";
39     private static final String CMD_SET_PROFILE_OWNER = "set-profile-owner";
40     private static final String CMD_REMOVE_ACTIVE_ADMIN = "remove-active-admin";
41     private static final String CMD_CLEAR_FREEZE_PERIOD_RECORD = "clear-freeze-period-record";
42     private static final String CMD_FORCE_NETWORK_LOGS = "force-network-logs";
43     private static final String CMD_FORCE_SECURITY_LOGS = "force-security-logs";
44     private static final String CMD_MARK_PO_ON_ORG_OWNED_DEVICE =
45             "mark-profile-owner-on-organization-owned-device";
46 
47     private static final String USER_OPTION = "--user";
48     private static final String DO_ONLY_OPTION = "--device-owner-only";
49 
50     private final DevicePolicyManagerService mService;
51     private int mUserId = UserHandle.USER_SYSTEM;
52     private ComponentName mComponent;
53     private boolean mSetDoOnly;
54 
DevicePolicyManagerServiceShellCommand(DevicePolicyManagerService service)55     DevicePolicyManagerServiceShellCommand(DevicePolicyManagerService service) {
56         mService = Objects.requireNonNull(service);
57     }
58 
59     @Override
onHelp()60     public void onHelp() {
61         try (PrintWriter pw = getOutPrintWriter()) {
62             pw.printf("DevicePolicyManager Service (device_policy) commands:\n\n");
63             showHelp(pw);
64         }
65     }
66 
67     @Override
onCommand(String cmd)68     public int onCommand(String cmd) {
69         if (cmd == null) {
70             return handleDefaultCommands(cmd);
71         }
72         try (PrintWriter pw = getOutPrintWriter()) {
73             switch (cmd) {
74                 case CMD_IS_SAFE_OPERATION:
75                     return runIsSafeOperation(pw);
76                 case CMD_IS_SAFE_OPERATION_BY_REASON:
77                     return runIsSafeOperationByReason(pw);
78                 case CMD_SET_SAFE_OPERATION:
79                     return runSetSafeOperation(pw);
80                 case CMD_LIST_OWNERS:
81                     return runListOwners(pw);
82                 case CMD_LIST_POLICY_EXEMPT_APPS:
83                     return runListPolicyExemptApps(pw);
84                 case CMD_SET_ACTIVE_ADMIN:
85                     return runSetActiveAdmin(pw);
86                 case CMD_SET_DEVICE_OWNER:
87                     return runSetDeviceOwner(pw);
88                 case CMD_SET_PROFILE_OWNER:
89                     return runSetProfileOwner(pw);
90                 case CMD_REMOVE_ACTIVE_ADMIN:
91                     return runRemoveActiveAdmin(pw);
92                 case CMD_CLEAR_FREEZE_PERIOD_RECORD:
93                     return runClearFreezePeriodRecord(pw);
94                 case CMD_FORCE_NETWORK_LOGS:
95                     return runForceNetworkLogs(pw);
96                 case CMD_FORCE_SECURITY_LOGS:
97                     return runForceSecurityLogs(pw);
98                 case CMD_MARK_PO_ON_ORG_OWNED_DEVICE:
99                     return runMarkProfileOwnerOnOrganizationOwnedDevice(pw);
100                 default:
101                     return onInvalidCommand(pw, cmd);
102             }
103         }
104     }
105 
onInvalidCommand(PrintWriter pw, String cmd)106     private int onInvalidCommand(PrintWriter pw, String cmd) {
107         if (super.handleDefaultCommands(cmd) == 0) {
108             return 0;
109         }
110 
111         pw.printf("Usage: \n");
112         showHelp(pw);
113         return -1;
114     }
115 
showHelp(PrintWriter pw)116     private void showHelp(PrintWriter pw) {
117         pw.printf("  help\n");
118         pw.printf("    Prints this help text.\n\n");
119         pw.printf("  %s <OPERATION_ID>\n", CMD_IS_SAFE_OPERATION);
120         pw.printf("    Checks if the give operation is safe \n\n");
121         pw.printf("  %s <REASON_ID>\n", CMD_IS_SAFE_OPERATION_BY_REASON);
122         pw.printf("    Checks if the operations are safe for the given reason\n\n");
123         pw.printf("  %s <OPERATION_ID> <REASON_ID>\n", CMD_SET_SAFE_OPERATION);
124         pw.printf("    Emulates the result of the next call to check if the given operation is safe"
125                 + " \n\n");
126         pw.printf("  %s\n", CMD_LIST_OWNERS);
127         pw.printf("    Lists the device / profile owners per user \n\n");
128         pw.printf("  %s\n", CMD_LIST_POLICY_EXEMPT_APPS);
129         pw.printf("    Lists the apps that are exempt from policies\n\n");
130         pw.printf("  %s [ %s <USER_ID> | current ] <COMPONENT>\n",
131                 CMD_SET_ACTIVE_ADMIN, USER_OPTION);
132         pw.printf("    Sets the given component as active admin for an existing user.\n\n");
133         pw.printf("  %s [ %s <USER_ID> | current *EXPERIMENTAL* ] [ %s ]"
134                 + "<COMPONENT>\n", CMD_SET_DEVICE_OWNER, USER_OPTION, DO_ONLY_OPTION);
135         pw.printf("    Sets the given component as active admin, and its package as device owner."
136                 + "\n\n");
137         pw.printf("  %s [ %s <USER_ID> | current ] <COMPONENT>\n",
138                 CMD_SET_PROFILE_OWNER, USER_OPTION);
139         pw.printf("    Sets the given component as active admin and profile owner for an existing "
140                 + "user.\n\n");
141         pw.printf("  %s [ %s <USER_ID> | current ] <COMPONENT>\n",
142                 CMD_REMOVE_ACTIVE_ADMIN, USER_OPTION);
143         pw.printf("    Disables an active admin, the admin must have declared android:testOnly in "
144                 + "the application in its manifest. This will also remove device and profile "
145                 + "owners.\n\n");
146         pw.printf("  %s\n", CMD_CLEAR_FREEZE_PERIOD_RECORD);
147         pw.printf("    Clears framework-maintained record of past freeze periods that the device "
148                 + "went through. For use during feature development to prevent triggering "
149                 + "restriction on setting freeze periods.\n\n");
150         pw.printf("  %s\n", CMD_FORCE_NETWORK_LOGS);
151         pw.printf("    Makes all network logs available to the DPC and triggers "
152                 + "DeviceAdminReceiver.onNetworkLogsAvailable() if needed.\n\n");
153         pw.printf("  %s\n", CMD_FORCE_SECURITY_LOGS);
154         pw.printf("    Makes all security logs available to the DPC and triggers "
155                 + "DeviceAdminReceiver.onSecurityLogsAvailable() if needed.\n\n");
156         pw.printf("  %s [ %s <USER_ID> | current ] <COMPONENT>\n",
157                 CMD_MARK_PO_ON_ORG_OWNED_DEVICE, USER_OPTION);
158         pw.printf("    Marks the profile owner of the given user as managing an organization-owned"
159                 + "device. That will give it access to device identifiers (such as serial number, "
160                 + "IMEI and MEID), as well as other privileges.\n\n");
161     }
162 
runIsSafeOperation(PrintWriter pw)163     private int runIsSafeOperation(PrintWriter pw) {
164         int operation = Integer.parseInt(getNextArgRequired());
165         int reason = mService.getUnsafeOperationReason(operation);
166         boolean safe = reason == DevicePolicyManager.OPERATION_SAFETY_REASON_NONE;
167         pw.printf("Operation %s is %s. Reason: %s\n",
168                 DevicePolicyManager.operationToString(operation), safeToString(safe),
169                 DevicePolicyManager.operationSafetyReasonToString(reason));
170         return 0;
171     }
172 
runIsSafeOperationByReason(PrintWriter pw)173     private int runIsSafeOperationByReason(PrintWriter pw) {
174         int reason = Integer.parseInt(getNextArgRequired());
175         boolean safe = mService.isSafeOperation(reason);
176         pw.printf("Operations affected by %s are %s\n",
177                 DevicePolicyManager.operationSafetyReasonToString(reason), safeToString(safe));
178         return 0;
179     }
180 
safeToString(boolean safe)181     private static String safeToString(boolean safe) {
182         return safe ? "SAFE" : "UNSAFE";
183     }
184 
runSetSafeOperation(PrintWriter pw)185     private int runSetSafeOperation(PrintWriter pw) {
186         int operation = Integer.parseInt(getNextArgRequired());
187         int reason = Integer.parseInt(getNextArgRequired());
188         mService.setNextOperationSafety(operation, reason);
189         pw.printf("Next call to check operation %s will return %s\n",
190                 DevicePolicyManager.operationToString(operation),
191                 DevicePolicyManager.operationSafetyReasonToString(reason));
192         return 0;
193     }
194 
printAndGetSize(PrintWriter pw, Collection<?> collection, String nameOnSingular)195     private int printAndGetSize(PrintWriter pw, Collection<?> collection, String nameOnSingular) {
196         if (collection.isEmpty()) {
197             pw.printf("no %ss\n", nameOnSingular);
198             return 0;
199         }
200         int size = collection.size();
201         pw.printf("%d %s%s:\n", size, nameOnSingular, (size == 1 ? "" : "s"));
202         return size;
203     }
204 
runListOwners(PrintWriter pw)205     private int runListOwners(PrintWriter pw) {
206         List<OwnerShellData> owners = mService.listAllOwners();
207         int size = printAndGetSize(pw, owners, "owner");
208         if (size == 0) return 0;
209 
210         for (int i = 0; i < size; i++) {
211             OwnerShellData owner = owners.get(i);
212             pw.printf("User %2d: admin=%s", owner.userId, owner.admin.flattenToShortString());
213             if (owner.isDeviceOwner) {
214                 pw.print(",DeviceOwner");
215             }
216             if (owner.isProfileOwner) {
217                 pw.print(",ProfileOwner");
218             }
219             if (owner.isManagedProfileOwner) {
220                 pw.printf(",ManagedProfileOwner(parentUserId=%d)", owner.parentUserId);
221             }
222             if (owner.isAffiliated) {
223                 pw.print(",Affiliated");
224             }
225             pw.println();
226         }
227 
228         return 0;
229     }
230 
runListPolicyExemptApps(PrintWriter pw)231     private int runListPolicyExemptApps(PrintWriter pw) {
232         List<String> apps = mService.listPolicyExemptApps();
233         int size = printAndGetSize(pw, apps, "policy exempt app");
234 
235         if (size == 0) return 0;
236 
237         for (int i = 0; i < size; i++) {
238             String app = apps.get(i);
239             pw.printf("  %d: %s\n", i, app);
240         }
241         return 0;
242     }
243 
runSetActiveAdmin(PrintWriter pw)244     private int runSetActiveAdmin(PrintWriter pw) {
245         parseArgs();
246         mService.setActiveAdmin(mComponent, /* refreshing= */ true, mUserId);
247 
248         pw.printf("Success: Active admin set to component %s\n", mComponent.flattenToShortString());
249         return 0;
250     }
251 
runSetDeviceOwner(PrintWriter pw)252     private int runSetDeviceOwner(PrintWriter pw) {
253         parseArgs();
254         mService.setActiveAdmin(mComponent, /* refreshing= */ true, mUserId);
255 
256         try {
257             if (!mService.setDeviceOwner(mComponent, mUserId,
258                     /* setProfileOwnerOnCurrentUserIfNecessary= */ !mSetDoOnly)) {
259                 throw new RuntimeException(
260                         "Can't set package " + mComponent + " as device owner.");
261             }
262         } catch (Exception e) {
263             // Need to remove the admin that we just added.
264             mService.removeActiveAdmin(mComponent, UserHandle.USER_SYSTEM);
265             throw e;
266         }
267 
268         mService.setUserProvisioningState(
269                 DevicePolicyManager.STATE_USER_SETUP_FINALIZED, mUserId);
270 
271         pw.printf("Success: Device owner set to package %s\n", mComponent.flattenToShortString());
272         pw.printf("Active admin set to component %s\n", mComponent.flattenToShortString());
273         return 0;
274     }
275 
runRemoveActiveAdmin(PrintWriter pw)276     private int runRemoveActiveAdmin(PrintWriter pw) {
277         parseArgs();
278         mService.forceRemoveActiveAdmin(mComponent, mUserId);
279         pw.printf("Success: Admin removed %s\n", mComponent);
280         return 0;
281     }
282 
runSetProfileOwner(PrintWriter pw)283     private int runSetProfileOwner(PrintWriter pw) {
284         parseArgs();
285         mService.setActiveAdmin(mComponent, /* refreshing= */ true, mUserId);
286 
287         try {
288             if (!mService.setProfileOwner(mComponent, mUserId)) {
289                 throw new RuntimeException("Can't set component "
290                         + mComponent.flattenToShortString() + " as profile owner for user "
291                         + mUserId);
292             }
293         } catch (Exception e) {
294             // Need to remove the admin that we just added.
295             mService.removeActiveAdmin(mComponent, mUserId);
296             throw e;
297         }
298 
299         mService.setUserProvisioningState(
300                 DevicePolicyManager.STATE_USER_SETUP_FINALIZED, mUserId);
301 
302         pw.printf("Success: Active admin and profile owner set to %s for user %d\n",
303                 mComponent.flattenToShortString(), mUserId);
304         return 0;
305     }
306 
runClearFreezePeriodRecord(PrintWriter pw)307     private int runClearFreezePeriodRecord(PrintWriter pw) {
308         mService.clearSystemUpdatePolicyFreezePeriodRecord();
309         pw.printf("Success\n");
310         return 0;
311     }
312 
runForceNetworkLogs(PrintWriter pw)313     private int runForceNetworkLogs(PrintWriter pw) {
314         while (true) {
315             long toWait = mService.forceNetworkLogs();
316             if (toWait == 0) {
317                 break;
318             }
319             pw.printf("We have to wait for %d milliseconds...\n", toWait);
320             SystemClock.sleep(toWait);
321         }
322         pw.printf("Success\n");
323         return 0;
324     }
325 
runForceSecurityLogs(PrintWriter pw)326     private int runForceSecurityLogs(PrintWriter pw) {
327         while (true) {
328             long toWait = mService.forceSecurityLogs();
329             if (toWait == 0) {
330                 break;
331             }
332             pw.printf("We have to wait for %d milliseconds...\n", toWait);
333             SystemClock.sleep(toWait);
334         }
335         pw.printf("Success\n");
336         return 0;
337     }
338 
runMarkProfileOwnerOnOrganizationOwnedDevice(PrintWriter pw)339     private int runMarkProfileOwnerOnOrganizationOwnedDevice(PrintWriter pw) {
340         parseArgs();
341         mService.setProfileOwnerOnOrganizationOwnedDevice(mComponent, mUserId, true);
342         pw.printf("Success\n");
343         return 0;
344     }
345 
parseArgs()346     private void parseArgs() {
347         String opt;
348         while ((opt = getNextOption()) != null) {
349             if (USER_OPTION.equals(opt)) {
350                 String arg = getNextArgRequired();
351                 mUserId = UserHandle.parseUserArg(arg);
352                 if (mUserId == UserHandle.USER_CURRENT) {
353                     mUserId = ActivityManager.getCurrentUser();
354                 }
355             } else if (DO_ONLY_OPTION.equals(opt)) {
356                 mSetDoOnly = true;
357             } else {
358                 throw new IllegalArgumentException("Unknown option: " + opt);
359             }
360         }
361         mComponent = parseComponentName(getNextArgRequired());
362     }
363 
parseComponentName(String component)364     private ComponentName parseComponentName(String component) {
365         ComponentName cn = ComponentName.unflattenFromString(component);
366         if (cn == null) {
367             throw new IllegalArgumentException("Invalid component " + component);
368         }
369         return cn;
370     }
371 }
372