1 /* 2 * Copyright (C) 2022 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 com.android.server.devicepolicy; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.app.admin.Authority; 22 import android.app.admin.DeviceAdminAuthority; 23 import android.app.admin.DpcAuthority; 24 import android.app.admin.RoleAuthority; 25 import android.app.admin.UnknownAuthority; 26 import android.content.ComponentName; 27 import android.os.UserHandle; 28 29 import com.android.modules.utils.TypedXmlPullParser; 30 import com.android.modules.utils.TypedXmlSerializer; 31 import com.android.role.RoleManagerLocal; 32 import com.android.server.LocalManagerRegistry; 33 import com.android.server.utils.Slogf; 34 35 import org.xmlpull.v1.XmlPullParserException; 36 37 import java.io.IOException; 38 import java.util.HashSet; 39 import java.util.Map; 40 import java.util.Objects; 41 import java.util.Set; 42 43 /** 44 * {@code EnforcingAdmins} can have the following authority types: 45 * 46 * <ul> 47 * <li> {@link #DPC_AUTHORITY} meaning it's an enterprise admin (e.g. PO, DO, COPE) 48 * <li> {@link #DEVICE_ADMIN_AUTHORITY} which is a legacy non enterprise admin 49 * <li> Or a role authority, in which case {@link #mAuthorities} contains a list of all roles 50 * held by the given {@code packageName} 51 * </ul> 52 * 53 */ 54 final class EnforcingAdmin { 55 56 static final String TAG = "EnforcingAdmin"; 57 58 static final String ROLE_AUTHORITY_PREFIX = "role:"; 59 static final String SYSTEM_AUTHORITY_PREFIX = "system:"; 60 static final String DPC_AUTHORITY = "enterprise"; 61 static final String DEVICE_ADMIN_AUTHORITY = "device_admin"; 62 static final String DEFAULT_AUTHORITY = "default"; 63 64 private static final String ATTR_PACKAGE_NAME = "package-name"; 65 private static final String ATTR_SYSTEM_ENTITY = "system-entity"; 66 private static final String ATTR_CLASS_NAME = "class-name"; 67 private static final String ATTR_AUTHORITIES = "authorities"; 68 private static final String ATTR_AUTHORITIES_SEPARATOR = ";"; 69 private static final String ATTR_USER_ID = "user-id"; 70 private static final String ATTR_IS_ROLE = "is-role"; 71 private static final String ATTR_IS_SYSTEM = "is-system"; 72 73 private final String mPackageName; 74 // Name of the system entity. Only used when mIsSystemAuthority is true. 75 private final String mSystemEntity; 76 // This is needed for DPCs and active admins 77 private final ComponentName mComponentName; 78 private Set<String> mAuthorities; 79 private final int mUserId; 80 private final boolean mIsRoleAuthority; 81 private final boolean mIsSystemAuthority; 82 createEnforcingAdmin(@onNull String packageName, int userId)83 static EnforcingAdmin createEnforcingAdmin(@NonNull String packageName, int userId) { 84 Objects.requireNonNull(packageName); 85 return new EnforcingAdmin(packageName, userId); 86 } 87 createEnterpriseEnforcingAdmin( @onNull ComponentName componentName, int userId)88 static EnforcingAdmin createEnterpriseEnforcingAdmin( 89 @NonNull ComponentName componentName, int userId) { 90 Objects.requireNonNull(componentName); 91 return new EnforcingAdmin( 92 componentName.getPackageName(), componentName, Set.of(DPC_AUTHORITY), userId); 93 } 94 createDeviceAdminEnforcingAdmin(ComponentName componentName, int userId)95 static EnforcingAdmin createDeviceAdminEnforcingAdmin(ComponentName componentName, int userId) { 96 Objects.requireNonNull(componentName); 97 return new EnforcingAdmin( 98 componentName.getPackageName(), componentName, Set.of(DEVICE_ADMIN_AUTHORITY), 99 userId); 100 } 101 createSystemEnforcingAdmin(@onNull String systemEntity)102 static EnforcingAdmin createSystemEnforcingAdmin(@NonNull String systemEntity) { 103 Objects.requireNonNull(systemEntity); 104 return new EnforcingAdmin(systemEntity); 105 } 106 createEnforcingAdmin(android.app.admin.EnforcingAdmin admin)107 static EnforcingAdmin createEnforcingAdmin(android.app.admin.EnforcingAdmin admin) { 108 Objects.requireNonNull(admin); 109 Authority authority = admin.getAuthority(); 110 Set<String> internalAuthorities = new HashSet<>(); 111 if (DpcAuthority.DPC_AUTHORITY.equals(authority)) { 112 return new EnforcingAdmin( 113 admin.getPackageName(), admin.getComponentName(), 114 Set.of(DPC_AUTHORITY), admin.getUserHandle().getIdentifier()); 115 } else if (DeviceAdminAuthority.DEVICE_ADMIN_AUTHORITY.equals(authority)) { 116 return new EnforcingAdmin( 117 admin.getPackageName(), admin.getComponentName(), 118 Set.of(DEVICE_ADMIN_AUTHORITY), admin.getUserHandle().getIdentifier()); 119 } else if (authority instanceof RoleAuthority roleAuthority) { 120 return new EnforcingAdmin( 121 admin.getPackageName(), admin.getComponentName(), 122 Set.of(DEVICE_ADMIN_AUTHORITY), admin.getUserHandle().getIdentifier(), 123 /* isRoleAuthority = */ true); 124 } 125 // TODO(b/324899199): Consider supporting android.app.admin.SystemAuthority. 126 return new EnforcingAdmin(admin.getPackageName(), admin.getComponentName(), 127 Set.of(), admin.getUserHandle().getIdentifier()); 128 } 129 getRoleAuthorityOf(String roleName)130 static String getRoleAuthorityOf(String roleName) { 131 return ROLE_AUTHORITY_PREFIX + roleName; 132 } 133 getParcelableAuthority(String authority)134 static Authority getParcelableAuthority(String authority) { 135 if (authority == null || authority.isEmpty()) { 136 return UnknownAuthority.UNKNOWN_AUTHORITY; 137 } 138 if (DPC_AUTHORITY.equals(authority)) { 139 return DpcAuthority.DPC_AUTHORITY; 140 } 141 if (DEVICE_ADMIN_AUTHORITY.equals(authority)) { 142 return DeviceAdminAuthority.DEVICE_ADMIN_AUTHORITY; 143 } 144 if (authority.startsWith(ROLE_AUTHORITY_PREFIX)) { 145 String role = authority.substring(ROLE_AUTHORITY_PREFIX.length()); 146 return new RoleAuthority(Set.of(role)); 147 } 148 return UnknownAuthority.UNKNOWN_AUTHORITY; 149 } 150 EnforcingAdmin( String packageName, @Nullable ComponentName componentName, Set<String> authorities, int userId)151 private EnforcingAdmin( 152 String packageName, @Nullable ComponentName componentName, Set<String> authorities, 153 int userId) { 154 Objects.requireNonNull(packageName); 155 Objects.requireNonNull(authorities); 156 157 // Role/System authorities should not be using this constructor 158 mIsRoleAuthority = false; 159 mIsSystemAuthority = false; 160 mPackageName = packageName; 161 mSystemEntity = null; 162 mComponentName = componentName; 163 mAuthorities = new HashSet<>(authorities); 164 mUserId = userId; 165 } 166 EnforcingAdmin(String packageName, int userId)167 private EnforcingAdmin(String packageName, int userId) { 168 Objects.requireNonNull(packageName); 169 170 // Only role authorities use this constructor. 171 mIsRoleAuthority = true; 172 mIsSystemAuthority = false; 173 mPackageName = packageName; 174 mSystemEntity = null; 175 mUserId = userId; 176 mComponentName = null; 177 // authorities will be loaded when needed 178 mAuthorities = null; 179 } 180 181 /** Constructor for System authorities. */ EnforcingAdmin(@onNull String systemEntity)182 private EnforcingAdmin(@NonNull String systemEntity) { 183 Objects.requireNonNull(systemEntity); 184 185 // Only system authorities use this constructor. 186 mIsSystemAuthority = true; 187 mIsRoleAuthority = false; 188 // Package name is not used for a system enforcing admin, so an empty string is fine. 189 mPackageName = ""; 190 mSystemEntity = systemEntity; 191 mUserId = UserHandle.USER_SYSTEM; 192 mComponentName = null; 193 mAuthorities = getSystemAuthority(systemEntity); 194 } 195 EnforcingAdmin( String packageName, @Nullable ComponentName componentName, Set<String> authorities, int userId, boolean isRoleAuthority)196 private EnforcingAdmin( 197 String packageName, @Nullable ComponentName componentName, Set<String> authorities, 198 int userId, boolean isRoleAuthority) { 199 Objects.requireNonNull(packageName); 200 Objects.requireNonNull(authorities); 201 202 mIsRoleAuthority = isRoleAuthority; 203 mIsSystemAuthority = false; 204 mPackageName = packageName; 205 mSystemEntity = null; 206 mComponentName = componentName; 207 mAuthorities = new HashSet<>(authorities); 208 mUserId = userId; 209 } 210 getRoleAuthoritiesOrDefault(String packageName, int userId)211 private static Set<String> getRoleAuthoritiesOrDefault(String packageName, int userId) { 212 Set<String> roles = getRoles(packageName, userId); 213 Set<String> authorities = new HashSet<>(); 214 for (String role : roles) { 215 authorities.add(ROLE_AUTHORITY_PREFIX + role); 216 } 217 return authorities.isEmpty() ? Set.of(DEFAULT_AUTHORITY) : authorities; 218 } 219 220 /** 221 * Returns a set of authorities for system authority. 222 * 223 * <p>Note that a system authority enforcing admin has only one authority that has the package 224 * name of the calling system service. Therefore, the returned set always contains one element. 225 */ getSystemAuthority(String systemEntity)226 private static Set<String> getSystemAuthority(String systemEntity) { 227 Set<String> authorities = new HashSet<>(); 228 authorities.add(SYSTEM_AUTHORITY_PREFIX + systemEntity); 229 return authorities; 230 } 231 232 // TODO(b/259042794): move this logic to RoleManagerLocal getRoles(String packageName, int userId)233 private static Set<String> getRoles(String packageName, int userId) { 234 RoleManagerLocal roleManagerLocal = LocalManagerRegistry.getManager( 235 RoleManagerLocal.class); 236 Set<String> roles = new HashSet<>(); 237 Map<String, Set<String>> rolesAndHolders = roleManagerLocal.getRolesAndHolders(userId); 238 for (String role : rolesAndHolders.keySet()) { 239 if (rolesAndHolders.get(role).contains(packageName)) { 240 roles.add(role); 241 } 242 } 243 return roles; 244 } 245 getAuthorities()246 private Set<String> getAuthorities() { 247 if (mAuthorities == null && mIsRoleAuthority) { 248 mAuthorities = getRoleAuthoritiesOrDefault(mPackageName, mUserId); 249 } 250 return mAuthorities; 251 } 252 reloadRoleAuthorities()253 void reloadRoleAuthorities() { 254 if (mIsRoleAuthority) { 255 mAuthorities = getRoleAuthoritiesOrDefault(mPackageName, mUserId); 256 } 257 } 258 hasAuthority(String authority)259 boolean hasAuthority(String authority) { 260 return getAuthorities().contains(authority); 261 } 262 isSystemAuthority()263 boolean isSystemAuthority() { 264 return mIsSystemAuthority; 265 } 266 267 @NonNull getPackageName()268 String getPackageName() { 269 return mPackageName; 270 } 271 getUserId()272 int getUserId() { 273 return mUserId; 274 } 275 276 @Nullable getComponentName()277 ComponentName getComponentName() { 278 return mComponentName; 279 } 280 281 @NonNull getParcelableAdmin()282 android.app.admin.EnforcingAdmin getParcelableAdmin() { 283 Authority authority; 284 if (mIsRoleAuthority) { 285 Set<String> roles = getRoles(mPackageName, mUserId); 286 if (roles.isEmpty()) { 287 authority = UnknownAuthority.UNKNOWN_AUTHORITY; 288 } else { 289 authority = new RoleAuthority(roles); 290 } 291 } else if (mAuthorities.contains(DPC_AUTHORITY)) { 292 authority = DpcAuthority.DPC_AUTHORITY; 293 } else if (mAuthorities.contains(DEVICE_ADMIN_AUTHORITY)) { 294 authority = DeviceAdminAuthority.DEVICE_ADMIN_AUTHORITY; 295 } else if (mIsSystemAuthority) { 296 // For now, System Authority returns UnknownAuthority. 297 authority = new UnknownAuthority(mSystemEntity); 298 } else { 299 authority = UnknownAuthority.UNKNOWN_AUTHORITY; 300 } 301 return new android.app.admin.EnforcingAdmin( 302 mPackageName, 303 authority, 304 UserHandle.of(mUserId), 305 mComponentName); 306 } 307 308 /** 309 * For two EnforcingAdmins to be equal they must: 310 * 311 * <ul> 312 * <li> have the same package names and component names and either 313 * <li> have exactly the same authorities ({@link #DPC_AUTHORITY} or 314 * {@link #DEVICE_ADMIN_AUTHORITY}), or have any role or default authorities. 315 * </ul> 316 * 317 * <p>EnforcingAdmins are considered equal if they have any role authority as they can have 318 * roles granted/revoked between calls. 319 */ 320 @Override equals(@ullable Object o)321 public boolean equals(@Nullable Object o) { 322 if (this == o) return true; 323 if (o == null || getClass() != o.getClass()) return false; 324 EnforcingAdmin other = (EnforcingAdmin) o; 325 return Objects.equals(mPackageName, other.mPackageName) 326 && Objects.equals(mSystemEntity, other.mSystemEntity) 327 && Objects.equals(mComponentName, other.mComponentName) 328 && Objects.equals(mIsRoleAuthority, other.mIsRoleAuthority) 329 && (mIsSystemAuthority == other.mIsSystemAuthority) 330 && hasMatchingAuthorities(this, other); 331 } 332 hasMatchingAuthorities(EnforcingAdmin admin1, EnforcingAdmin admin2)333 private static boolean hasMatchingAuthorities(EnforcingAdmin admin1, EnforcingAdmin admin2) { 334 if (admin1.mIsRoleAuthority && admin2.mIsRoleAuthority) { 335 return true; 336 } 337 return admin1.getAuthorities().equals(admin2.getAuthorities()); 338 } 339 340 @Override hashCode()341 public int hashCode() { 342 if (mIsRoleAuthority) { 343 return Objects.hash(mPackageName, mUserId); 344 } else if (mIsSystemAuthority) { 345 return Objects.hash(mSystemEntity); 346 } else { 347 return Objects.hash( 348 mComponentName == null ? mPackageName : mComponentName, 349 mUserId, 350 getAuthorities()); 351 } 352 } 353 saveToXml(TypedXmlSerializer serializer)354 void saveToXml(TypedXmlSerializer serializer) throws IOException { 355 serializer.attribute(/* namespace= */ null, ATTR_PACKAGE_NAME, mPackageName); 356 serializer.attributeBoolean(/* namespace= */ null, ATTR_IS_ROLE, mIsRoleAuthority); 357 serializer.attributeBoolean(/* namespace= */ null, ATTR_IS_SYSTEM, mIsSystemAuthority); 358 serializer.attributeInt(/* namespace= */ null, ATTR_USER_ID, mUserId); 359 if (mIsSystemAuthority) { 360 serializer.attribute(/* namespace= */ null, ATTR_SYSTEM_ENTITY, mSystemEntity); 361 } 362 if (!mIsRoleAuthority && !mIsSystemAuthority) { 363 if (mComponentName != null) { 364 serializer.attribute( 365 /* namespace= */ null, ATTR_CLASS_NAME, mComponentName.getClassName()); 366 } 367 // Role authorities get recomputed on load so no need to save them. 368 serializer.attribute( 369 /* namespace= */ null, 370 ATTR_AUTHORITIES, 371 String.join(ATTR_AUTHORITIES_SEPARATOR, getAuthorities())); 372 } 373 } 374 375 @Nullable readFromXml(TypedXmlPullParser parser)376 static EnforcingAdmin readFromXml(TypedXmlPullParser parser) 377 throws XmlPullParserException { 378 String packageName = parser.getAttributeValue(/* namespace= */ null, ATTR_PACKAGE_NAME); 379 String systemEntity = parser.getAttributeValue(/* namespace= */ null, ATTR_SYSTEM_ENTITY); 380 boolean isRoleAuthority = parser.getAttributeBoolean(/* namespace= */ null, ATTR_IS_ROLE); 381 boolean isSystemAuthority = parser.getAttributeBoolean( 382 /* namespace= */ null, ATTR_IS_SYSTEM, /* defaultValue= */ false); 383 String authoritiesStr = parser.getAttributeValue(/* namespace= */ null, ATTR_AUTHORITIES); 384 int userId = parser.getAttributeInt(/* namespace= */ null, ATTR_USER_ID); 385 386 if (isRoleAuthority) { 387 if (packageName == null) { 388 Slogf.wtf(TAG, "Error parsing EnforcingAdmin with RoleAuthority, packageName is " 389 + "null."); 390 return null; 391 } 392 // TODO(b/281697976): load active admin 393 return new EnforcingAdmin(packageName, userId); 394 } else if (isSystemAuthority) { 395 if (systemEntity == null) { 396 Slogf.wtf(TAG, "Error parsing EnforcingAdmin with SystemAuthority, " 397 + "systemEntity is null."); 398 return null; 399 } 400 return new EnforcingAdmin(systemEntity); 401 } else { 402 if (packageName == null || authoritiesStr == null) { 403 Slogf.wtf(TAG, "Error parsing EnforcingAdmin, packageName is " 404 + (packageName == null ? "null" : packageName) + ", and authorities is " 405 + (authoritiesStr == null ? "null" : authoritiesStr) + "."); 406 return null; 407 } 408 String className = parser.getAttributeValue(/* namespace= */ null, ATTR_CLASS_NAME); 409 ComponentName componentName = className == null 410 ? null : new ComponentName(packageName, className); 411 Set<String> authorities = Set.of(authoritiesStr.split(ATTR_AUTHORITIES_SEPARATOR)); 412 // TODO(b/281697976): load active admin 413 return new EnforcingAdmin(packageName, componentName, authorities, userId); 414 } 415 } 416 417 @Override toString()418 public String toString() { 419 StringBuilder sb = new StringBuilder(); 420 sb.append("EnforcingAdmin { mPackageName= "); 421 sb.append(mPackageName); 422 if (mComponentName != null) { 423 sb.append(", mComponentName= "); 424 sb.append(mComponentName); 425 } 426 if (mAuthorities != null) { 427 sb.append(", mAuthorities= "); 428 sb.append(mAuthorities); 429 } 430 sb.append(", mUserId= "); 431 sb.append(mUserId); 432 sb.append(", mIsRoleAuthority= "); 433 sb.append(mIsRoleAuthority); 434 sb.append(", mIsSystemAuthority= "); 435 sb.append(mIsSystemAuthority); 436 sb.append(", mSystemEntity = "); 437 sb.append(mSystemEntity); 438 sb.append(" }"); 439 return sb.toString(); 440 } 441 } 442