1088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee/* 2088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee * Copyright (C) 2017 The Android Open Source Project 3088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee * 4088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee * Licensed under the Apache License, Version 2.0 (the "License"); 5088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee * you may not use this file except in compliance with the License. 6088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee * You may obtain a copy of the License at 7088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee * 8088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee * http://www.apache.org/licenses/LICENSE-2.0 9088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee * 10088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee * Unless required by applicable law or agreed to in writing, software 11088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee * distributed under the License is distributed on an "AS IS" BASIS, 12088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee * See the License for the specific language governing permissions and 14088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee * limitations under the License. 15088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee */ 16088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee 17088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Leepackage com.android.server.devicepolicy; 18088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee 19088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Leeimport android.app.Notification; 20088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Leeimport android.app.NotificationManager; 21088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Leeimport android.app.PendingIntent; 22088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Leeimport android.content.BroadcastReceiver; 23088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Leeimport android.content.Context; 24088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Leeimport android.content.Intent; 25088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Leeimport android.content.IntentFilter; 26088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Leeimport android.content.pm.ActivityInfo; 27088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Leeimport android.content.pm.PackageManager; 28088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Leeimport android.content.res.Resources; 29088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Leeimport android.graphics.Color; 30088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Leeimport android.os.Build; 31088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Leeimport android.os.Handler; 32088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Leeimport android.os.RemoteException; 33088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Leeimport android.os.UserHandle; 34088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Leeimport android.os.UserManager; 35088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Leeimport android.os.storage.StorageManager; 36088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Leeimport android.provider.Settings; 37088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Leeimport android.security.Credentials; 38088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Leeimport android.security.KeyChain; 39088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Leeimport android.security.KeyChain.KeyChainConnection; 40088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Leeimport android.util.Log; 41088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee 42282cfefea0fbbd299839e353e6d30affdcd4a55cChris Wrenimport com.android.internal.messages.nano.SystemMessageProto.SystemMessage; 43088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Leeimport com.android.internal.notification.SystemNotificationChannels; 44088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Leeimport com.android.internal.R; 45088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee 46088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Leeimport java.io.ByteArrayInputStream; 47088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Leeimport java.io.IOException; 48088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Leeimport java.security.cert.CertificateException; 49088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Leeimport java.security.cert.CertificateFactory; 50088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Leeimport java.security.cert.X509Certificate; 51088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Leeimport java.util.List; 52088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Leeimport java.util.Set; 53088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee 54088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Leepublic class CertificateMonitor { 55088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee protected static final String LOG_TAG = DevicePolicyManagerService.LOG_TAG; 56282cfefea0fbbd299839e353e6d30affdcd4a55cChris Wren protected static final int MONITORING_CERT_NOTIFICATION_ID = SystemMessage.NOTE_SSL_CERT_INFO; 57088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee 58088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee private final DevicePolicyManagerService mService; 59088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee private final DevicePolicyManagerService.Injector mInjector; 60088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee private final Handler mHandler; 61088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee 62088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee public CertificateMonitor(final DevicePolicyManagerService service, 63088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee final DevicePolicyManagerService.Injector injector, final Handler handler) { 64088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee mService = service; 65088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee mInjector = injector; 66088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee mHandler = handler; 67088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee 68088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee // Broadcast filter for changes to the trusted certificate store. Listens on the background 69088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee // handler to avoid blocking time-critical tasks on the main handler thread. 70088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee IntentFilter filter = new IntentFilter(); 71088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee filter.addAction(Intent.ACTION_USER_STARTED); 72088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee filter.addAction(Intent.ACTION_USER_UNLOCKED); 73088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee filter.addAction(KeyChain.ACTION_TRUST_STORE_CHANGED); 74088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); 75088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee mInjector.mContext.registerReceiverAsUser( 76088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee mRootCaReceiver, UserHandle.ALL, filter, null, mHandler); 77088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee } 78088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee 79088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee public String installCaCert(final UserHandle userHandle, byte[] certBuffer) { 80088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee // Convert certificate data from X509 format to PEM. 81088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee byte[] pemCert; 82088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee try { 83088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee X509Certificate cert = parseCert(certBuffer); 84088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee pemCert = Credentials.convertToPem(cert); 85088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee } catch (CertificateException | IOException ce) { 86088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee Log.e(LOG_TAG, "Problem converting cert", ce); 87088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee return null; 88088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee } 89088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee 90088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee try (KeyChainConnection keyChainConnection = mInjector.keyChainBindAsUser(userHandle)) { 91088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee return keyChainConnection.getService().installCaCertificate(pemCert); 92088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee } catch (RemoteException e) { 93088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee Log.e(LOG_TAG, "installCaCertsToKeyChain(): ", e); 94088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee } catch (InterruptedException e1) { 95088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee Log.w(LOG_TAG, "installCaCertsToKeyChain(): ", e1); 96088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee Thread.currentThread().interrupt(); 97088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee } 98088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee return null; 99088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee } 100088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee 101088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee public void uninstallCaCerts(final UserHandle userHandle, final String[] aliases) { 102088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee try (KeyChainConnection keyChainConnection = mInjector.keyChainBindAsUser(userHandle)) { 103088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee for (int i = 0 ; i < aliases.length; i++) { 104088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee keyChainConnection.getService().deleteCaCertificate(aliases[i]); 105088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee } 106088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee } catch (RemoteException e) { 107088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee Log.e(LOG_TAG, "from CaCertUninstaller: ", e); 108088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee } catch (InterruptedException ie) { 109088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee Log.w(LOG_TAG, "CaCertUninstaller: ", ie); 110088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee Thread.currentThread().interrupt(); 111088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee } 112088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee } 113088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee 114088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee public List<String> getInstalledCaCertificates(UserHandle userHandle) 115088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee throws RemoteException, RuntimeException { 116088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee try (KeyChainConnection conn = mInjector.keyChainBindAsUser(userHandle)) { 117088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee return conn.getService().getUserCaAliases().getList(); 118088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee } catch (InterruptedException e) { 119088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee Thread.currentThread().interrupt(); 120088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee return null; 121088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee } catch (AssertionError e) { 122088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee throw new RuntimeException(e); 123088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee } 124088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee } 125088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee 126088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee public void onCertificateApprovalsChanged(int userId) { 127088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee mHandler.post(() -> updateInstalledCertificates(UserHandle.of(userId))); 128088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee } 129088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee 130088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee /** 131088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee * Broadcast receiver for changes to the trusted certificate store. 132088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee */ 133088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee private final BroadcastReceiver mRootCaReceiver = new BroadcastReceiver() { 134088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee @Override 135088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee public void onReceive(Context context, Intent intent) { 136088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee if (StorageManager.inCryptKeeperBounce()) { 137088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee return; 138088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee } 139088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, getSendingUserId()); 140088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee updateInstalledCertificates(UserHandle.of(userId)); 141088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee } 142088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee }; 143088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee 144088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee private void updateInstalledCertificates(final UserHandle userHandle) { 145088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee if (!mInjector.getUserManager().isUserUnlocked(userHandle.getIdentifier())) { 146088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee return; 147088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee } 148088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee 149088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee final List<String> installedCerts; 150088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee try { 151088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee installedCerts = getInstalledCaCertificates(userHandle); 152088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee } catch (RemoteException | RuntimeException e) { 153088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee Log.e(LOG_TAG, "Could not retrieve certificates from KeyChain service", e); 154088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee return; 155088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee } 156088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee mService.onInstalledCertificatesChanged(userHandle, installedCerts); 157088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee 158088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee final int pendingCertificateCount = 159088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee installedCerts.size() - mService.getAcceptedCaCertificates(userHandle).size(); 160088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee if (pendingCertificateCount != 0) { 161088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee final Notification noti = buildNotification(userHandle, pendingCertificateCount); 162088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee mInjector.getNotificationManager().notifyAsUser( 163088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee LOG_TAG, MONITORING_CERT_NOTIFICATION_ID, noti, userHandle); 164088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee } else { 165088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee mInjector.getNotificationManager().cancelAsUser( 166088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee LOG_TAG, MONITORING_CERT_NOTIFICATION_ID, userHandle); 167088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee } 168088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee } 169088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee 170088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee private Notification buildNotification(UserHandle userHandle, int pendingCertificateCount) { 171088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee final Context userContext; 172088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee try { 173088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee userContext = mInjector.createContextAsUser(userHandle); 174088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee } catch (PackageManager.NameNotFoundException e) { 175088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee Log.e(LOG_TAG, "Create context as " + userHandle + " failed", e); 176088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee return null; 177088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee } 178088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee 179088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee final Resources resources = mInjector.getResources(); 180088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee final int smallIconId; 181088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee final String contentText; 182088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee 183088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee int parentUserId = userHandle.getIdentifier(); 184088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee 185088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee if (mService.getProfileOwner(userHandle.getIdentifier()) != null) { 186088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee contentText = resources.getString(R.string.ssl_ca_cert_noti_managed, 187088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee mService.getProfileOwnerName(userHandle.getIdentifier())); 188088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee smallIconId = R.drawable.stat_sys_certificate_info; 189088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee parentUserId = mService.getProfileParentId(userHandle.getIdentifier()); 190088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee } else if (mService.getDeviceOwnerUserId() == userHandle.getIdentifier()) { 191088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee final String ownerName = mService.getDeviceOwnerName(); 192088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee contentText = resources.getString(R.string.ssl_ca_cert_noti_managed, 193088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee mService.getDeviceOwnerName()); 194088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee smallIconId = R.drawable.stat_sys_certificate_info; 195088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee } else { 196088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee contentText = resources.getString(R.string.ssl_ca_cert_noti_by_unknown); 197088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee smallIconId = android.R.drawable.stat_sys_warning; 198088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee } 199088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee 200088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee // Create an intent to launch an activity showing information about the certificate. 201088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee Intent dialogIntent = new Intent(Settings.ACTION_MONITORING_CERT_INFO); 202088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee dialogIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); 203088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee dialogIntent.putExtra(Settings.EXTRA_NUMBER_OF_CERTIFICATES, pendingCertificateCount); 204088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee dialogIntent.putExtra(Intent.EXTRA_USER_ID, userHandle.getIdentifier()); 205088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee 206088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee // The intent should only be allowed to resolve to a system app. 207088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee ActivityInfo targetInfo = dialogIntent.resolveActivityInfo( 208088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee mInjector.getPackageManager(), PackageManager.MATCH_SYSTEM_ONLY); 209088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee if (targetInfo != null) { 210088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee dialogIntent.setComponent(targetInfo.getComponentName()); 211088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee } 212088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee 213088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee PendingIntent notifyIntent = mInjector.pendingIntentGetActivityAsUser(userContext, 0, 214088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee dialogIntent, PendingIntent.FLAG_UPDATE_CURRENT, null, 215088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee UserHandle.of(parentUserId)); 216088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee 217088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee return new Notification.Builder(userContext, SystemNotificationChannels.SECURITY) 218088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee .setSmallIcon(smallIconId) 219088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee .setContentTitle(resources.getQuantityText(R.plurals.ssl_ca_cert_warning, 220088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee pendingCertificateCount)) 221088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee .setContentText(contentText) 222088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee .setContentIntent(notifyIntent) 223088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee .setShowWhen(false) 224088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee .setColor(R.color.system_notification_accent_color) 225088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee .build(); 226088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee } 227088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee 228088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee private static X509Certificate parseCert(byte[] certBuffer) throws CertificateException { 229088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); 230088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee return (X509Certificate) certFactory.generateCertificate(new ByteArrayInputStream( 231088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee certBuffer)); 232088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee } 233088d7aa9c1e9b73ea9dce1616b4958f0c41ca05eRobin Lee} 234