1 /* 2 * Copyright (C) 2014 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.trust; 18 19 import android.annotation.TargetApi; 20 import android.app.AlarmManager; 21 import android.app.PendingIntent; 22 import android.app.admin.DevicePolicyManager; 23 import android.content.BroadcastReceiver; 24 import android.content.ComponentName; 25 import android.content.Context; 26 import android.content.Intent; 27 import android.content.IntentFilter; 28 import android.content.ServiceConnection; 29 import android.net.Uri; 30 import android.os.Binder; 31 import android.os.Build; 32 import android.os.Handler; 33 import android.os.IBinder; 34 import android.os.Message; 35 import android.os.PatternMatcher; 36 import android.os.PersistableBundle; 37 import android.os.RemoteException; 38 import android.os.SystemClock; 39 import android.os.UserHandle; 40 import android.service.trust.ITrustAgentService; 41 import android.service.trust.ITrustAgentServiceCallback; 42 import android.service.trust.TrustAgentService; 43 import android.util.Log; 44 import android.util.Slog; 45 import java.util.Collections; 46 import java.util.List; 47 48 /** 49 * A wrapper around a TrustAgentService interface. Coordinates communication between 50 * TrustManager and the actual TrustAgent. 51 */ 52 @TargetApi(Build.VERSION_CODES.LOLLIPOP) 53 public class TrustAgentWrapper { 54 private static final String EXTRA_COMPONENT_NAME = "componentName"; 55 private static final String TRUST_EXPIRED_ACTION = "android.server.trust.TRUST_EXPIRED_ACTION"; 56 private static final String PERMISSION = android.Manifest.permission.PROVIDE_TRUST_AGENT; 57 private static final boolean DEBUG = TrustManagerService.DEBUG; 58 private static final String TAG = "TrustAgentWrapper"; 59 60 private static final int MSG_GRANT_TRUST = 1; 61 private static final int MSG_REVOKE_TRUST = 2; 62 private static final int MSG_TRUST_TIMEOUT = 3; 63 private static final int MSG_RESTART_TIMEOUT = 4; 64 private static final int MSG_SET_TRUST_AGENT_FEATURES_COMPLETED = 5; 65 private static final int MSG_MANAGING_TRUST = 6; 66 private static final int MSG_ADD_ESCROW_TOKEN = 7; 67 private static final int MSG_REMOVE_ESCROW_TOKEN = 8; 68 private static final int MSG_ESCROW_TOKEN_STATE = 9; 69 private static final int MSG_UNLOCK_USER = 10; 70 71 /** 72 * Time in uptime millis that we wait for the service connection, both when starting 73 * and when the service disconnects. 74 */ 75 private static final long RESTART_TIMEOUT_MILLIS = 5 * 60000; 76 77 /** 78 * Long extra for {@link #MSG_GRANT_TRUST} 79 */ 80 private static final String DATA_DURATION = "duration"; 81 private static final String DATA_ESCROW_TOKEN = "escrow_token"; 82 private static final String DATA_HANDLE = "handle"; 83 private static final String DATA_USER_ID = "user_id"; 84 85 private final TrustManagerService mTrustManagerService; 86 private final int mUserId; 87 private final Context mContext; 88 private final ComponentName mName; 89 90 private ITrustAgentService mTrustAgentService; 91 private boolean mBound; 92 private long mScheduledRestartUptimeMillis; 93 private long mMaximumTimeToLock; // from DevicePolicyManager 94 private boolean mPendingSuccessfulUnlock = false; 95 96 // Trust state 97 private boolean mTrusted; 98 private CharSequence mMessage; 99 private boolean mTrustDisabledByDpm; 100 private boolean mManagingTrust; 101 private IBinder mSetTrustAgentFeaturesToken; 102 private AlarmManager mAlarmManager; 103 private final Intent mAlarmIntent; 104 private PendingIntent mAlarmPendingIntent; 105 106 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 107 @Override 108 public void onReceive(Context context, Intent intent) { 109 ComponentName component = intent.getParcelableExtra(EXTRA_COMPONENT_NAME); 110 if (TRUST_EXPIRED_ACTION.equals(intent.getAction()) 111 && mName.equals(component)) { 112 mHandler.removeMessages(MSG_TRUST_TIMEOUT); 113 mHandler.sendEmptyMessage(MSG_TRUST_TIMEOUT); 114 } 115 } 116 }; 117 118 private final Handler mHandler = new Handler() { 119 @Override 120 public void handleMessage(Message msg) { 121 switch (msg.what) { 122 case MSG_GRANT_TRUST: 123 if (!isConnected()) { 124 Log.w(TAG, "Agent is not connected, cannot grant trust: " 125 + mName.flattenToShortString()); 126 return; 127 } 128 mTrusted = true; 129 mMessage = (CharSequence) msg.obj; 130 int flags = msg.arg1; 131 long durationMs = msg.getData().getLong(DATA_DURATION); 132 if (durationMs > 0) { 133 final long duration; 134 if (mMaximumTimeToLock != 0) { 135 // Enforce DevicePolicyManager timeout. This is here as a safeguard to 136 // ensure trust agents are evaluating trust state at least as often as 137 // the policy dictates. Admins that want more guarantees should be using 138 // DevicePolicyManager#KEYGUARD_DISABLE_TRUST_AGENTS. 139 duration = Math.min(durationMs, mMaximumTimeToLock); 140 if (DEBUG) { 141 Slog.d(TAG, "DPM lock timeout in effect. Timeout adjusted from " 142 + durationMs + " to " + duration); 143 } 144 } else { 145 duration = durationMs; 146 } 147 long expiration = SystemClock.elapsedRealtime() + duration; 148 mAlarmPendingIntent = PendingIntent.getBroadcast(mContext, 0, mAlarmIntent, 149 PendingIntent.FLAG_CANCEL_CURRENT); 150 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, expiration, 151 mAlarmPendingIntent); 152 } 153 mTrustManagerService.mArchive.logGrantTrust(mUserId, mName, 154 (mMessage != null ? mMessage.toString() : null), 155 durationMs, flags); 156 mTrustManagerService.updateTrust(mUserId, flags); 157 break; 158 case MSG_TRUST_TIMEOUT: 159 if (DEBUG) Slog.d(TAG, "Trust timed out : " + mName.flattenToShortString()); 160 mTrustManagerService.mArchive.logTrustTimeout(mUserId, mName); 161 onTrustTimeout(); 162 // Fall through. 163 case MSG_REVOKE_TRUST: 164 mTrusted = false; 165 mMessage = null; 166 mHandler.removeMessages(MSG_TRUST_TIMEOUT); 167 if (msg.what == MSG_REVOKE_TRUST) { 168 mTrustManagerService.mArchive.logRevokeTrust(mUserId, mName); 169 } 170 mTrustManagerService.updateTrust(mUserId, 0); 171 break; 172 case MSG_RESTART_TIMEOUT: 173 Slog.w(TAG, "Connection attempt to agent " + mName.flattenToShortString() 174 + " timed out, rebinding"); 175 destroy(); 176 mTrustManagerService.resetAgent(mName, mUserId); 177 break; 178 case MSG_SET_TRUST_AGENT_FEATURES_COMPLETED: 179 IBinder token = (IBinder) msg.obj; 180 boolean result = msg.arg1 != 0; 181 if (mSetTrustAgentFeaturesToken == token) { 182 mSetTrustAgentFeaturesToken = null; 183 if (mTrustDisabledByDpm && result) { 184 if (DEBUG) Slog.d(TAG, "Re-enabling agent because it acknowledged " 185 + "enabled features: " + mName.flattenToShortString()); 186 mTrustDisabledByDpm = false; 187 mTrustManagerService.updateTrust(mUserId, 0); 188 } 189 } else { 190 if (DEBUG) Slog.w(TAG, "Ignoring MSG_SET_TRUST_AGENT_FEATURES_COMPLETED " 191 + "with obsolete token: " + mName.flattenToShortString()); 192 } 193 break; 194 case MSG_MANAGING_TRUST: 195 mManagingTrust = msg.arg1 != 0; 196 if (!mManagingTrust) { 197 mTrusted = false; 198 mMessage = null; 199 } 200 mTrustManagerService.mArchive.logManagingTrust(mUserId, mName, mManagingTrust); 201 mTrustManagerService.updateTrust(mUserId, 0); 202 break; 203 case MSG_ADD_ESCROW_TOKEN: { 204 byte[] eToken = msg.getData().getByteArray(DATA_ESCROW_TOKEN); 205 int userId = msg.getData().getInt(DATA_USER_ID); 206 long handle = mTrustManagerService.addEscrowToken(eToken, userId); 207 boolean resultDeliverred = false; 208 try { 209 if (mTrustAgentService != null) { 210 mTrustAgentService.onEscrowTokenAdded( 211 eToken, handle, UserHandle.of(userId)); 212 resultDeliverred = true; 213 } 214 } catch (RemoteException e) { 215 onError(e); 216 } 217 218 if (!resultDeliverred) { 219 mTrustManagerService.removeEscrowToken(handle, userId); 220 } 221 break; 222 } 223 case MSG_ESCROW_TOKEN_STATE: { 224 long handle = msg.getData().getLong(DATA_HANDLE); 225 int userId = msg.getData().getInt(DATA_USER_ID); 226 boolean active = mTrustManagerService.isEscrowTokenActive(handle, userId); 227 try { 228 if (mTrustAgentService != null) { 229 mTrustAgentService.onTokenStateReceived(handle, 230 active ? TrustAgentService.TOKEN_STATE_ACTIVE 231 : TrustAgentService.TOKEN_STATE_INACTIVE); 232 } 233 } catch (RemoteException e) { 234 onError(e); 235 } 236 break; 237 } 238 case MSG_REMOVE_ESCROW_TOKEN: { 239 long handle = msg.getData().getLong(DATA_HANDLE); 240 int userId = msg.getData().getInt(DATA_USER_ID); 241 boolean success = mTrustManagerService.removeEscrowToken(handle, userId); 242 try { 243 if (mTrustAgentService != null) { 244 mTrustAgentService.onEscrowTokenRemoved(handle, success); 245 } 246 } catch (RemoteException e) { 247 onError(e); 248 } 249 break; 250 } 251 case MSG_UNLOCK_USER: { 252 long handle = msg.getData().getLong(DATA_HANDLE); 253 int userId = msg.getData().getInt(DATA_USER_ID); 254 byte[] eToken = msg.getData().getByteArray(DATA_ESCROW_TOKEN); 255 mTrustManagerService.unlockUserWithToken(handle, eToken, userId); 256 break; 257 } 258 } 259 } 260 }; 261 262 private ITrustAgentServiceCallback mCallback = new ITrustAgentServiceCallback.Stub() { 263 264 @Override 265 public void grantTrust(CharSequence userMessage, long durationMs, int flags) { 266 if (DEBUG) Slog.d(TAG, "enableTrust(" + userMessage + ", durationMs = " + durationMs 267 + ", flags = " + flags + ")"); 268 269 Message msg = mHandler.obtainMessage( 270 MSG_GRANT_TRUST, flags, 0, userMessage); 271 msg.getData().putLong(DATA_DURATION, durationMs); 272 msg.sendToTarget(); 273 } 274 275 @Override 276 public void revokeTrust() { 277 if (DEBUG) Slog.d(TAG, "revokeTrust()"); 278 mHandler.sendEmptyMessage(MSG_REVOKE_TRUST); 279 } 280 281 @Override 282 public void setManagingTrust(boolean managingTrust) { 283 if (DEBUG) Slog.d(TAG, "managingTrust()"); 284 mHandler.obtainMessage(MSG_MANAGING_TRUST, managingTrust ? 1 : 0, 0).sendToTarget(); 285 } 286 287 @Override 288 public void onConfigureCompleted(boolean result, IBinder token) { 289 if (DEBUG) Slog.d(TAG, "onSetTrustAgentFeaturesEnabledCompleted(result=" + result); 290 mHandler.obtainMessage(MSG_SET_TRUST_AGENT_FEATURES_COMPLETED, 291 result ? 1 : 0, 0, token).sendToTarget(); 292 } 293 294 @Override 295 public void addEscrowToken(byte[] token, int userId) { 296 if (mContext.getResources() 297 .getBoolean(com.android.internal.R.bool.config_allowEscrowTokenForTrustAgent)) { 298 throw new SecurityException("Escrow token API is not allowed."); 299 } 300 301 if (DEBUG) Slog.d(TAG, "adding escrow token for user " + userId); 302 Message msg = mHandler.obtainMessage(MSG_ADD_ESCROW_TOKEN); 303 msg.getData().putByteArray(DATA_ESCROW_TOKEN, token); 304 msg.getData().putInt(DATA_USER_ID, userId); 305 msg.sendToTarget(); 306 } 307 308 @Override 309 public void isEscrowTokenActive(long handle, int userId) { 310 if (mContext.getResources() 311 .getBoolean(com.android.internal.R.bool.config_allowEscrowTokenForTrustAgent)) { 312 throw new SecurityException("Escrow token API is not allowed."); 313 } 314 315 if (DEBUG) Slog.d(TAG, "checking the state of escrow token on user " + userId); 316 Message msg = mHandler.obtainMessage(MSG_ESCROW_TOKEN_STATE); 317 msg.getData().putLong(DATA_HANDLE, handle); 318 msg.getData().putInt(DATA_USER_ID, userId); 319 msg.sendToTarget(); 320 } 321 322 @Override 323 public void removeEscrowToken(long handle, int userId) { 324 if (mContext.getResources() 325 .getBoolean(com.android.internal.R.bool.config_allowEscrowTokenForTrustAgent)) { 326 throw new SecurityException("Escrow token API is not allowed."); 327 } 328 329 if (DEBUG) Slog.d(TAG, "removing escrow token on user " + userId); 330 Message msg = mHandler.obtainMessage(MSG_REMOVE_ESCROW_TOKEN); 331 msg.getData().putLong(DATA_HANDLE, handle); 332 msg.getData().putInt(DATA_USER_ID, userId); 333 msg.sendToTarget(); 334 } 335 336 @Override 337 public void unlockUserWithToken(long handle, byte[] token, int userId) { 338 if (mContext.getResources() 339 .getBoolean(com.android.internal.R.bool.config_allowEscrowTokenForTrustAgent)) { 340 throw new SecurityException("Escrow token API is not allowed."); 341 } 342 343 if (DEBUG) Slog.d(TAG, "unlocking user " + userId); 344 Message msg = mHandler.obtainMessage(MSG_UNLOCK_USER); 345 msg.getData().putInt(DATA_USER_ID, userId); 346 msg.getData().putLong(DATA_HANDLE, handle); 347 msg.getData().putByteArray(DATA_ESCROW_TOKEN, token); 348 msg.sendToTarget(); 349 } 350 }; 351 352 private final ServiceConnection mConnection = new ServiceConnection() { 353 @Override 354 public void onServiceConnected(ComponentName name, IBinder service) { 355 if (DEBUG) Slog.d(TAG, "TrustAgent started : " + name.flattenToString()); 356 mHandler.removeMessages(MSG_RESTART_TIMEOUT); 357 mTrustAgentService = ITrustAgentService.Stub.asInterface(service); 358 mTrustManagerService.mArchive.logAgentConnected(mUserId, name); 359 setCallback(mCallback); 360 updateDevicePolicyFeatures(); 361 362 if (mPendingSuccessfulUnlock) { 363 onUnlockAttempt(true); 364 mPendingSuccessfulUnlock = false; 365 } 366 367 if (mTrustManagerService.isDeviceLockedInner(mUserId)) { 368 onDeviceLocked(); 369 } else { 370 onDeviceUnlocked(); 371 } 372 } 373 374 @Override 375 public void onServiceDisconnected(ComponentName name) { 376 if (DEBUG) Slog.d(TAG, "TrustAgent disconnected : " + name.flattenToShortString()); 377 mTrustAgentService = null; 378 mManagingTrust = false; 379 mSetTrustAgentFeaturesToken = null; 380 mTrustManagerService.mArchive.logAgentDied(mUserId, name); 381 mHandler.sendEmptyMessage(MSG_REVOKE_TRUST); 382 if (mBound) { 383 scheduleRestart(); 384 } 385 // mTrustDisabledByDpm maintains state 386 } 387 }; 388 389 public TrustAgentWrapper(Context context, TrustManagerService trustManagerService, 390 Intent intent, UserHandle user) { 391 mContext = context; 392 mTrustManagerService = trustManagerService; 393 mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); 394 mUserId = user.getIdentifier(); 395 mName = intent.getComponent(); 396 397 mAlarmIntent = new Intent(TRUST_EXPIRED_ACTION).putExtra(EXTRA_COMPONENT_NAME, mName); 398 mAlarmIntent.setData(Uri.parse(mAlarmIntent.toUri(Intent.URI_INTENT_SCHEME))); 399 mAlarmIntent.setPackage(context.getPackageName()); 400 401 final IntentFilter alarmFilter = new IntentFilter(TRUST_EXPIRED_ACTION); 402 alarmFilter.addDataScheme(mAlarmIntent.getScheme()); 403 final String pathUri = mAlarmIntent.toUri(Intent.URI_INTENT_SCHEME); 404 alarmFilter.addDataPath(pathUri, PatternMatcher.PATTERN_LITERAL); 405 406 // Schedules a restart for when connecting times out. If the connection succeeds, 407 // the restart is canceled in mCallback's onConnected. 408 scheduleRestart(); 409 mBound = context.bindServiceAsUser(intent, mConnection, 410 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, user); 411 if (mBound) { 412 mContext.registerReceiver(mBroadcastReceiver, alarmFilter, PERMISSION, null); 413 } else { 414 Log.e(TAG, "Can't bind to TrustAgent " + mName.flattenToShortString()); 415 } 416 } 417 418 private void onError(Exception e) { 419 Slog.w(TAG , "Exception ", e); 420 } 421 422 private void onTrustTimeout() { 423 try { 424 if (mTrustAgentService != null) mTrustAgentService.onTrustTimeout(); 425 } catch (RemoteException e) { 426 onError(e); 427 } 428 } 429 430 /** 431 * @see android.service.trust.TrustAgentService#onUnlockAttempt(boolean) 432 */ 433 public void onUnlockAttempt(boolean successful) { 434 try { 435 if (mTrustAgentService != null) { 436 mTrustAgentService.onUnlockAttempt(successful); 437 } else { 438 mPendingSuccessfulUnlock = successful; 439 } 440 } catch (RemoteException e) { 441 onError(e); 442 } 443 } 444 445 /** 446 * @see android.service.trust.TrustAgentService#onUnlockLockout(int) 447 */ 448 public void onUnlockLockout(int timeoutMs) { 449 try { 450 if (mTrustAgentService != null) { 451 mTrustAgentService.onUnlockLockout(timeoutMs); 452 } 453 } catch (RemoteException e) { 454 onError(e); 455 } 456 } 457 458 /** 459 * @see android.service.trust.TrustAgentService#onDeviceLocked() 460 */ 461 public void onDeviceLocked() { 462 try { 463 if (mTrustAgentService != null) mTrustAgentService.onDeviceLocked(); 464 } catch (RemoteException e) { 465 onError(e); 466 } 467 } 468 469 /** 470 * @see android.service.trust.TrustAgentService#onDeviceUnlocked() 471 */ 472 public void onDeviceUnlocked() { 473 try { 474 if (mTrustAgentService != null) mTrustAgentService.onDeviceUnlocked(); 475 } catch (RemoteException e) { 476 onError(e); 477 } 478 } 479 480 private void setCallback(ITrustAgentServiceCallback callback) { 481 try { 482 if (mTrustAgentService != null) { 483 mTrustAgentService.setCallback(callback); 484 } 485 } catch (RemoteException e) { 486 onError(e); 487 } 488 } 489 490 boolean updateDevicePolicyFeatures() { 491 boolean trustDisabled = false; 492 if (DEBUG) Slog.d(TAG, "updateDevicePolicyFeatures(" + mName + ")"); 493 try { 494 if (mTrustAgentService != null) { 495 DevicePolicyManager dpm = 496 (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); 497 498 if ((dpm.getKeyguardDisabledFeatures(null, mUserId) 499 & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0) { 500 List<PersistableBundle> config = dpm.getTrustAgentConfiguration( 501 null, mName, mUserId); 502 trustDisabled = true; 503 if (DEBUG) Slog.d(TAG, "Detected trust agents disabled. Config = " + config); 504 if (config != null && config.size() > 0) { 505 if (DEBUG) { 506 Slog.d(TAG, "TrustAgent " + mName.flattenToShortString() 507 + " disabled until it acknowledges "+ config); 508 } 509 mSetTrustAgentFeaturesToken = new Binder(); 510 mTrustAgentService.onConfigure(config, mSetTrustAgentFeaturesToken); 511 } 512 } else { 513 mTrustAgentService.onConfigure(Collections.EMPTY_LIST, null); 514 } 515 final long maxTimeToLock = dpm.getMaximumTimeToLockForUserAndProfiles(mUserId); 516 if (maxTimeToLock != mMaximumTimeToLock) { 517 // If the timeout changes, cancel the alarm and send a timeout event to have 518 // the agent re-evaluate trust. 519 mMaximumTimeToLock = maxTimeToLock; 520 if (mAlarmPendingIntent != null) { 521 mAlarmManager.cancel(mAlarmPendingIntent); 522 mAlarmPendingIntent = null; 523 mHandler.sendEmptyMessage(MSG_TRUST_TIMEOUT); 524 } 525 } 526 } 527 } catch (RemoteException e) { 528 onError(e); 529 } 530 if (mTrustDisabledByDpm != trustDisabled) { 531 mTrustDisabledByDpm = trustDisabled; 532 mTrustManagerService.updateTrust(mUserId, 0); 533 } 534 return trustDisabled; 535 } 536 537 public boolean isTrusted() { 538 return mTrusted && mManagingTrust && !mTrustDisabledByDpm; 539 } 540 541 public boolean isManagingTrust() { 542 return mManagingTrust && !mTrustDisabledByDpm; 543 } 544 545 public CharSequence getMessage() { 546 return mMessage; 547 } 548 549 public void destroy() { 550 mHandler.removeMessages(MSG_RESTART_TIMEOUT); 551 552 if (!mBound) { 553 return; 554 } 555 if (DEBUG) Slog.d(TAG, "TrustAgent unbound : " + mName.flattenToShortString()); 556 mTrustManagerService.mArchive.logAgentStopped(mUserId, mName); 557 mContext.unbindService(mConnection); 558 mBound = false; 559 mContext.unregisterReceiver(mBroadcastReceiver); 560 mTrustAgentService = null; 561 mSetTrustAgentFeaturesToken = null; 562 mHandler.sendEmptyMessage(MSG_REVOKE_TRUST); 563 } 564 565 public boolean isConnected() { 566 return mTrustAgentService != null; 567 } 568 569 public boolean isBound() { 570 return mBound; 571 } 572 573 /** 574 * If not connected, returns the time at which the agent is restarted. 575 * 576 * @return restart time in uptime millis. 577 */ 578 public long getScheduledRestartUptimeMillis() { 579 return mScheduledRestartUptimeMillis; 580 } 581 582 private void scheduleRestart() { 583 mHandler.removeMessages(MSG_RESTART_TIMEOUT); 584 mScheduledRestartUptimeMillis = SystemClock.uptimeMillis() + RESTART_TIMEOUT_MILLIS; 585 mHandler.sendEmptyMessageAtTime(MSG_RESTART_TIMEOUT, mScheduledRestartUptimeMillis); 586 } 587 } 588