Merge "Allow PO to enable security logging on work profile" into sc-dev

This commit is contained in:
Branden Archer
2021-03-19 20:24:30 +00:00
committed by Android (Google) Code Review
6 changed files with 127 additions and 29 deletions

View File

@@ -6943,6 +6943,7 @@ package android.app.admin {
method @Nullable public String onChoosePrivateKeyAlias(@NonNull android.content.Context, @NonNull android.content.Intent, int, @Nullable android.net.Uri, @Nullable String);
method public void onNetworkLogsAvailable(@NonNull android.content.Context, @NonNull android.content.Intent, long, @IntRange(from=1) int);
method public final void onReceive(@NonNull android.content.Context, @NonNull android.content.Intent);
method public void onSecurityLogsAvailable(@NonNull android.content.Context, @NonNull android.content.Intent);
}
public final class DeviceAdminInfo implements android.os.Parcelable {
@@ -7020,6 +7021,7 @@ package android.app.admin {
field public static final String ACTION_PASSWORD_FAILED = "android.app.action.ACTION_PASSWORD_FAILED";
field public static final String ACTION_PASSWORD_SUCCEEDED = "android.app.action.ACTION_PASSWORD_SUCCEEDED";
field public static final String ACTION_PROFILE_PROVISIONING_COMPLETE = "android.app.action.PROFILE_PROVISIONING_COMPLETE";
field public static final String ACTION_SECURITY_LOGS_AVAILABLE = "android.app.action.SECURITY_LOGS_AVAILABLE";
field public static final int BUGREPORT_FAILURE_FAILED_COMPLETING = 0; // 0x0
field public static final int BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE = 1; // 0x1
field public static final String DEVICE_ADMIN_META_DATA = "android.app.device_admin";
@@ -7315,6 +7317,7 @@ package android.app.admin {
field public static final String DELEGATION_NETWORK_LOGGING = "delegation-network-logging";
field public static final String DELEGATION_PACKAGE_ACCESS = "delegation-package-access";
field public static final String DELEGATION_PERMISSION_GRANT = "delegation-permission-grant";
field public static final String DELEGATION_SECURITY_LOGGING = "delegation-security-logging";
field public static final int ENCRYPTION_STATUS_ACTIVATING = 2; // 0x2
field public static final int ENCRYPTION_STATUS_ACTIVE = 3; // 0x3
field public static final int ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY = 4; // 0x4

View File

@@ -18,6 +18,7 @@ package android.app.admin;
import static android.app.admin.DeviceAdminReceiver.ACTION_CHOOSE_PRIVATE_KEY_ALIAS;
import static android.app.admin.DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE;
import static android.app.admin.DeviceAdminReceiver.ACTION_SECURITY_LOGS_AVAILABLE;
import static android.app.admin.DeviceAdminReceiver.EXTRA_CHOOSE_PRIVATE_KEY_ALIAS;
import static android.app.admin.DeviceAdminReceiver.EXTRA_CHOOSE_PRIVATE_KEY_SENDER_UID;
import static android.app.admin.DeviceAdminReceiver.EXTRA_CHOOSE_PRIVATE_KEY_URI;
@@ -114,6 +115,29 @@ public class DelegatedAdminReceiver extends BroadcastReceiver {
throw new UnsupportedOperationException("onNetworkLogsAvailable should be implemented");
}
/**
* Called each time a new batch of security logs can be retrieved. This callback method will
* only ever be called when security logging is enabled. The logs can only be retrieved while
* security logging is enabled.
*
* <p>If a secondary user or profile is created, this callback won't be received until all users
* become affiliated again (even if security logging is enabled). It will also no longer be
* possible to retrieve the security logs. See {@link DevicePolicyManager#setAffiliationIds}.
*
* <p> This callback is only applicable if the delegated app has
* {@link DevicePolicyManager#DELEGATION_SECURITY_LOGGING} capability. Additionally, it must
* declare an intent filter for {@link DeviceAdminReceiver#ACTION_SECURITY_LOGS_AVAILABLE} in
* the receiver's manifest in order to receive this callback. The default implementation
* simply throws {@link UnsupportedOperationException}.
*
* @param context The running context as per {@link #onReceive}.
* @param intent The received intent as per {@link #onReceive}.
* @see DevicePolicyManager#retrieveSecurityLogs
*/
public void onSecurityLogsAvailable(@NonNull Context context, @NonNull Intent intent) {
throw new UnsupportedOperationException("onSecurityLogsAvailable should be implemented");
}
/**
* Intercept delegated device administrator broadcasts. Implementations should not override
* this method; implement the convenience callbacks for each action instead.
@@ -132,6 +156,8 @@ public class DelegatedAdminReceiver extends BroadcastReceiver {
long batchToken = intent.getLongExtra(EXTRA_NETWORK_LOGS_TOKEN, -1);
int networkLogsCount = intent.getIntExtra(EXTRA_NETWORK_LOGS_COUNT, 0);
onNetworkLogsAvailable(context, intent, batchToken, networkLogsCount);
} else if (ACTION_SECURITY_LOGS_AVAILABLE.equals(action)) {
onSecurityLogsAvailable(context, intent);
} else {
Log.w(TAG, "Unhandled broadcast: " + action);
}

View File

@@ -290,7 +290,6 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
/**
* Broadcast action: notify that a new batch of security logs is ready to be collected.
* @hide
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
@BroadcastBehavior(explicitOnly = true)

View File

@@ -1904,6 +1904,20 @@ public class DevicePolicyManager {
*/
public static final String DELEGATION_CERT_SELECTION = "delegation-cert-selection";
/**
* Grants access to {@link #setSecurityLoggingEnabled}, {@link #isSecurityLoggingEnabled},
* {@link #retrieveSecurityLogs}, and {@link #retrievePreRebootSecurityLogs}. Once granted the
* delegated app will start receiving {@link DelegatedAdminReceiver#onSecurityLogsAvailable}
* callback, and Device owner or Profile Owner will no longer receive the
* {@link DeviceAdminReceiver#onSecurityLogsAvailable} callback. There can be at most one app
* that has this delegation. If another app already had delegated security logging access, it
* will lose the delegation when a new app is delegated.
*
* <p> Can only be granted by Device Owner or Profile Owner of an organnization owned and
* managed profile.
*/
public static final String DELEGATION_SECURITY_LOGGING = "delegation-security-logging";
/**
* No management for current user in-effect. This is the default.
* @hide
@@ -11241,7 +11255,7 @@ public class DevicePolicyManager {
public void setSecurityLoggingEnabled(@NonNull ComponentName admin, boolean enabled) {
throwIfParentInstance("setSecurityLoggingEnabled");
try {
mService.setSecurityLoggingEnabled(admin, enabled);
mService.setSecurityLoggingEnabled(admin, mContext.getPackageName(), enabled);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
@@ -11260,7 +11274,7 @@ public class DevicePolicyManager {
public boolean isSecurityLoggingEnabled(@Nullable ComponentName admin) {
throwIfParentInstance("isSecurityLoggingEnabled");
try {
return mService.isSecurityLoggingEnabled(admin);
return mService.isSecurityLoggingEnabled(admin, mContext.getPackageName());
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
@@ -11285,10 +11299,12 @@ public class DevicePolicyManager {
* @see #isAffiliatedUser
* @see DeviceAdminReceiver#onSecurityLogsAvailable
*/
@SuppressLint("NullableCollection")
public @Nullable List<SecurityEvent> retrieveSecurityLogs(@NonNull ComponentName admin) {
throwIfParentInstance("retrieveSecurityLogs");
try {
ParceledListSlice<SecurityEvent> list = mService.retrieveSecurityLogs(admin);
ParceledListSlice<SecurityEvent> list = mService.retrieveSecurityLogs(
admin, mContext.getPackageName());
if (list != null) {
return list.getList();
} else {
@@ -11438,11 +11454,13 @@ public class DevicePolicyManager {
* @see #isAffiliatedUser
* @see #retrieveSecurityLogs
*/
@SuppressLint("NullableCollection")
public @Nullable List<SecurityEvent> retrievePreRebootSecurityLogs(
@NonNull ComponentName admin) {
throwIfParentInstance("retrievePreRebootSecurityLogs");
try {
ParceledListSlice<SecurityEvent> list = mService.retrievePreRebootSecurityLogs(admin);
ParceledListSlice<SecurityEvent> list = mService.retrievePreRebootSecurityLogs(
admin, mContext.getPackageName());
if (list != null) {
return list.getList();
} else {

View File

@@ -386,10 +386,10 @@ interface IDevicePolicyManager {
List<String> getAffiliationIds(in ComponentName admin);
boolean isAffiliatedUser();
void setSecurityLoggingEnabled(in ComponentName admin, boolean enabled);
boolean isSecurityLoggingEnabled(in ComponentName admin);
ParceledListSlice retrieveSecurityLogs(in ComponentName admin);
ParceledListSlice retrievePreRebootSecurityLogs(in ComponentName admin);
void setSecurityLoggingEnabled(in ComponentName admin, String packageName, boolean enabled);
boolean isSecurityLoggingEnabled(in ComponentName admin, String packageName);
ParceledListSlice retrieveSecurityLogs(in ComponentName admin, String packageName);
ParceledListSlice retrievePreRebootSecurityLogs(in ComponentName admin, String packageName);
long forceNetworkLogs();
long forceSecurityLogs();

View File

@@ -51,6 +51,7 @@ import static android.app.admin.DevicePolicyManager.DELEGATION_KEEP_UNINSTALLED_
import static android.app.admin.DevicePolicyManager.DELEGATION_NETWORK_LOGGING;
import static android.app.admin.DevicePolicyManager.DELEGATION_PACKAGE_ACCESS;
import static android.app.admin.DevicePolicyManager.DELEGATION_PERMISSION_GRANT;
import static android.app.admin.DevicePolicyManager.DELEGATION_SECURITY_LOGGING;
import static android.app.admin.DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER;
import static android.app.admin.DevicePolicyManager.ID_TYPE_BASE_INFO;
import static android.app.admin.DevicePolicyManager.ID_TYPE_IMEI;
@@ -430,6 +431,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
DELEGATION_INSTALL_EXISTING_PACKAGE,
DELEGATION_KEEP_UNINSTALLED_PACKAGES,
DELEGATION_NETWORK_LOGGING,
DELEGATION_SECURITY_LOGGING,
DELEGATION_CERT_SELECTION,
};
@@ -440,9 +442,18 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
DELEGATION_NETWORK_LOGGING,
});
// Subset of delegations that can only be delegated by Device Owner or Profile Owner of an
// organization-owned and managed profile.
private static final List<String>
DEVICE_OWNER_OR_ORGANIZATION_OWNED_MANAGED_PROFILE_OWNER_DELEGATIONS =
Arrays.asList(new String[]{
DELEGATION_SECURITY_LOGGING,
});
// Subset of delegations that only one single package within a given user can hold
private static final List<String> EXCLUSIVE_DELEGATIONS = Arrays.asList(new String[] {
DELEGATION_NETWORK_LOGGING,
DELEGATION_SECURITY_LOGGING,
DELEGATION_CERT_SELECTION,
});
@@ -6024,6 +6035,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!Collections.disjoint(scopes, DEVICE_OWNER_OR_MANAGED_PROFILE_OWNER_DELEGATIONS)) {
Preconditions.checkCallAuthorization(isDeviceOwner(caller)
|| (isProfileOwner(caller) && isManagedProfile(caller.getUserId())));
} else if (!Collections.disjoint(
scopes, DEVICE_OWNER_OR_ORGANIZATION_OWNED_MANAGED_PROFILE_OWNER_DELEGATIONS)) {
Preconditions.checkCallAuthorization(isDeviceOwner(caller)
|| isProfileOwnerOfOrganizationOwnedDevice(caller));
} else {
Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
}
@@ -7658,6 +7673,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
receiverComponent = resolveDelegateReceiver(DELEGATION_NETWORK_LOGGING, action,
deviceOwnerUserId);
}
if (action.equals(DeviceAdminReceiver.ACTION_SECURITY_LOGS_AVAILABLE)) {
receiverComponent = resolveDelegateReceiver(DELEGATION_SECURITY_LOGGING, action,
deviceOwnerUserId);
}
if (receiverComponent == null) {
synchronized (getLockObject()) {
receiverComponent = mOwners.getDeviceOwnerComponent();
@@ -7674,6 +7693,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (action.equals(DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE)) {
receiverComponent = resolveDelegateReceiver(DELEGATION_NETWORK_LOGGING, action, userId);
}
if (action.equals(DeviceAdminReceiver.ACTION_SECURITY_LOGS_AVAILABLE)) {
receiverComponent = resolveDelegateReceiver(
DELEGATION_SECURITY_LOGGING, action, userId);
}
if (receiverComponent == null) {
receiverComponent = getOwnerComponent(userId);
}
@@ -13920,16 +13943,24 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
@Override
public void setSecurityLoggingEnabled(ComponentName admin, boolean enabled) {
public void setSecurityLoggingEnabled(ComponentName admin, String packageName,
boolean enabled) {
if (!mHasFeature) {
return;
}
Objects.requireNonNull(admin);
final CallerIdentity caller = getCallerIdentity(admin);
final CallerIdentity caller = getCallerIdentity(admin, packageName);
synchronized (getLockObject()) {
Preconditions.checkCallAuthorization(isProfileOwnerOfOrganizationOwnedDevice(caller)
|| isDeviceOwner(caller));
if (admin != null) {
Preconditions.checkCallAuthorization(
isProfileOwnerOfOrganizationOwnedDevice(caller)
|| isDeviceOwner(caller));
} else {
// A delegate app passes a null admin component, which is expected
Preconditions.checkCallAuthorization(
isCallerDelegate(caller, DELEGATION_SECURITY_LOGGING));
}
if (enabled == mInjector.securityLogGetLoggingEnabledProperty()) {
return;
}
@@ -13949,17 +13980,23 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
@Override
public boolean isSecurityLoggingEnabled(ComponentName admin) {
public boolean isSecurityLoggingEnabled(ComponentName admin, String packageName) {
if (!mHasFeature) {
return false;
}
synchronized (getLockObject()) {
if (!isCallerWithSystemUid()) {
Objects.requireNonNull(admin);
final CallerIdentity caller = getCallerIdentity(admin);
Preconditions.checkCallAuthorization(
isProfileOwnerOfOrganizationOwnedDevice(caller) || isDeviceOwner(caller));
final CallerIdentity caller = getCallerIdentity(admin, packageName);
if (admin != null) {
Preconditions.checkCallAuthorization(
isProfileOwnerOfOrganizationOwnedDevice(caller)
|| isDeviceOwner(caller));
} else {
// A delegate app passes a null admin component, which is expected
Preconditions.checkCallAuthorization(
isCallerDelegate(caller, DELEGATION_SECURITY_LOGGING));
}
}
return mInjector.securityLogGetLoggingEnabledProperty();
}
@@ -13977,15 +14014,23 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
@Override
public ParceledListSlice<SecurityEvent> retrievePreRebootSecurityLogs(ComponentName admin) {
public ParceledListSlice<SecurityEvent> retrievePreRebootSecurityLogs(ComponentName admin,
String packageName) {
if (!mHasFeature) {
return null;
}
Objects.requireNonNull(admin, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(admin);
Preconditions.checkCallAuthorization(isDeviceOwner(caller)
|| isProfileOwnerOfOrganizationOwnedDevice(caller));
final CallerIdentity caller = getCallerIdentity(admin, packageName);
if (admin != null) {
Preconditions.checkCallAuthorization(
isProfileOwnerOfOrganizationOwnedDevice(caller)
|| isDeviceOwner(caller));
} else {
// A delegate app passes a null admin component, which is expected
Preconditions.checkCallAuthorization(
isCallerDelegate(caller, DELEGATION_SECURITY_LOGGING));
}
Preconditions.checkCallAuthorization(isOrganizationOwnedDeviceWithManagedProfile()
|| areAllUsersAffiliatedWithDeviceLocked());
@@ -14015,15 +14060,22 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
@Override
public ParceledListSlice<SecurityEvent> retrieveSecurityLogs(ComponentName admin) {
public ParceledListSlice<SecurityEvent> retrieveSecurityLogs(ComponentName admin,
String packageName) {
if (!mHasFeature) {
return null;
}
Objects.requireNonNull(admin, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(admin);
Preconditions.checkCallAuthorization(isDeviceOwner(caller)
|| isProfileOwnerOfOrganizationOwnedDevice(caller));
final CallerIdentity caller = getCallerIdentity(admin, packageName);
if (admin != null) {
Preconditions.checkCallAuthorization(
isProfileOwnerOfOrganizationOwnedDevice(caller)
|| isDeviceOwner(caller));
} else {
// A delegate app passes a null admin component, which is expected
Preconditions.checkCallAuthorization(
isCallerDelegate(caller, DELEGATION_SECURITY_LOGGING));
}
Preconditions.checkCallAuthorization(isOrganizationOwnedDeviceWithManagedProfile()
|| areAllUsersAffiliatedWithDeviceLocked());