From 4d092238de2de290f018c41c1134b8b89baa635d Mon Sep 17 00:00:00 2001 From: Erik Kline Date: Mon, 30 Oct 2017 15:29:44 +0900 Subject: [PATCH] Replace dns_tls with private_dns_mode setting Also includes: - SettingsLib strings used in PrivateDnsModeDialogPreference interaction in the Settings app - rename ContentResolver "resolver" in methods working with DNS resolvers (too confusing) Test: as follows - built - flashed - booted - runtest frameworks-net - no new failures in SettingsBackupTest nor in SettingsProviderTest - manual interaction with developer option works Bug: 34953048 Bug: 64133961 Change-Id: Ia7502916db9ffa0792e1e500a35e34d06a88e79d --- .../java/android/net/ConnectivityManager.java | 29 +++++++++++++ core/java/android/provider/Settings.java | 17 ++++++-- .../android/provider/SettingsBackupTest.java | 1 - packages/SettingsLib/res/values/strings.xml | 12 +++--- .../server/NetworkManagementService.java | 43 ++++++++++++++++--- 5 files changed, 86 insertions(+), 16 deletions(-) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 0ccebc1c7a55e..6bf14257c772a 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -619,6 +619,35 @@ public class ConnectivityManager { */ public static final int NETID_UNSET = 0; + /** + * Private DNS Mode values. + * + * The "private_dns_mode" global setting stores a String value which is + * expected to be one of the following. + */ + + /** + * @hide + */ + public static final String PRIVATE_DNS_MODE_OFF = "off"; + /** + * @hide + */ + public static final String PRIVATE_DNS_MODE_OPPORTUNISTIC = "opportunistic"; + /** + * @hide + */ + public static final String PRIVATE_DNS_MODE_PROVIDER_HOSTNAME = "hostname"; + /** + * The default Private DNS mode. + * + * This may change from release to release or may become dependent upon + * the capabilities of the underlying platform. + * + * @hide + */ + public static final String PRIVATE_DNS_DEFAULT_MODE = PRIVATE_DNS_MODE_OPPORTUNISTIC; + private final IConnectivityManager mService; /** * A kludge to facilitate static access where a Context pointer isn't available, like in the diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index cbeeabe26335c..6981ffcae72d0 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -9158,11 +9158,20 @@ public final class Settings { public static final String DEFAULT_DNS_SERVER = "default_dns_server"; /** - * Whether to disable DNS over TLS (boolean) + * The requested Private DNS mode (string), and an accompanying specifier (string). + * + * Currently, the specifier holds the chosen provider name when the mode requests + * a specific provider. It may be used to store the provider name even when the + * mode changes so that temporarily disabling and re-enabling the specific + * provider mode does not necessitate retyping the provider hostname. * * @hide */ - public static final String DNS_TLS_DISABLED = "dns_tls_disabled"; + public static final String PRIVATE_DNS_MODE = "private_dns_mode"; + /** + * @hide + */ + public static final String PRIVATE_DNS_SPECIFIER = "private_dns_specifier"; /** {@hide} */ public static final String @@ -10204,7 +10213,9 @@ public final class Settings { DOCK_AUDIO_MEDIA_ENABLED, ENCODED_SURROUND_OUTPUT, LOW_POWER_MODE_TRIGGER_LEVEL, - BLUETOOTH_ON + BLUETOOTH_ON, + PRIVATE_DNS_MODE, + PRIVATE_DNS_SPECIFIER }; private static final ContentProviderHolder sProviderHolder = diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java index 88f2b4b7aece9..a979ac82dafa8 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -177,7 +177,6 @@ public class SettingsBackupTest { Settings.Global.DNS_RESOLVER_MIN_SAMPLES, Settings.Global.DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS, Settings.Global.DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT, - Settings.Global.DNS_TLS_DISABLED, Settings.Global.DOCK_SOUNDS_ENABLED_WHEN_ACCESSIBILITY, Settings.Global.DOWNLOAD_MAX_BYTES_OVER_MOBILE, Settings.Global.DOWNLOAD_RECOMMENDED_MAX_BYTES_OVER_MOBILE, diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index e981e26b6fc67..a73f800fb6899 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -505,11 +505,13 @@ Streaming: %1$s - - DNS over TLS - - If enabled, attempt DNS over TLS on port 853. + + Private DNS + Select Private DNS Mode + Off + Opportunistic + Private DNS provider hostname + Enter hostname of DNS provider Show options for wireless display certification diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index b1d6f7353bdb4..7c73818a70fa3 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -20,6 +20,9 @@ import static android.Manifest.permission.CONNECTIVITY_INTERNAL; import static android.Manifest.permission.DUMP; import static android.Manifest.permission.NETWORK_STACK; import static android.Manifest.permission.SHUTDOWN; +import static android.net.ConnectivityManager.PRIVATE_DNS_DEFAULT_MODE; +import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC; +import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME; import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_DOZABLE; import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE; import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_NONE; @@ -92,6 +95,7 @@ import android.telephony.DataConnectionRealTimeInfo; import android.telephony.PhoneStateListener; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; +import android.text.TextUtils; import android.util.Log; import android.util.Slog; import android.util.SparseBooleanArray; @@ -1946,9 +1950,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub public void setDnsConfigurationForNetwork(int netId, String[] servers, String domains) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); - ContentResolver resolver = mContext.getContentResolver(); + final ContentResolver cr = mContext.getContentResolver(); - int sampleValidity = Settings.Global.getInt(resolver, + int sampleValidity = Settings.Global.getInt(cr, Settings.Global.DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS, DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS); if (sampleValidity < 0 || sampleValidity > 65535) { @@ -1957,7 +1961,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub sampleValidity = DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS; } - int successThreshold = Settings.Global.getInt(resolver, + int successThreshold = Settings.Global.getInt(cr, Settings.Global.DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT, DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT); if (successThreshold < 0 || successThreshold > 100) { @@ -1966,9 +1970,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub successThreshold = DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT; } - int minSamples = Settings.Global.getInt(resolver, + int minSamples = Settings.Global.getInt(cr, Settings.Global.DNS_RESOLVER_MIN_SAMPLES, DNS_RESOLVER_DEFAULT_MIN_SAMPLES); - int maxSamples = Settings.Global.getInt(resolver, + int maxSamples = Settings.Global.getInt(cr, Settings.Global.DNS_RESOLVER_MAX_SAMPLES, DNS_RESOLVER_DEFAULT_MAX_SAMPLES); if (minSamples < 0 || minSamples > maxSamples || maxSamples > 64) { Slog.w(TAG, "Invalid sample count (min, max)=(" + minSamples + ", " + maxSamples + @@ -1980,8 +1984,24 @@ public class NetworkManagementService extends INetworkManagementService.Stub final String[] domainStrs = domains == null ? new String[0] : domains.split(" "); final int[] params = { sampleValidity, successThreshold, minSamples, maxSamples }; - final boolean useTls = Settings.Global.getInt(resolver, - Settings.Global.DNS_TLS_DISABLED, 0) == 0; + final boolean useTls = shouldUseTls(cr); + // TODO: Populate tlsHostname once it's decided how the hostname's IP + // addresses will be resolved: + // + // [1] network-provided DNS servers are included here with the + // hostname and netd will use the network-provided servers to + // resolve the hostname and fix up its internal structures, or + // + // [2] network-provided DNS servers are included here without the + // hostname, the ConnectivityService layer resolves the given + // hostname, and then reconfigures netd with this information. + // + // In practice, there will always be a need for ConnectivityService or + // the captive portal app to use the network-provided services to make + // some queries. This argues in favor of [1], in concert with another + // mechanism, perhaps setting a high bit in the netid, to indicate + // via existing DNS APIs which set of servers (network-provided or + // non-network-provided private DNS) should be queried. final String tlsHostname = ""; final String[] tlsFingerprints = new String[0]; try { @@ -1992,6 +2012,15 @@ public class NetworkManagementService extends INetworkManagementService.Stub } } + private static boolean shouldUseTls(ContentResolver cr) { + String privateDns = Settings.Global.getString(cr, Settings.Global.PRIVATE_DNS_MODE); + if (TextUtils.isEmpty(privateDns)) { + privateDns = PRIVATE_DNS_DEFAULT_MODE; + } + return privateDns.equals(PRIVATE_DNS_MODE_OPPORTUNISTIC) || + privateDns.startsWith(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME); + } + @Override public void addVpnUidRanges(int netId, UidRange[] ranges) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);