From 2140529d9b8e116d88c2a385a0b3179c2ede5ad7 Mon Sep 17 00:00:00 2001 From: Erik Kline Date: Wed, 21 Mar 2018 07:18:33 -0700 Subject: [PATCH] Support bypassing TLS in the framework This change comprises the following parts: [1] android.net.dns.ResolvUtil, containing methods that encapsulate the use of the high bit in netids used in DNS resolution contexts. [2] Updates to captive portal apps to call the ResolvUtil method that enables DNS-over-TLS bypass for the captive portal app process. Test: as follows - builds - flashes - boots - runtest frameworks-net passes Bug: 64133961 Bug: 72345192 Change-Id: I2072c1f68d6978fa0d7e9d8693135a2c51bb0f87 --- packages/CaptivePortalLogin/Android.mk | 2 +- .../CaptivePortalLoginActivity.java | 3 + packages/CarrierDefaultApp/Android.mk | 2 + .../CaptivePortalLoginActivity.java | 3 + .../android/server/connectivity/DnsManager.java | 36 ++++-------- services/net/java/android/net/dns/ResolvUtil.java | 65 ++++++++++++++++++++++ 6 files changed, 86 insertions(+), 25 deletions(-) create mode 100644 services/net/java/android/net/dns/ResolvUtil.java diff --git a/packages/CaptivePortalLogin/Android.mk b/packages/CaptivePortalLogin/Android.mk index 7dc23ff8e8b8..8a96b1693dc1 100644 --- a/packages/CaptivePortalLogin/Android.mk +++ b/packages/CaptivePortalLogin/Android.mk @@ -2,7 +2,7 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS := optional -LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 +LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 services.net LOCAL_SRC_FILES := $(call all-java-files-under, src) diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java index 7828c4caa7ab..2a1bbedd86d4 100644 --- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java +++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java @@ -30,6 +30,7 @@ import android.net.NetworkInfo; import android.net.NetworkRequest; import android.net.Proxy; import android.net.Uri; +import android.net.dns.ResolvUtil; import android.net.http.SslError; import android.os.Build; import android.os.Bundle; @@ -118,6 +119,8 @@ public class CaptivePortalLoginActivity extends Activity { // Also initializes proxy system properties. mCm.bindProcessToNetwork(mNetwork); + mCm.setProcessDefaultNetworkForHostResolution( + ResolvUtil.getNetworkWithUseLocalNameserversFlag(mNetwork)); // Proxy system properties must be initialized before setContentView is called because // setContentView initializes the WebView logic which in turn reads the system properties. diff --git a/packages/CarrierDefaultApp/Android.mk b/packages/CarrierDefaultApp/Android.mk index df88afdcf041..5068b3beb7a1 100644 --- a/packages/CarrierDefaultApp/Android.mk +++ b/packages/CarrierDefaultApp/Android.mk @@ -9,6 +9,8 @@ LOCAL_PACKAGE_NAME := CarrierDefaultApp LOCAL_PRIVATE_PLATFORM_APIS := true LOCAL_CERTIFICATE := platform +LOCAL_STATIC_JAVA_LIBRARIES := services.net + include $(BUILD_PACKAGE) # This finds and builds the test apk as well, so a single make does both. diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java index 95ec83dd9e14..7479d9aa773b 100644 --- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java +++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java @@ -32,6 +32,7 @@ import android.net.NetworkRequest; import android.net.Proxy; import android.net.TrafficStats; import android.net.Uri; +import android.net.dns.ResolvUtil; import android.net.http.SslError; import android.os.Bundle; import android.telephony.CarrierConfigManager; @@ -115,6 +116,8 @@ public class CaptivePortalLoginActivity extends Activity { requestNetworkForCaptivePortal(); } else { mCm.bindProcessToNetwork(mNetwork); + mCm.setProcessDefaultNetworkForHostResolution( + ResolvUtil.getNetworkWithUseLocalNameserversFlag(mNetwork)); // Start initial page load so WebView finishes loading proxy settings. // Actual load of mUrl is initiated by MyWebViewClient. mWebView.loadData("", "text/html", null); diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java index 36f5a6c354f2..55798491cdef 100644 --- a/services/core/java/com/android/server/connectivity/DnsManager.java +++ b/services/core/java/com/android/server/connectivity/DnsManager.java @@ -34,22 +34,19 @@ import android.net.LinkProperties; import android.net.Network; import android.net.NetworkUtils; import android.net.Uri; +import android.net.dns.ResolvUtil; import android.os.Binder; import android.os.INetworkManagementService; import android.os.Handler; import android.os.UserHandle; import android.provider.Settings; -import android.system.GaiException; -import android.system.OsConstants; -import android.system.StructAddrinfo; import android.text.TextUtils; import android.util.Slog; import com.android.server.connectivity.MockableSystemProperties; -import libcore.io.Libcore; - import java.net.InetAddress; +import java.net.UnknownHostException; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; @@ -126,28 +123,19 @@ public class DnsManager { } public static PrivateDnsConfig tryBlockingResolveOf(Network network, String name) { - final StructAddrinfo hints = new StructAddrinfo(); - // Unnecessary, but expressly no AI_ADDRCONFIG. - hints.ai_flags = 0; - // Fetch all IP addresses at once to minimize re-resolution. - hints.ai_family = OsConstants.AF_UNSPEC; - hints.ai_socktype = OsConstants.SOCK_DGRAM; - try { - final InetAddress[] ips = Libcore.os.android_getaddrinfo(name, hints, network.netId); - if (ips != null && ips.length > 0) { - return new PrivateDnsConfig(name, ips); - } - } catch (GaiException ignored) {} - - return null; + final InetAddress[] ips = ResolvUtil.blockingResolveAllLocally(network, name); + return new PrivateDnsConfig(name, ips); + } catch (UnknownHostException uhe) { + return new PrivateDnsConfig(name, null); + } } public static Uri[] getPrivateDnsSettingsUris() { - final Uri[] uris = new Uri[2]; - uris[0] = Settings.Global.getUriFor(PRIVATE_DNS_MODE); - uris[1] = Settings.Global.getUriFor(PRIVATE_DNS_SPECIFIER); - return uris; + return new Uri[]{ + Settings.Global.getUriFor(PRIVATE_DNS_MODE), + Settings.Global.getUriFor(PRIVATE_DNS_SPECIFIER), + }; } private final Context mContext; @@ -203,7 +191,7 @@ public class DnsManager { // NetworkMonitor to decide which networks need validation and runs the // blocking calls to resolve Private DNS strict mode hostnames. // - // At this time we do attempt to enable Private DNS on non-Internet + // At this time we do not attempt to enable Private DNS on non-Internet // networks like IMS. final PrivateDnsConfig privateDnsCfg = mPrivateDnsMap.get(netId); diff --git a/services/net/java/android/net/dns/ResolvUtil.java b/services/net/java/android/net/dns/ResolvUtil.java new file mode 100644 index 000000000000..97d20f4b2922 --- /dev/null +++ b/services/net/java/android/net/dns/ResolvUtil.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.dns; + +import android.net.Network; +import android.net.NetworkUtils; +import android.system.GaiException; +import android.system.OsConstants; +import android.system.StructAddrinfo; + +import libcore.io.Libcore; + +import java.net.InetAddress; +import java.net.UnknownHostException; + + +/** + * DNS resolution utility class. + * + * @hide + */ +public class ResolvUtil { + // Non-portable DNS resolution flag. + private static final long NETID_USE_LOCAL_NAMESERVERS = 0x80000000L; + + private ResolvUtil() {} + + public static InetAddress[] blockingResolveAllLocally(Network network, String name) + throws UnknownHostException { + final StructAddrinfo hints = new StructAddrinfo(); + // Unnecessary, but expressly no AI_ADDRCONFIG. + hints.ai_flags = 0; + // Fetch all IP addresses at once to minimize re-resolution. + hints.ai_family = OsConstants.AF_UNSPEC; + hints.ai_socktype = OsConstants.SOCK_DGRAM; + + final Network networkForResolv = getNetworkWithUseLocalNameserversFlag(network); + + try { + return Libcore.os.android_getaddrinfo(name, hints, (int) networkForResolv.netId); + } catch (GaiException gai) { + gai.rethrowAsUnknownHostException(name + ": TLS-bypass resolution failed"); + return null; // keep compiler quiet + } + } + + public static Network getNetworkWithUseLocalNameserversFlag(Network network) { + final long netidForResolv = NETID_USE_LOCAL_NAMESERVERS | (long) network.netId; + return new Network((int) netidForResolv); + } +} -- 2.11.0