1 /* 2 * Copyright (C) 2015 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.permission2.cts; 18 19 import android.content.pm.PackageInfo; 20 import android.content.pm.PackageManager; 21 import android.content.pm.PermissionGroupInfo; 22 import android.content.pm.PermissionInfo; 23 import android.test.AndroidTestCase; 24 import android.util.ArrayMap; 25 import android.util.ArraySet; 26 import android.util.Log; 27 import android.util.Xml; 28 import org.xmlpull.v1.XmlPullParser; 29 30 import java.io.InputStream; 31 import java.lang.String; 32 import java.util.ArrayList; 33 import java.util.List; 34 import java.util.Map; 35 import java.util.Set; 36 37 /** 38 * Tests for permission policy on the platform. 39 */ 40 public class PermissionPolicyTest extends AndroidTestCase { 41 private static final String LOG_TAG = "PermissionProtectionTest"; 42 43 private static final String PLATFORM_PACKAGE_NAME = "android"; 44 45 private static final String PLATFORM_ROOT_NAMESPACE = "android."; 46 47 private static final String TAG_PERMISSION = "permission"; 48 49 private static final String ATTR_NAME = "name"; 50 private static final String ATTR_PERMISSION_GROUP = "permissionGroup"; 51 private static final String ATTR_PROTECTION_LEVEL = "protectionLevel"; 52 testPlatformPermissionPolicyUnaltered()53 public void testPlatformPermissionPolicyUnaltered() throws Exception { 54 PackageInfo platformPackage = getContext().getPackageManager() 55 .getPackageInfo(PLATFORM_PACKAGE_NAME, PackageManager.GET_PERMISSIONS); 56 Map<String, PermissionInfo> declaredPermissionsMap = new ArrayMap<>(); 57 for (PermissionInfo declaredPermission : platformPackage.permissions) { 58 declaredPermissionsMap.put(declaredPermission.name, declaredPermission); 59 } 60 61 List<PermissionGroupInfo> declaredGroups = getContext().getPackageManager() 62 .getAllPermissionGroups(0); 63 Set<String> declaredGroupsSet = new ArraySet<>(); 64 for (PermissionGroupInfo declaredGroup : declaredGroups) { 65 declaredGroupsSet.add(declaredGroup.name); 66 } 67 68 Set<String> expectedPermissionGroups = new ArraySet<String>(); 69 70 for (PermissionInfo expectedPermission : loadExpectedPermissions()) { 71 // OEMs cannot remove permissions 72 String expectedPermissionName = expectedPermission.name; 73 PermissionInfo declaredPermission = declaredPermissionsMap.get(expectedPermissionName); 74 assertNotNull("Permission " + expectedPermissionName 75 + " must be declared", declaredPermission); 76 77 // We want to end up with OEM defined permissions and groups to check their namespace 78 declaredPermissionsMap.remove(expectedPermissionName); 79 // Collect expected groups to check if OEM defined groups aren't in platform namespace 80 expectedPermissionGroups.add(expectedPermission.group); 81 82 // OEMs cannot change permission protection 83 final int expectedProtection = expectedPermission.protectionLevel 84 & PermissionInfo.PROTECTION_MASK_BASE; 85 final int declaredProtection = declaredPermission.protectionLevel 86 & PermissionInfo.PROTECTION_MASK_BASE; 87 assertEquals("Permission " + expectedPermissionName + " invalid protection level", 88 expectedProtection, declaredProtection); 89 90 // OEMs cannot change permission protection flags 91 final int expectedProtectionFlags = expectedPermission.protectionLevel 92 & PermissionInfo.PROTECTION_MASK_FLAGS; 93 final int declaredProtectionFlags = declaredPermission.protectionLevel 94 & PermissionInfo.PROTECTION_MASK_FLAGS; 95 assertEquals("Permission " + expectedPermissionName + " invalid enforced protection" 96 + " level flags", expectedProtectionFlags, declaredProtectionFlags); 97 98 // OEMs cannot change permission grouping 99 if ((declaredPermission.protectionLevel & PermissionInfo.PROTECTION_DANGEROUS) != 0) { 100 assertEquals("Permission " + expectedPermissionName + " not in correct group", 101 expectedPermission.group, declaredPermission.group); 102 assertTrue("Permission group " + expectedPermission.group + "must be defined", 103 declaredGroupsSet.contains(declaredPermission.group)); 104 } 105 } 106 107 // OEMs cannot define permissions in the platform namespace 108 for (String permission : declaredPermissionsMap.keySet()) { 109 assertFalse("Cannot define permission " + permission + " in android namespace", 110 permission.startsWith(PLATFORM_ROOT_NAMESPACE)); 111 } 112 113 // OEMs cannot define groups in the platform namespace 114 for (PermissionGroupInfo declaredGroup : declaredGroups) { 115 if (!expectedPermissionGroups.contains(declaredGroup.name)) { 116 assertFalse("Cannot define group " + declaredGroup.name + " in android namespace", 117 declaredGroup.name != null 118 && declaredGroup.packageName.equals(PLATFORM_PACKAGE_NAME) 119 && declaredGroup.name.startsWith(PLATFORM_ROOT_NAMESPACE)); 120 } 121 } 122 } 123 loadExpectedPermissions()124 private List<PermissionInfo> loadExpectedPermissions() throws Exception { 125 List<PermissionInfo> permissions = new ArrayList<>(); 126 try ( 127 InputStream in = getContext().getResources() 128 .openRawResource(android.permission2.cts.R.raw.android_manifest) 129 ) { 130 XmlPullParser parser = Xml.newPullParser(); 131 parser.setInput(in, null); 132 133 final int outerDepth = parser.getDepth(); 134 int type; 135 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 136 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 137 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 138 continue; 139 } 140 if (TAG_PERMISSION.equals(parser.getName())) { 141 PermissionInfo permissionInfo = new PermissionInfo(); 142 permissionInfo.name = parser.getAttributeValue(null, ATTR_NAME); 143 permissionInfo.group = parser.getAttributeValue(null, ATTR_PERMISSION_GROUP); 144 permissionInfo.protectionLevel = parseProtectionLevel( 145 parser.getAttributeValue(null, ATTR_PROTECTION_LEVEL)); 146 permissions.add(permissionInfo); 147 } else { 148 Log.e(LOG_TAG, "Unknown tag " + parser.getName()); 149 } 150 } 151 } 152 return permissions; 153 } 154 parseProtectionLevel(String protectionLevelString)155 private static int parseProtectionLevel(String protectionLevelString) { 156 int protectionLevel = 0; 157 String[] fragments = protectionLevelString.split("\\|"); 158 for (String fragment : fragments) { 159 switch (fragment.trim()) { 160 case "normal": { 161 protectionLevel |= PermissionInfo.PROTECTION_NORMAL; 162 } break; 163 case "dangerous": { 164 protectionLevel |= PermissionInfo.PROTECTION_DANGEROUS; 165 } break; 166 case "signature": { 167 protectionLevel |= PermissionInfo.PROTECTION_SIGNATURE; 168 } break; 169 case "signatureOrSystem": { 170 protectionLevel |= PermissionInfo.PROTECTION_SIGNATURE; 171 protectionLevel |= PermissionInfo.PROTECTION_FLAG_SYSTEM; 172 } break; 173 case "system": { 174 protectionLevel |= PermissionInfo.PROTECTION_FLAG_SYSTEM; 175 } break; 176 case "installer": { 177 protectionLevel |= PermissionInfo.PROTECTION_FLAG_INSTALLER; 178 } break; 179 case "verifier": { 180 protectionLevel |= PermissionInfo.PROTECTION_FLAG_VERIFIER; 181 } break; 182 case "preinstalled": { 183 protectionLevel |= PermissionInfo.PROTECTION_FLAG_PREINSTALLED; 184 } break; 185 case "pre23": { 186 protectionLevel |= PermissionInfo.PROTECTION_FLAG_PRE23; 187 } break; 188 case "appop": { 189 protectionLevel |= PermissionInfo.PROTECTION_FLAG_APPOP; 190 } break; 191 case "development": { 192 protectionLevel |= PermissionInfo.PROTECTION_FLAG_DEVELOPMENT; 193 } break; 194 case "privileged": { 195 protectionLevel |= PermissionInfo.PROTECTION_FLAG_PRIVILEGED; 196 } break; 197 case "setup": { 198 protectionLevel |= PermissionInfo.PROTECTION_FLAG_SETUP; 199 } break; 200 } 201 } 202 return protectionLevel; 203 } 204 } 205