• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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