Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2eb3473d authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Private DNS connectivity check"

parents e770d22d 309e071b
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -6664,7 +6664,7 @@ package android.app.admin {
    method public void setDelegatedScopes(android.content.ComponentName, java.lang.String, java.util.List<java.lang.String>);
    method public void setDeviceOwnerLockScreenInfo(android.content.ComponentName, java.lang.CharSequence);
    method public void setEndUserSessionMessage(android.content.ComponentName, java.lang.CharSequence);
    method public void setGlobalPrivateDns(android.content.ComponentName, int, java.lang.String);
    method public int setGlobalPrivateDns(android.content.ComponentName, int, java.lang.String);
    method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
    method public void setKeepUninstalledPackages(android.content.ComponentName, java.util.List<java.lang.String>);
    method public boolean setKeyPairCertificate(android.content.ComponentName, java.lang.String, java.util.List<java.security.cert.Certificate>, boolean);
@@ -6845,6 +6845,9 @@ package android.app.admin {
    field public static final int PRIVATE_DNS_MODE_OPPORTUNISTIC = 2; // 0x2
    field public static final int PRIVATE_DNS_MODE_PROVIDER_HOSTNAME = 3; // 0x3
    field public static final int PRIVATE_DNS_MODE_UNKNOWN = 0; // 0x0
    field public static final int PRIVATE_DNS_SET_ERROR_FAILURE_SETTING = 2; // 0x2
    field public static final int PRIVATE_DNS_SET_ERROR_HOST_NOT_SERVING = 1; // 0x1
    field public static final int PRIVATE_DNS_SET_SUCCESS = 0; // 0x0
    field public static final int RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT = 2; // 0x2
    field public static final int RESET_PASSWORD_REQUIRE_ENTRY = 1; // 0x1
    field public static final int SKIP_SETUP_WIZARD = 1; // 0x1
+56 −3
Original line number Diff line number Diff line
@@ -49,6 +49,8 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ParceledListSlice;
import android.content.pm.UserInfo;
import android.graphics.Bitmap;
import android.net.NetworkUtils;
import android.net.PrivateDnsConnectivityChecker;
import android.net.ProxyInfo;
import android.net.Uri;
import android.os.Binder;
@@ -79,6 +81,7 @@ import android.security.keystore.StrongBoxUnavailableException;
import android.service.restrictions.RestrictionsReceiver;
import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;

@@ -2031,6 +2034,35 @@ public class DevicePolicyManager {
    @Retention(RetentionPolicy.SOURCE)
    public @interface InstallUpdateCallbackErrorConstants {}

    /**
     * The selected mode has been set successfully. If the mode is
     * {@code PRIVATE_DNS_MODE_PROVIDER_HOSTNAME} then it implies the supplied host is valid
     * and reachable.
     */
    public static final int PRIVATE_DNS_SET_SUCCESS = 0;

    /**
     * If the {@code privateDnsHost} provided was of a valid hostname but that host was found
     * to not support DNS-over-TLS.
     */
    public static final int PRIVATE_DNS_SET_ERROR_HOST_NOT_SERVING = 1;

    /**
     * General failure to set the Private DNS mode, not due to one of the reasons listed above.
     */
    public static final int PRIVATE_DNS_SET_ERROR_FAILURE_SETTING = 2;

    /**
     * @hide
     */
    @IntDef(prefix = {"PRIVATE_DNS_SET_"}, value = {
            PRIVATE_DNS_SET_SUCCESS,
            PRIVATE_DNS_SET_ERROR_HOST_NOT_SERVING,
            PRIVATE_DNS_SET_ERROR_FAILURE_SETTING
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface SetPrivateDnsModeResultConstants {}

    /**
     * Return true if the given administrator component is currently active (enabled) in the system.
     *
@@ -9897,6 +9929,16 @@ public class DevicePolicyManager {
     * Sets the global Private DNS mode and host to be used.
     * May only be called by the device owner.
     *
     * <p>Note that in case a Private DNS resolver is specified, the method is blocking as it
     * will perform a connectivity check to the resolver, to ensure it is valid. Because of that,
     * the method should not be called on any thread that relates to user interaction, such as the
     * UI thread.
     *
     * <p>In case a VPN is used in conjunction with Private DNS resolver, the Private DNS resolver
     * must be reachable both from within and outside the VPN. Otherwise, the device may lose
     * the ability to resolve hostnames as system traffic to the resolver may not go through the
     * VPN.
     *
     * @param admin which {@link DeviceAdminReceiver} this request is associated with.
     * @param mode Which mode to set - either {@code PRIVATE_DNS_MODE_OPPORTUNISTIC} or
     *             {@code PRIVATE_DNS_MODE_PROVIDER_HOSTNAME}.
@@ -9906,6 +9948,9 @@ public class DevicePolicyManager {
     * @param privateDnsHost The hostname of a server that implements DNS over TLS (RFC7858), if
     *                       {@code PRIVATE_DNS_MODE_PROVIDER_HOSTNAME} was specified as the mode,
     *                       null otherwise.
     *
     * @return One of the values in {@link SetPrivateDnsModeResultConstants}.
     *
     * @throws IllegalArgumentException in the following cases: if a {@code privateDnsHost} was
     * provided but the mode was not {@code PRIVATE_DNS_MODE_PROVIDER_HOSTNAME}, if the mode
     * specified was {@code PRIVATE_DNS_MODE_PROVIDER_HOSTNAME} but {@code privateDnsHost} does
@@ -9913,15 +9958,23 @@ public class DevicePolicyManager {
     *
     * @throws SecurityException if the caller is not the device owner.
     */
    public void setGlobalPrivateDns(@NonNull ComponentName admin,
    public int setGlobalPrivateDns(@NonNull ComponentName admin,
            @PrivateDnsMode int mode, @Nullable String privateDnsHost) {
        throwIfParentInstance("setGlobalPrivateDns");

        if (mService == null) {
            return;
            return PRIVATE_DNS_SET_ERROR_FAILURE_SETTING;
        }

        if (mode == PRIVATE_DNS_MODE_PROVIDER_HOSTNAME && !TextUtils.isEmpty(privateDnsHost)
                && NetworkUtils.isWeaklyValidatedHostname(privateDnsHost)) {
            if (!PrivateDnsConnectivityChecker.canConnectToPrivateDnsServer(privateDnsHost)) {
                return PRIVATE_DNS_SET_ERROR_HOST_NOT_SERVING;
            }
        }

        try {
            mService.setGlobalPrivateDns(admin, mode, privateDnsHost);
            return mService.setGlobalPrivateDns(admin, mode, privateDnsHost);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
+1 −1
Original line number Diff line number Diff line
@@ -415,7 +415,7 @@ interface IDevicePolicyManager {

    boolean isMeteredDataDisabledPackageForUser(in ComponentName admin, String packageName, int userId);

    void setGlobalPrivateDns(in ComponentName admin, int mode, in String privateDnsHost);
    int setGlobalPrivateDns(in ComponentName admin, int mode, in String privateDnsHost);
    int getGlobalPrivateDnsMode(in ComponentName admin);
    String getGlobalPrivateDnsHost(in ComponentName admin);

+64 −0
Original line number Diff line number Diff line
/*
 * 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;

import android.annotation.NonNull;
import android.util.Log;

import java.io.IOException;
import java.net.InetSocketAddress;

import javax.net.SocketFactory;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

/**
 * Class for testing connectivity to DNS-over-TLS servers.
 * {@hide}
 */
public class PrivateDnsConnectivityChecker {
    private static final String TAG = "NetworkUtils";

    private static final int PRIVATE_DNS_PORT = 853;
    private static final int CONNECTION_TIMEOUT_MS = 5000;

    private PrivateDnsConnectivityChecker() { }

    /**
     * checks that a provided host can perform a TLS handshake on port 853.
     * @param hostname host to connect to.
     */
    public static boolean canConnectToPrivateDnsServer(@NonNull String hostname) {
        final SocketFactory factory = SSLSocketFactory.getDefault();
        TrafficStats.setThreadStatsTag(TrafficStats.TAG_SYSTEM_APP);

        try (SSLSocket socket = (SSLSocket) factory.createSocket()) {
            socket.setSoTimeout(CONNECTION_TIMEOUT_MS);
            socket.connect(new InetSocketAddress(hostname, PRIVATE_DNS_PORT));
            if (!socket.isConnected()) {
                Log.w(TAG, String.format("Connection to %s failed.", hostname));
                return false;
            }
            socket.startHandshake();
            Log.w(TAG, String.format("TLS handshake to %s succeeded.", hostname));
            return true;
        } catch (IOException e) {
            Log.w(TAG, String.format("TLS handshake to %s failed.", hostname), e);
            return false;
        }
    }
}
+2 −1
Original line number Diff line number Diff line
@@ -81,7 +81,8 @@ abstract class BaseIDevicePolicyManager extends IDevicePolicyManager.Stub {
    }

    @Override
    public void setGlobalPrivateDns(ComponentName who, int mode, String privateDnsHost) {
    public int setGlobalPrivateDns(ComponentName who, int mode, String privateDnsHost) {
        return DevicePolicyManager.PRIVATE_DNS_SET_ERROR_FAILURE_SETTING;
    }

    @Override
Loading