diff options
author | Joman Chu <jcchu@tycho.ncsc.mil> | 2012-11-16 16:14:37 -0500 |
---|---|---|
committer | Ricardo Cerqueira <cyanogenmod@cerqueira.org> | 2013-07-18 21:02:22 +0100 |
commit | 2a091b42566d4de5fd88e6e58f29f9b7feadc0b7 (patch) | |
tree | ec4f4e3a1a8c39a2ce34df38a2033f92d5720eba /services | |
parent | b00a063e976fe2f97a3297b769310fc70ca4f699 (diff) | |
download | frameworks_base-2a091b42566d4de5fd88e6e58f29f9b7feadc0b7.zip frameworks_base-2a091b42566d4de5fd88e6e58f29f9b7feadc0b7.tar.gz frameworks_base-2a091b42566d4de5fd88e6e58f29f9b7feadc0b7.tar.bz2 |
Implement Device Admin API for MMAC
Conflicts:
api/current.txt
core/java/android/app/admin/DevicePolicyManager.java
Change-Id: I1df507ced67fbcab8fdcde9cce78705b5e54e346
Diffstat (limited to 'services')
-rw-r--r-- | services/java/com/android/server/DevicePolicyManagerService.java | 278 |
1 files changed, 278 insertions, 0 deletions
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java index a8c5221..e5c7337 100644 --- a/services/java/com/android/server/DevicePolicyManagerService.java +++ b/services/java/com/android/server/DevicePolicyManagerService.java @@ -149,6 +149,19 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { // No device admin controls SELinux return null; } + + /** Return the admin that controls SE Android MMAC, or null if there is none. */ + ActiveAdmin findMMACadminLocked() { + //Uses very similar code to the SELinux version + final int N = mAdminList.size(); + for (int i = 0; i < N; ++i) { + ActiveAdmin ap = mAdminList.get(i); + if (ap.isMMACadmin) { + return ap; + } + } + return null; + } } final SparseArray<DevicePolicyData> mUserData = new SparseArray<DevicePolicyData>(); @@ -228,6 +241,23 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } + private static class MMACpolicyDescription extends PolicyFileDescription { + MMACpolicyDescription(String path) { + super(path, DeviceAdminInfo.USES_POLICY_ENFORCE_MMAC); + } + + @Override + boolean isPolicyAdmin(ActiveAdmin admin) { + return admin.isMMACadmin; + } + + @Override + boolean doPolicyReload() { + //policy is reloaded on reboot + return true; + } + } + private static final String SEPOLICY_PATH_SEPOLICY = "/data/system/sepolicy"; private static final String SEPOLICY_PATH_PROPCTXS = "/data/system/property_contexts"; @@ -236,6 +266,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { private static final String SEPOLICY_PATH_SEAPPCTXS = "/data/system/seapp_contexts"; + private static final String MMAC_POLICY_PATH = "/data/system/mac_permissions.xml"; + private static final PolicyFileDescription[] POLICY_DESCRIPTIONS = { // 0 = SEPOLICY_FILE_SEPOLICY new SELinuxPolicyDescription(SEPOLICY_PATH_SEPOLICY), @@ -245,6 +277,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { new SELinuxPolicyDescription(SEPOLICY_PATH_FILECTXS), // 3 = SEPOLICY_FILE_SEAPPCTXS new SELinuxPolicyDescription(SEPOLICY_PATH_SEAPPCTXS), + // 4 = MMAC_POLICY_FILE + new MMACpolicyDescription(MMAC_POLICY_PATH), }; static class ActiveAdmin { @@ -303,6 +337,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { boolean enforceSELinux = false; Map<String, Boolean> sebools = null; + boolean isMMACadmin = false; + boolean enforceMMAC = false; + boolean[] isCustomPolicyFile = new boolean[DevicePolicyManager.SEPOLICY_FILE_COUNT]; ActiveAdmin(DeviceAdminInfo _info) { @@ -463,6 +500,22 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { out.endTag(null, "selinux-seappctxs"); } } + if (isMMACadmin) { + out.startTag(null, "mmac-admin"); + out.attribute(null, "value", Boolean.toString(isMMACadmin)); + out.endTag(null, "mmac-admin"); + if (enforceMMAC) { + out.startTag(null, "enforce-mmac"); + out.attribute(null, "value", Boolean.toString(enforceMMAC)); + out.endTag(null, "enforce-mmac"); + } + boolean isCustomMMAC = isCustomPolicyFile[DevicePolicyManager.MMAC_POLICY_FILE]; + if (isCustomMMAC) { + out.startTag(null, "mmac-macperms"); + out.attribute(null, "value", Boolean.toString(isCustomMMAC)); + out.endTag(null, "mmac-macperms"); + } + } } void readFromXml(XmlPullParser parser) @@ -560,6 +613,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } else if ("selinux-seappctxs".equals(tag)) { this.isCustomPolicyFile[DevicePolicyManager.SEPOLICY_FILE_SEAPPCTXS] = Boolean.parseBoolean(parser.getAttributeValue(null, "value")); + } else if ("mmac-admin".equals(tag)) { + isMMACadmin = Boolean.parseBoolean( + parser.getAttributeValue(null, "value")); + } else if ("enforce-mmac".equals(tag)) { + enforceMMAC = Boolean.parseBoolean( + parser.getAttributeValue(null, "value")); + } else if ("mmac-macperms".equals(tag)) { + this.isCustomPolicyFile[DevicePolicyManager.MMAC_POLICY_FILE] = + Boolean.parseBoolean(parser.getAttributeValue(null, "value")); } else { Slog.w(TAG, "Unknown admin tag: " + tag); } @@ -632,6 +694,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { pw.println(isCustomPolicyFile[DevicePolicyManager.SEPOLICY_FILE_FILECTXS]); pw.print(prefix); pw.print("customSEappContexts="); pw.println(isCustomPolicyFile[DevicePolicyManager.SEPOLICY_FILE_SEAPPCTXS]); + pw.print(prefix); pw.print("isMMACadmin="); + pw.println(isMMACadmin); + pw.print(prefix); pw.print("enforceMMAC="); + pw.println(enforceMMAC); + pw.print(prefix); pw.print("customMMACpolicy="); + pw.println(isCustomPolicyFile[DevicePolicyManager.MMAC_POLICY_FILE]); + } } @@ -859,6 +928,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { boolean doProxyCleanup = admin.info.usesPolicy( DeviceAdminInfo.USES_POLICY_SETS_GLOBAL_PROXY); boolean doSELinuxCleanup = admin.isSELinuxAdmin; + boolean doMMACcleanup = admin.isMMACadmin; policy.mAdminList.remove(admin); policy.mAdminMap.remove(adminReceiver); validatePasswordOwnerLocked(policy); @@ -873,6 +943,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { admin.isCustomPolicyFile[DevicePolicyManager.SEPOLICY_FILE_FILECTXS], admin.isCustomPolicyFile[DevicePolicyManager.SEPOLICY_FILE_SEAPPCTXS]); } + if (doMMACcleanup) { + syncMMACpolicyLocked(policy, admin.isCustomPolicyFile[DevicePolicyManager.MMAC_POLICY_FILE]); + } saveSettingsLocked(userHandle); updateMaximumTimeToLockLocked(policy); } @@ -1113,6 +1186,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { syncDeviceCapabilitiesLocked(policy); updateMaximumTimeToLockLocked(policy); syncSELinuxPolicyLocked(policy, false); + syncMMACpolicyLocked(policy, false); } static void validateQualityConstant(int quality) { @@ -2920,6 +2994,210 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } + // Possible MMAC Admin API states: + // 1: Caller has ENFORCE_MMAC = {T,F} + // 2: Caller is a MMAC admin = {T,F} + // 3: There is a MMAC admin on the system = {T,F} + // Invariants: + // a) 1=F -> 2=F + // b) 3=F -> 2=F for all admin apps + // States: + // TTT, TTF, TFT, TFF, FTT, FTF, FFT, FFF + // TTT, TFT, TFF, FFT, FFF + // TTF fails b, + // FTT fails a + // FTF fails a,b + + /** + * This system property is used to share the state of the MAC enforcing mode. + * SE Android MAC protection layer is expected to read this property and act accordingly. + */ + public static final String SYSTEM_PROP_ENFORCE_MAC = "persist.mac_enforcing_mode"; + + /** + * Sync's the current MMAC admin's policies to the device. If there is + * no MMAC admin, then this will set MMAC to permissive mode + * and may remove the {@link MMAC_POLICY_PATH} file. + * @return true if policies were synced successfully + */ + private boolean syncMMACpolicyLocked(DevicePolicyData policy, + boolean removePolicy) { + if (policy.mUserHandle == UserHandle.USER_OWNER) { + ActiveAdmin mmacAdmin = policy.findMMACadminLocked(); + if (mmacAdmin == null) { + // No admin, so create a fake one and restore it. + mmacAdmin = new ActiveAdmin(null); + mmacAdmin.enforceMMAC = false; + } + + boolean systemState = SystemProperties.getBoolean(SYSTEM_PROP_ENFORCE_MAC, false); + boolean enforceMMAC = mmacAdmin.enforceMMAC; + if (systemState != enforceMMAC) { + Slog.v(TAG, SYSTEM_PROP_ENFORCE_MAC + " was " + systemState + ", to be set to " + enforceMMAC); + String value = enforceMMAC ? "1" : "0"; + SystemProperties.set(SYSTEM_PROP_ENFORCE_MAC, value); + } + + if (removePolicy) { + boolean ret = true; + File polFile; + polFile = new File(MMAC_POLICY_PATH); + if (polFile.exists() && !polFile.delete()) { + ret = false; + } + return ret; + + } else { //Not removing any policy files + return true; + } + + } else { //User is not owner + return false; + } + } + + // Cases = 8 + @Override + public boolean isMMACadmin(ComponentName who, int userHandle) { + //Uses very similar code to the SELinux version + enforceCrossUserPermission(userHandle); + synchronized (this) { + // Check for permissions + if (who == null) { + throw new NullPointerException("ComponentName is null"); + } + // Only owner can set MMAC settings + if (userHandle != UserHandle.USER_OWNER + || UserHandle.getCallingUserId() != UserHandle.USER_OWNER) { + Slog.w(TAG, "Only owner is allowed to set MMAC settings. User " + + UserHandle.getCallingUserId() + " is not permitted."); + return false; + } + // Case F** = 4 + ActiveAdmin admin = getActiveAdminForCallerLocked(who, + DeviceAdminInfo.USES_POLICY_ENFORCE_MMAC); + // Case T** = 4 + return admin.isMMACadmin; + } + } + + // Cases = 16 + @Override + public boolean setMMACadmin(ComponentName who, boolean control, int userHandle) { + //Uses very similar code to the SELinux version + enforceCrossUserPermission(userHandle); + synchronized (this) { + // Check for permissions + if (who == null) { + throw new NullPointerException("ComponentName is null"); + } + // Only owner can set MMAC settings + if (userHandle != UserHandle.USER_OWNER + || UserHandle.getCallingUserId() != UserHandle.USER_OWNER) { + Slog.w(TAG, "Only owner is allowed to set MMAC settings. User " + + UserHandle.getCallingUserId() + " is not permitted."); + return false; + } + // Case F**(*) = 8 + ActiveAdmin admin = getActiveAdminForCallerLocked(who, + DeviceAdminInfo.USES_POLICY_ENFORCE_MMAC); + + // Case TT*(T) = 2 + // Case TF*(F) = 2 + if (admin.isMMACadmin == control) { + return true; + } + + DevicePolicyData policy = getUserData(userHandle); + ActiveAdmin curAdmin = policy.findMMACadminLocked(); + + // Case TFF(T) = 1 + if (control && curAdmin == null) { + Slog.v(TAG, "SE Android MMAC admin set to " + admin.info.getComponent()); + admin.isMMACadmin = true; + saveSettingsLocked(userHandle); + return true; + } + + // Case TTT(F) = 1 + if (!control && curAdmin.equals(admin)) { + boolean setMMACpolicyFile = admin.isCustomPolicyFile[DevicePolicyManager.MMAC_POLICY_FILE]; + Slog.v(TAG, admin.info.getComponent() + " is no longer a SE Android MMAC admin"); + + admin.isMMACadmin = false; + admin.enforceMMAC = false; + admin.isCustomPolicyFile[DevicePolicyManager.MMAC_POLICY_FILE] = false; + + saveSettingsLocked(userHandle); + syncMMACpolicyLocked(policy, setMMACpolicyFile); + return true; + } + } + + // Case TTF(F) = 1 + // Case TFT(T) = 1 + return false; + } + + @Override + public boolean getMMACenforcing(ComponentName who, int userHandle) { + //Uses very similar code to the SELinux version + enforceCrossUserPermission(userHandle); + synchronized (this) { + // Check for permissions + if (who == null) { + throw new NullPointerException("ComponentName is null"); + } + // Only owner can set MMAC settings + if (userHandle != UserHandle.USER_OWNER + || UserHandle.getCallingUserId() != UserHandle.USER_OWNER) { + Slog.w(TAG, "Only owner is allowed to set MMAC settings. User " + + UserHandle.getCallingUserId() + " is not permitted."); + return false; + } + // Case: F** = 4 + ActiveAdmin admin = getActiveAdminForCallerLocked(who, + DeviceAdminInfo.USES_POLICY_ENFORCE_MMAC); + // Case: T** = 4 + return admin.isMMACadmin && admin.enforceMMAC; + } + } + + @Override + public boolean setMMACenforcing(ComponentName who, boolean enforcing, int userHandle) { + //Uses very similar code to the SELinux version + enforceCrossUserPermission(userHandle); + synchronized (this) { + // Check for permissions + if (who == null) { + throw new NullPointerException("ComponentName is null"); + } + // Only owner can set MMAC settings + if (userHandle != UserHandle.USER_OWNER + || UserHandle.getCallingUserId() != UserHandle.USER_OWNER) { + Slog.w(TAG, "Only owner is allowed to set MMAC settings. User " + + UserHandle.getCallingUserId() + " is not permitted."); + return false; + } + // Case F**(*) = 8 + ActiveAdmin admin = getActiveAdminForCallerLocked(who, + DeviceAdminInfo.USES_POLICY_ENFORCE_MMAC); + + // Case TF*(*) = 4 + if (!admin.isMMACadmin) { + return false; + } + + // Case TT*(*) = 4 + if (admin.enforceMMAC != enforcing) { + admin.enforceMMAC = enforcing; + saveSettingsLocked(userHandle); + } + DevicePolicyData policy = getUserData(userHandle); + return syncMMACpolicyLocked(policy, false); + } + } + @Override public boolean isCustomPolicyFile(ComponentName who, int policyType, int userHandle) { enforceCrossUserPermission(userHandle); |