summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoman Chu <jcchu@tycho.ncsc.mil>2012-11-16 16:14:37 -0500
committerRicardo Cerqueira <cyanogenmod@cerqueira.org>2013-07-18 21:02:22 +0100
commit2a091b42566d4de5fd88e6e58f29f9b7feadc0b7 (patch)
treeec4f4e3a1a8c39a2ce34df38a2033f92d5720eba
parentb00a063e976fe2f97a3297b769310fc70ca4f699 (diff)
downloadframeworks_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
-rw-r--r--core/java/android/app/admin/DeviceAdminInfo.java16
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java155
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl6
-rw-r--r--core/res/res/values/strings.xml4
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--services/java/com/android/server/DevicePolicyManagerService.java278
6 files changed, 457 insertions, 4 deletions
diff --git a/core/java/android/app/admin/DeviceAdminInfo.java b/core/java/android/app/admin/DeviceAdminInfo.java
index 85031cc..3ea4c7f 100644
--- a/core/java/android/app/admin/DeviceAdminInfo.java
+++ b/core/java/android/app/admin/DeviceAdminInfo.java
@@ -155,6 +155,16 @@ public final class DeviceAdminInfo implements Parcelable {
*/
public static final int USES_POLICY_ENFORCE_SELINUX = 10;
+ /**
+ * @hide
+ * A type of policy that this device admin can use: enforce SE Android MMAC policy.
+ *
+ * <p>To control this policy, the device admin must have a "enforce-mmac" tag in the
+ * "uses-policies" section of its meta-data.
+ */
+ public static final int USES_POLICY_ENFORCE_MMAC = 11;
+
+
/** @hide */
public static class PolicyInfo {
public final int ident;
@@ -209,6 +219,9 @@ public final class DeviceAdminInfo implements Parcelable {
sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_ENFORCE_SELINUX, "enforce-selinux",
com.android.internal.R.string.policylab_enforceSelinux,
com.android.internal.R.string.policydesc_enforceSelinux));
+ sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_ENFORCE_MMAC, "enforce-mmac",
+ com.android.internal.R.string.policylab_enforceMmac,
+ com.android.internal.R.string.policydesc_enforceMmac));
for (int i=0; i<sPoliciesDisplayOrder.size(); i++) {
PolicyInfo pi = sPoliciesDisplayOrder.get(i);
@@ -401,7 +414,8 @@ public final class DeviceAdminInfo implements Parcelable {
* {@link #USES_POLICY_RESET_PASSWORD}, {@link #USES_POLICY_FORCE_LOCK},
* {@link #USES_POLICY_WIPE_DATA},
* {@link #USES_POLICY_EXPIRE_PASSWORD}, {@link #USES_ENCRYPTED_STORAGE},
- * {@link #USES_POLICY_DISABLE_CAMERA}, {@link #USES_POLICY_ENFORCE_SELINUX}.
+ * {@link #USES_POLICY_DISABLE_CAMERA}, {@link #USES_POLICY_ENFORCE_SELINUX},
+ * {@link #USES_POLICY_ENFORCE_MMAC}.
*/
public boolean usesPolicy(int policyIdent) {
return (mUsesPolicies & (1<<policyIdent)) != 0;
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index b0fe60b..fb186a6 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1640,6 +1640,134 @@ public class DevicePolicyManager {
return false;
}
+ /**
+ * Checks whether an admin app has control over SE Android MMAC policy.
+ *
+ * <p>The calling device admin must have requested
+ * {@link DeviceAdminInfo#USES_POLICY_ENFORCE_MMAC} to be able to call
+ * this method; if it has not, a security exception will be thrown.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated,
+ * must be self
+ * @return true if admin app can control MMAC policy, false otherwise
+ * @hide
+ */
+ public boolean isMMACadmin(ComponentName admin) {
+ return isMMACadmin(admin, UserHandle.myUserId());
+ }
+
+ /** @hide per-user version */
+ public boolean isMMACadmin(ComponentName admin, int userHandle) {
+ if (mService != null) {
+ try {
+ return mService.isMMACadmin(admin, userHandle);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy server", e);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Called by an application that is administering the device to start or stop
+ * controlling SE Android MMAC policies, enforcement, etc. When an admin
+ * app gives up control of MMAC policies, the policy in place prior to the app
+ * taking control will be applied.
+ *
+ * <p>The calling device admin must have requested
+ * {@link DeviceAdminInfo#USES_POLICY_ENFORCE_MMAC} to be able to call
+ * this method; if it has not, a security exception will be thrown.
+ *
+ * <p>When an application gains control of MMAC settings, it is called an
+ * MMAC administrator. Admistration applications will call this with true and
+ * ensure this method returned true before attempting to toggle MMAC settings.
+ * When apps intend to stop controlling MMAC settings, apps should call this
+ * with false.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated,
+ * must be self
+ * @param control true if the admin wishes to control MMAC, false if the admin
+ * wishes to give back control of MMAC
+ * @return true if the operation succeeded, false if the operation failed or
+ * MMAC was not enabled on the device.
+ * @hide
+ */
+ public boolean setMMACadmin(ComponentName admin, boolean control) {
+ return setMMACadmin(admin, control, UserHandle.myUserId());
+ }
+
+ /** @hide per-user version */
+ public boolean setMMACadmin(ComponentName admin, boolean control, int userHandle) {
+ if (mService != null) {
+ try {
+ return mService.setMMACadmin(admin, control, userHandle);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy server", e);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Called by an application that is a SEAndroid MMAC admin to set MMAC
+ * protections into enforcing or permissive mode. The system requires a
+ * reboot for the protections to take effect.
+ *
+ * <p>The calling device admin must have requested
+ * {@link DeviceAdminInfo#USES_POLICY_ENFORCE_MMAC} to be able to call
+ * this method; if it has not, a security exception will be thrown.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param enforcing true for enforcing mode, false for permissive mode.
+ * @return false if Android was unable to set the desired mode
+ * @hide
+ */
+ public boolean setMMACenforcing(ComponentName admin, boolean enforcing) {
+ return setMMACenforcing(admin, enforcing, UserHandle.myUserId());
+ }
+
+ /** @hide per-user version */
+ public boolean setMMACenforcing(ComponentName admin, boolean enforcing, int userHandle) {
+ if (mService != null) {
+ try {
+ return mService.setMMACenforcing(admin, enforcing, userHandle);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy server", e);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Determine whether SE Android MMAC policies are being enforced by the
+ * current admin.
+ *
+ * <p>The calling device admin must have requested
+ * {@link DeviceAdminInfo#USES_POLICY_ENFORCE_MMAC} to be able to call
+ * this method; if it has not, a security exception will be thrown.
+ *
+ * <p>The returned value is only meaningful if the current admin is a
+ * MMAC admin.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @hide
+ */
+ public boolean getMMACenforcing(ComponentName admin) {
+ return getMMACenforcing(admin, UserHandle.myUserId());
+ }
+
+ /** @hide per-user version */
+ public boolean getMMACenforcing(ComponentName admin, int userHandle) {
+ if (mService != null) {
+ try {
+ return mService.getMMACenforcing(admin, userHandle);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy server", e);
+ }
+ }
+ return false;
+ }
+
// Before changing these values, be sure to update
// DevicePolicyManagerService.java's POLICY_DESCRIPTIONS array.
/** @hide */
@@ -1651,7 +1779,9 @@ public class DevicePolicyManager {
/** @hide */
public static final int SEPOLICY_FILE_SEAPPCTXS = 3;
/** @hide */
- public static final int SEPOLICY_FILE_COUNT = SEPOLICY_FILE_SEAPPCTXS+1;
+ public static final int MMAC_POLICY_FILE = 4;
+ /** @hide */
+ public static final int SEPOLICY_FILE_COUNT = MMAC_POLICY_FILE+1;
/**
* Sets a new policy file and reloads it at the proper time.
@@ -1671,9 +1801,20 @@ public class DevicePolicyManager {
* returned value is only meaingful if the current admin is a SELinux
* admin.
*
+ * <p>For {@link #MMAC_POLICY_FILE}, the admin must have requested
+ * {@link DeviceAdminInfo#USES_POLICY_ENFORCE_MMAC} before calling this
+ * method. If it has not, a security exception will be thrown.
+ *
+ * <p>For {@link #MMAC_POLICY_FILE}, the MMAC policy file is reloaded on
+ * reboot.
+ *
+ * <p>For {@link #MMAC_POLICY_FILE}, the returned value is only meaingful
+ * if the current admin is a MMAC admin.
+ *
* @param admin which {@link DeviceAdminReceiver} this request is associated with
* @param policyType one of {@link #SEPOLICY_FILE_SEPOLICY}, {@link #SEPOLICY_FILE_PROPCTXS},
- * {@link #SEPOLICY_FILE_FILECTXS}, or {@link #SEPOLICY_FILE_SEAPPCTXS}
+ * {@link #SEPOLICY_FILE_FILECTXS}, {@link #SEPOLICY_FILE_SEAPPCTXS},
+ * or {@link #MMAC_POLICY_FILE}.
* @param policy the new policy file in bytes, or null if you wish to revert to
* the default policy
* @return false if Android was unable to set the new policy
@@ -1709,9 +1850,17 @@ public class DevicePolicyManager {
* returned value is only meaingful if the current admin is a SELinux
* admin.
*
+ * <p>For {@link #MMAC_POLICY_FILE}, the admin must have requested
+ * {@link DeviceAdminInfo#USES_POLICY_ENFORCE_MMAC} before calling this
+ * method. If it has not, a security exception will be thrown.
+ *
+ * <p>For {@link #MMAC_POLICY_FILE}, the returned value is only meaingful
+ * if the current admin is a MMAC admin.
+ *
* @param admin which {@link DeviceAdminReceiver} this request is associated with
* @param policyType one of {@link #SEPOLICY_FILE_SEPOLICY}, {@link #SEPOLICY_FILE_PROPCTXS},
- * {@link #SEPOLICY_FILE_FILECTXS}, or {@link #SEPOLICY_FILE_SEAPPCTXS}
+ * {@link #SEPOLICY_FILE_FILECTXS}, {@link #SEPOLICY_FILE_SEAPPCTXS}, or
+ * {@link #MMAC_POLICY_FILE}
* @return true if the admin set a custom policy file
* @hide
*/
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 3e998fd..5a04604 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -103,6 +103,12 @@ interface IDevicePolicyManager {
boolean getSELinuxBooleanValue(in ComponentName who, String name, int userHandle);
boolean setSELinuxBooleanValue(in ComponentName who, String name, boolean value, int userHandle);
+ boolean isMMACadmin(in ComponentName who, int userHandle);
+ boolean setMMACadmin(in ComponentName who, boolean control, int userHandle);
+
+ boolean setMMACenforcing(in ComponentName who, boolean enforcing, int userHandle);
+ boolean getMMACenforcing(in ComponentName who, int userHandle);
+
boolean setCustomPolicyFile(in ComponentName who, int policyType, in byte[] policy, int userHandle);
boolean isCustomPolicyFile(in ComponentName who, int policyType, int userHandle);
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index f67e9b2..d71a24a 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1824,6 +1824,10 @@
<string name="policylab_enforceSelinux">Enforce SELinux</string>
<!-- Description of policy access to start enforcing SELinux policy [CHAR LIMIT=110]-->
<string name="policydesc_enforceSelinux">Toggle SELinux policy enforcing or permissive mode.</string>
+ <!-- Title of policy access to start enforcing SE Android MMAC policy [CHAR LIMIT=30]-->
+ <string name="policylab_enforceMmac">Enforce SE Android MMAC</string>
+ <!-- Description of policy access to start enforcing SE Android MMAC policy [CHAR LIMIT=110]-->
+ <string name="policydesc_enforceMmac">Toggle SE Android MMAC policy enforcing or permissive mode.</string>
<!-- The order of these is important, don't reorder without changing Contacts.java --> <skip />
<!-- Phone number types from android.provider.Contacts. This could be used when adding a new phone number for a contact, for example. -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 06f9acb..ef66ddd 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -865,6 +865,8 @@
<java-symbol type="string" name="owner_name" />
<java-symbol type="string" name="policylab_enforceSelinux" />
<java-symbol type="string" name="policydesc_enforceSelinux" />
+ <java-symbol type="string" name="policylab_enforceMmac" />
+ <java-symbol type="string" name="policydesc_enforceMmac" />
<java-symbol type="plurals" name="abbrev_in_num_days" />
<java-symbol type="plurals" name="abbrev_in_num_hours" />
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);