diff options
-rw-r--r-- | core/java/android/app/admin/DevicePolicyManager.java | 2 | ||||
-rw-r--r-- | core/java/android/provider/Settings.java | 32 | ||||
-rw-r--r-- | core/res/res/drawable-hdpi/stat_sys_certificate_info.png | bin | 0 -> 1416 bytes | |||
-rw-r--r-- | core/res/res/drawable-mdpi/stat_sys_certificate_info.png | bin | 0 -> 930 bytes | |||
-rw-r--r-- | core/res/res/drawable-xhdpi/stat_sys_certificate_info.png | bin | 0 -> 1946 bytes | |||
-rw-r--r-- | core/res/res/drawable-xxhdpi/stat_sys_certificate_info.png | bin | 0 -> 4141 bytes | |||
-rw-r--r-- | core/res/res/values/strings.xml | 12 | ||||
-rw-r--r-- | core/res/res/values/symbols.xml | 4 | ||||
-rw-r--r-- | packages/SystemUI/res/values/strings.xml | 13 | ||||
-rw-r--r-- | packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java | 43 | ||||
-rw-r--r-- | services/java/com/android/server/DevicePolicyManagerService.java | 81 |
11 files changed, 132 insertions, 55 deletions
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index e0b1c00..ab82531 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -1372,7 +1372,7 @@ public class DevicePolicyManager { * * @hide */ - public boolean hasAnyCaCertsInstalled() { + public static boolean hasAnyCaCertsInstalled() { TrustedCertificateStore certStore = new TrustedCertificateStore(); Set<String> aliases = certStore.userAliases(); return aliases != null && !aliases.isEmpty(); diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index af905b4..c1c826c 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -160,6 +160,38 @@ public final class Settings { "android.settings.SECURITY_SETTINGS"; /** + * Activity Action: Show trusted credentials settings, opening to the user tab, + * to allow management of installed credentials. + * <p> + * In some cases, a matching Activity may not exist, so ensure you + * safeguard against this. + * <p> + * Input: Nothing. + * <p> + * Output: Nothing. + * @hide + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_TRUSTED_CREDENTIALS_USER = + "com.android.settings.TRUSTED_CREDENTIALS_USER"; + + /** + * Activity Action: Show dialog explaining that an installed CA cert may enable + * monitoring of encrypted network traffic. + * <p> + * In some cases, a matching Activity may not exist, so ensure you + * safeguard against this. + * <p> + * Input: Nothing. + * <p> + * Output: Nothing. + * @hide + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_MONITORING_CERT_INFO = + "com.android.settings.MONITORING_CERT_INFO"; + + /** * Activity Action: Show settings to allow configuration of privacy options. * <p> * In some cases, a matching Activity may not exist, so ensure you diff --git a/core/res/res/drawable-hdpi/stat_sys_certificate_info.png b/core/res/res/drawable-hdpi/stat_sys_certificate_info.png Binary files differnew file mode 100644 index 0000000..3be426c --- /dev/null +++ b/core/res/res/drawable-hdpi/stat_sys_certificate_info.png diff --git a/core/res/res/drawable-mdpi/stat_sys_certificate_info.png b/core/res/res/drawable-mdpi/stat_sys_certificate_info.png Binary files differnew file mode 100644 index 0000000..e15cf38 --- /dev/null +++ b/core/res/res/drawable-mdpi/stat_sys_certificate_info.png diff --git a/core/res/res/drawable-xhdpi/stat_sys_certificate_info.png b/core/res/res/drawable-xhdpi/stat_sys_certificate_info.png Binary files differnew file mode 100644 index 0000000..3c93ea0 --- /dev/null +++ b/core/res/res/drawable-xhdpi/stat_sys_certificate_info.png diff --git a/core/res/res/drawable-xxhdpi/stat_sys_certificate_info.png b/core/res/res/drawable-xxhdpi/stat_sys_certificate_info.png Binary files differnew file mode 100644 index 0000000..d96ef64 --- /dev/null +++ b/core/res/res/drawable-xxhdpi/stat_sys_certificate_info.png diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 35d0fbd..a03378e 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -273,6 +273,18 @@ <!-- If MMS discovers there isn't much space left on the device, it will show a toast with this message. --> <string name="low_memory" product="default">Phone storage is full. Delete some files to free space.</string> + <!-- SSL CA cert notification --> <skip /> + <!-- Shows up when there is a user SSL CA Cert installed on the + device. Indicates to the user that SSL traffic can be intercepted. [CHAR LIMIT=NONE] --> + <string name="ssl_ca_cert_warning">Network may be monitored</string> + <!-- Content text for a notification. The Title of the notification is "ssl_ca_cert_warning", + i.e. "Network may be monitored". This says that an unknown party is doing the monitoring. + [CHAR LIMIT=100]--> + <string name="ssl_ca_cert_noti_by_unknown">By an unknown third party</string> + <!-- Content text for a notification. The Title of the notification is "ssl_ca_cert_warning", + i.e. "Network may be monitored". This indicates who is doing the monitoring. + [CHAR LIMIT=100]--> + <string name="ssl_ca_cert_noti_managed">By <xliff:g id="managing_domain">%s</xliff:g></string> <!-- Display name for any time a piece of data refers to the owner of the phone. For example, this could be used in place of the phone's phone number. --> <string name="me">Me</string> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 44891a8..4148f20 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -886,6 +886,9 @@ <java-symbol type="string" name="write_fail_reason_cannot_write" /> <java-symbol type="string" name="transient_navigation_confirmation" /> <java-symbol type="string" name="transient_navigation_confirmation_long" /> + <java-symbol type="string" name="ssl_ca_cert_noti_by_unknown" /> + <java-symbol type="string" name="ssl_ca_cert_noti_managed" /> + <java-symbol type="string" name="ssl_ca_cert_warning" /> <java-symbol type="plurals" name="abbrev_in_num_days" /> <java-symbol type="plurals" name="abbrev_in_num_hours" /> @@ -1008,6 +1011,7 @@ <java-symbol type="drawable" name="stat_notify_rssi_in_range" /> <java-symbol type="drawable" name="stat_sys_gps_on" /> <java-symbol type="drawable" name="stat_sys_tether_wifi" /> + <java-symbol type="drawable" name="stat_sys_certificate_info" /> <java-symbol type="drawable" name="status_bar_background" /> <java-symbol type="drawable" name="sym_keyboard_shift" /> <java-symbol type="drawable" name="sym_keyboard_shift_locked" /> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 3ffa6f4..bbfe383 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -500,16 +500,5 @@ <!-- Shows up when there is a user SSL CA Cert installed on the device. Indicates to the user that SSL traffic can be intercepted. [CHAR LIMIT=NONE] --> <string name="ssl_ca_cert_warning">Network may be monitored</string> - <!-- Button to close the SSL CA cert warning dialog box. [CHAR LIMIT=NONE] --> - <string name="done_button">Done</string> - <!-- Title of Dialog warning users of SSL monitoring. [CHAR LIMIT=NONE] --> - <string name="ssl_ca_cert_dialog_title">Network Monitoring</string> - <!-- Text of message to show to users whose administrator has installed a SSL CA Cert. - [CHAR LIMIT=NONE] --> - <string name="ssl_ca_cert_info_message">This device is managed by: <xliff:g id="managing_domain">%s</xliff:g>.\n\nYour administrator is capable of monitoring your network activity, including emails, apps, and secure websites.\n\nFor more information,contact your administrator.</string> - <!-- Text of warning to show to users that have a SSL CA Cert installed. [CHAR LIMIT=NONE] --> - <string name="ssl_ca_cert_warning_message">A third party is capable of monitoring your network\nactivity, including emails, apps, and secure websites.\n\nA trusted credential installed on your device is making this possible.</string> - <!-- Label on button that will take the user to the Trusted Credentials settings page. - [CHAR LIMIT=NONE]--> - <string name="ssl_ca_cert_settings_button">Check trusted credentials</string> + </resources> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java index 68ee2b5..ceed30e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java @@ -194,7 +194,7 @@ class QuickSettings { mQueryCertTask = new AsyncTask<Void, Void, Pair<Boolean, Boolean>>() { @Override protected Pair<Boolean, Boolean> doInBackground(Void... params) { - boolean hasCert = mDevicePolicyManager.hasAnyCaCertsInstalled(); + boolean hasCert = DevicePolicyManager.hasAnyCaCertsInstalled(); boolean isManaged = mDevicePolicyManager.getDeviceOwner() != null; return Pair.create(hasCert, isManaged); @@ -764,7 +764,7 @@ class QuickSettings { @Override public void onClick(View v) { collapsePanels(); - showSslCaCertWarningDialog(); + startSettingsActivity(Settings.ACTION_MONITORING_CERT_INFO); } }); @@ -832,45 +832,6 @@ class QuickSettings { dialog.show(); } - private void showSslCaCertWarningDialog() { - final AlertDialog.Builder builder = new AlertDialog.Builder(mContext); - builder.setTitle(R.string.ssl_ca_cert_dialog_title); - builder.setCancelable(true); - final boolean hasDeviceOwner = mDevicePolicyManager.getDeviceOwner() != null; - int buttonLabel; - if (hasDeviceOwner) { - // Institutional case. Show informational message. - String message = mContext.getResources().getString(R.string.ssl_ca_cert_info_message, - mDevicePolicyManager.getDeviceOwnerName()); - builder.setMessage(message); - buttonLabel = R.string.done_button; - } else { - // Consumer case. Show scary warning. - builder.setMessage(R.string.ssl_ca_cert_warning_message); - buttonLabel = R.string.ssl_ca_cert_settings_button; - } - - builder.setPositiveButton(buttonLabel, new OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - // do something. - if (hasDeviceOwner) { - // Close - } else { - startSettingsActivity("com.android.settings.TRUSTED_CREDENTIALS_USER"); - } - } - }); - - final Dialog dialog = builder.create(); - dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); - try { - WindowManagerGlobal.getWindowManagerService().dismissKeyguard(); - } catch (RemoteException e) { - } - dialog.show(); - } - private void updateWifiDisplayStatus() { mWifiDisplayStatus = mDisplayManager.getWifiDisplayStatus(); applyWifiDisplayStatus(); diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java index 7e83396..2bca759 100644 --- a/services/java/com/android/server/DevicePolicyManagerService.java +++ b/services/java/com/android/server/DevicePolicyManagerService.java @@ -18,6 +18,7 @@ package com.android.server; import static android.Manifest.permission.MANAGE_CA_CERTIFICATES; +import com.android.internal.R; import com.android.internal.os.storage.ExternalStorageFormatter; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.JournaledFile; @@ -33,6 +34,9 @@ import android.app.Activity; import android.app.ActivityManagerNative; import android.app.AlarmManager; import android.app.AppGlobals; +import android.app.INotificationManager; +import android.app.Notification; +import android.app.NotificationManager; import android.app.PendingIntent; import android.app.admin.DeviceAdminInfo; import android.app.admin.DeviceAdminReceiver; @@ -51,6 +55,7 @@ import android.content.pm.PackageManager; import android.content.pm.Signature; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; +import android.content.pm.UserInfo; import android.net.Uri; import android.os.AsyncTask; import android.os.Binder; @@ -123,6 +128,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { protected static final String ACTION_EXPIRED_PASSWORD_NOTIFICATION = "com.android.server.ACTION_EXPIRED_PASSWORD_NOTIFICATION"; + private static final int MONITORING_CERT_NOTIFICATION_ID = R.string.ssl_ca_cert_warning; + private static final boolean DBG = false; final Context mContext; @@ -130,6 +137,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { IPowerManager mIPowerManager; IWindowManager mIWindowManager; + NotificationManager mNotificationManager; private DeviceOwner mDeviceOwner; @@ -177,7 +185,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { handlePasswordExpirationNotification(getUserData(userHandle)); } }); - } else if (Intent.ACTION_USER_REMOVED.equals(action)) { + } + if (Intent.ACTION_BOOT_COMPLETED.equals(action) + || KeyChain.ACTION_STORAGE_CHANGED.equals(action)) { + manageMonitoringCertificateNotification(intent); + } + if (Intent.ACTION_USER_REMOVED.equals(action)) { removeUserData(userHandle); } else if (Intent.ACTION_USER_STARTED.equals(action) || Intent.ACTION_PACKAGE_CHANGED.equals(action) @@ -526,6 +539,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { filter.addAction(ACTION_EXPIRED_PASSWORD_NOTIFICATION); filter.addAction(Intent.ACTION_USER_REMOVED); filter.addAction(Intent.ACTION_USER_STARTED); + filter.addAction(KeyChain.ACTION_STORAGE_CHANGED); context.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler); filter = new IntentFilter(); filter.addAction(Intent.ACTION_PACKAGE_CHANGED); @@ -635,6 +649,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return mIWindowManager; } + private NotificationManager getNotificationManager() { + if (mNotificationManager == null) { + mNotificationManager = + (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); + } + return mNotificationManager; + } + ActiveAdmin getActiveAdminUncheckedLocked(ComponentName who, int userHandle) { ActiveAdmin admin = getUserData(userHandle).mAdminMap.get(who); if (admin != null @@ -1053,6 +1075,63 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } + private void manageMonitoringCertificateNotification(Intent intent) { + final NotificationManager notificationManager = getNotificationManager(); + + final boolean hasCert = DevicePolicyManager.hasAnyCaCertsInstalled(); + if (! hasCert) { + if (intent.getAction().equals(KeyChain.ACTION_STORAGE_CHANGED)) { + UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE); + for (UserInfo user : um.getUsers()) { + notificationManager.cancelAsUser( + null, MONITORING_CERT_NOTIFICATION_ID, user.getUserHandle()); + } + } + return; + } + final boolean isManaged = getDeviceOwner() != null; + int smallIconId; + String contentText; + if (isManaged) { + contentText = mContext.getString(R.string.ssl_ca_cert_noti_managed, + getDeviceOwnerName()); + smallIconId = R.drawable.stat_sys_certificate_info; + } else { + contentText = mContext.getString(R.string.ssl_ca_cert_noti_by_unknown); + smallIconId = android.R.drawable.stat_sys_warning; + } + + Intent dialogIntent = new Intent(Settings.ACTION_MONITORING_CERT_INFO); + dialogIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + dialogIntent.setPackage("com.android.settings"); + // Notification will be sent individually to all users. The activity should start as + // whichever user is current when it starts. + PendingIntent notifyIntent = PendingIntent.getActivityAsUser(mContext, 0, dialogIntent, + PendingIntent.FLAG_UPDATE_CURRENT, null, UserHandle.CURRENT); + + Notification noti = new Notification.Builder(mContext) + .setSmallIcon(smallIconId) + .setContentTitle(mContext.getString(R.string.ssl_ca_cert_warning)) + .setContentText(contentText) + .setContentIntent(notifyIntent) + .setPriority(Notification.PRIORITY_HIGH) + .setShowWhen(false) + .build(); + + // If this is a boot intent, this will fire for each user. But if this is a storage changed + // intent, it will fire once, so we need to notify all users. + if (intent.getAction().equals(KeyChain.ACTION_STORAGE_CHANGED)) { + UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE); + for (UserInfo user : um.getUsers()) { + notificationManager.notifyAsUser( + null, MONITORING_CERT_NOTIFICATION_ID, noti, user.getUserHandle()); + } + } else { + notificationManager.notifyAsUser( + null, MONITORING_CERT_NOTIFICATION_ID, noti, UserHandle.CURRENT); + } + } + /** * @param adminReceiver The admin to add * @param refreshing true = update an active admin, no error |