OSDN Git Service

Fixup SntpClient to bypass Private DNS
authorErik Kline <ek@google.com>
Tue, 22 May 2018 12:15:49 +0000 (21:15 +0900)
committerErik Kline <ek@google.com>
Wed, 23 May 2018 07:03:03 +0000 (16:03 +0900)
NTP may be necessary in order to validate Private DNS certificates,
so it should be allowed to bypass Private DNS.

Test: as follows
    - built, flashed, booted
    - tcpdump for port 53; adb shell am restart
      queries for the NTP hostname appear in the clear
    - runtest frameworks-net passes
Bug: 64133961
Bug: 80118648
Change-Id: Id9ceb3fcaaffb48cbbd4cd381d48cae991572c9e

core/java/android/net/Network.java
core/java/android/net/SntpClient.java

index 15a0ee5..d75d439 100644 (file)
@@ -85,6 +85,21 @@ public class Network implements Parcelable {
     private static final long HANDLE_MAGIC = 0xcafed00dL;
     private static final int HANDLE_MAGIC_SIZE = 32;
 
+    // A boolean to control how getAllByName()/getByName() behaves in the face
+    // of Private DNS.
+    //
+    // When true, these calls will request that DNS resolution bypass any
+    // Private DNS that might otherwise apply. Use of this feature is restricted
+    // and permission checks are made by netd (attempts to bypass Private DNS
+    // without appropriate permission are silently turned into vanilla DNS
+    // requests). This only affects DNS queries made using this network object.
+    //
+    // It it not parceled to receivers because (a) it can be set or cleared at
+    // anytime and (b) receivers should be explicit about attempts to bypass
+    // Private DNS so that the intent of the code is easily determined and
+    // code search audits are possible.
+    private boolean mPrivateDnsBypass = false;
+
     /**
      * @hide
      */
@@ -108,7 +123,7 @@ public class Network implements Parcelable {
      * @throws UnknownHostException if the address lookup fails.
      */
     public InetAddress[] getAllByName(String host) throws UnknownHostException {
-        return InetAddress.getAllByNameOnNet(host, netId);
+        return InetAddress.getAllByNameOnNet(host, getNetIdForResolv());
     }
 
     /**
@@ -122,7 +137,32 @@ public class Network implements Parcelable {
      *             if the address lookup fails.
      */
     public InetAddress getByName(String host) throws UnknownHostException {
-        return InetAddress.getByNameOnNet(host, netId);
+        return InetAddress.getByNameOnNet(host, getNetIdForResolv());
+    }
+
+    /**
+     * Specify whether or not Private DNS should be bypassed when attempting
+     * to use {@link getAllByName()}/{@link getByName()} methods on the given
+     * instance for hostname resolution.
+     *
+     * @hide
+     */
+    public void setPrivateDnsBypass(boolean bypass) {
+        mPrivateDnsBypass = bypass;
+    }
+
+    /**
+     * Returns a netid marked with the Private DNS bypass flag.
+     *
+     * This flag must be kept in sync with the NETID_USE_LOCAL_NAMESERVERS flag
+     * in system/netd/include/NetdClient.h.
+     *
+     * @hide
+     */
+    public int getNetIdForResolv() {
+        return mPrivateDnsBypass
+                ? (int) (0x80000000L | (long) netId)  // Non-portable DNS resolution flag.
+                : netId;
     }
 
     /**
index 66cdc99..ddf63ca 100644 (file)
@@ -84,6 +84,10 @@ public class SntpClient {
      * @return true if the transaction was successful.
      */
     public boolean requestTime(String host, int timeout, Network network) {
+        // This flag only affects DNS resolution and not other socket semantics,
+        // therefore it's safe to set unilaterally rather than take more
+        // defensive measures like making a copy.
+        network.setPrivateDnsBypass(true);
         InetAddress address = null;
         try {
             address = network.getByName(host);