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

Commit 1e06786b authored by Thiébaud Weksteen's avatar Thiébaud Weksteen Committed by Android (Google) Code Review
Browse files

Merge "Define new NetworkSecurityConfig for localhost" into main

parents c524c81c 2b8cabc8
Loading
Loading
Loading
Loading
+33 −23
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ public final class ApplicationConfig {

    private Set<Pair<Domain, NetworkSecurityConfig>> mConfigs;
    private NetworkSecurityConfig mDefaultConfig;
    private NetworkSecurityConfig mLocalhostConfig;
    private X509TrustManager mTrustManager;

    private ConfigSource mConfigSource;
@@ -62,8 +63,10 @@ public final class ApplicationConfig {

    /**
     * Get the {@link NetworkSecurityConfig} corresponding to the provided hostname.
     * When matching the most specific matching domain rule will be used, if no match exists
     * then the default configuration will be returned.
     * The most specific matching domain rule will be used. If no match exists
     * and the hostname is considered to be localhost (according to {@link
     * Domain#isLocalhost()}), the localhost configuration will be returned.
     * Otherwise, the default configuration will be returned.
     *
     * {@code NetworkSecurityConfig} objects returned by this method can be safely cached for
     * {@code hostname}. Subsequent calls with the same hostname will always return the same
@@ -74,7 +77,8 @@ public final class ApplicationConfig {
     */
    public NetworkSecurityConfig getConfigForHostname(String hostname) {
        ensureInitialized();
        if (hostname == null || hostname.isEmpty() || mConfigs == null) {
        if (hostname == null || hostname.isEmpty()
                || (mConfigs == null && mLocalhostConfig == null)) {
            return mDefaultConfig;
        }
        if (hostname.charAt(0) ==  '.') {
@@ -89,7 +93,7 @@ public final class ApplicationConfig {
        }
        // Find the Domain -> NetworkSecurityConfig entry with the most specific matching
        // Domain entry for hostname.
        // TODO: Use a smarter data structure for the lookup.
        if (mConfigs != null) {
            Pair<Domain, NetworkSecurityConfig> bestMatch = null;
            for (Pair<Domain, NetworkSecurityConfig> entry : mConfigs) {
                Domain domain = entry.first;
@@ -102,7 +106,8 @@ public final class ApplicationConfig {
                // sub-domain of the Domain.
                if (domain.subdomainsIncluded
                        && hostname.endsWith(domain.hostname)
                    && hostname.charAt(hostname.length() - domain.hostname.length() - 1) == '.') {
                        && hostname.charAt(
                                hostname.length() - domain.hostname.length() - 1) == '.') {
                    if (bestMatch == null) {
                        bestMatch = entry;
                    } else if (domain.hostname.length() > bestMatch.first.hostname.length()) {
@@ -113,6 +118,10 @@ public final class ApplicationConfig {
            if (bestMatch != null) {
                return bestMatch.second;
            }
        }
        if (mLocalhostConfig != null && Domain.isLocalhost(hostname)) {
            return mLocalhostConfig;
        }
        // If no match was found use the default configuration.
        return mDefaultConfig;
    }
@@ -195,6 +204,7 @@ public final class ApplicationConfig {
            }
            mConfigs = mConfigSource.getPerDomainConfigs();
            mDefaultConfig = mConfigSource.getDefaultConfig();
            mLocalhostConfig = mConfigSource.getLocalhostConfig();
            mConfigSource = null;
            mTrustManager = new RootTrustManager(this);
            mInitialized = true;
+13 −0
Original line number Diff line number Diff line
@@ -16,11 +16,24 @@

package android.security.net.config;

import android.annotation.Nullable;
import android.util.Pair;

import java.util.Set;

/** @hide */
public interface ConfigSource {

    /** Returns the set of configurations that are associated with a Domain. */
    @Nullable
    Set<Pair<Domain, NetworkSecurityConfig>> getPerDomainConfigs();

    /** Returns the default NetworkSecurityConfig */
    NetworkSecurityConfig getDefaultConfig();

    /** Returns the NetworkSecurityConfig associated with localhost.
     *  See {@link Domain#isLocalhost()} for the exact definition.
     */
    @Nullable
    NetworkSecurityConfig getLocalhostConfig();
}
+33 −0
Original line number Diff line number Diff line
@@ -17,11 +17,17 @@
package android.security.net.config;

import android.annotation.Nullable;
import android.net.InetAddresses;

import java.net.InetAddress;
import java.util.Locale;
import java.util.Set;


/** @hide */
public final class Domain {
    private static final Set<String> LOCALHOSTS = Set.of("localhost", "ip6-localhost");

    /**
     * Lower case hostname for this domain rule.
     */
@@ -57,4 +63,31 @@ public final class Domain {
        return otherDomain.subdomainsIncluded == this.subdomainsIncluded &&
                otherDomain.hostname.equals(this.hostname);
    }

    public boolean isLocalhost() {
        return isLocalhost(this.hostname);
    }

    /**
     * Whether the hostname is considered to be localhost or not.
     */
    public static boolean isLocalhost(String hostname) {
        if (LOCALHOSTS.contains(hostname)) {
            return true;
        }
        // RFC 2732: To use a literal IPv6 address in a URL, the literal
        // address should be enclosed in "[" and "]" characters.
        if (hostname.charAt(0) == '[' && hostname.charAt(hostname.length() - 1) == ']') {
            hostname = hostname.substring(1, hostname.length() - 1);
        }
        // parseNumericAddress raises an exception if the address is not valid.
        // We could use isNumericAddress beforehand to avoid the exception, but
        // this would imply parsing the address twice. Simply ignore
        // IllegalArgumentException.
        try {
            InetAddress addr = InetAddresses.parseNumericAddress(hostname);
            return addr.isLoopbackAddress();
        } catch (IllegalArgumentException e) { }
        return false;
    }
}
+5 −0
Original line number Diff line number Diff line
@@ -45,5 +45,10 @@ class KeyStoreConfigSource implements ConfigSource {
    public NetworkSecurityConfig getDefaultConfig() {
        return mConfig;
    }

    @Override
    public NetworkSecurityConfig getLocalhostConfig() {
        return null;
    }
}
+18 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package android.security.net.config;

import static com.android.org.conscrypt.net.flags.Flags.networkSecurityConfigLocalhost;

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.util.Log;
@@ -50,6 +52,11 @@ public class ManifestConfigSource implements ConfigSource {
        return getConfigSource().getDefaultConfig();
    }

    @Override
    public NetworkSecurityConfig getLocalhostConfig() {
        return getConfigSource().getLocalhostConfig();
    }

    private ConfigSource getConfigSource() {
        synchronized (mLock) {
            if (mConfigSource != null) {
@@ -86,11 +93,17 @@ public class ManifestConfigSource implements ConfigSource {
    private static final class DefaultConfigSource implements ConfigSource {

        private final NetworkSecurityConfig mDefaultConfig;
        private final NetworkSecurityConfig mLocalhostConfig;

        DefaultConfigSource(boolean usesCleartextTraffic, ApplicationInfo info) {
            mDefaultConfig = NetworkSecurityConfig.getDefaultBuilder(info)
                    .setCleartextTrafficPermitted(usesCleartextTraffic)
                    .build();
            if (networkSecurityConfigLocalhost()) {
                mLocalhostConfig = NetworkSecurityConfig.getLocalhostBuilder().build();
            } else {
                mLocalhostConfig = null;
            }
        }

        @Override
@@ -98,6 +111,11 @@ public class ManifestConfigSource implements ConfigSource {
            return mDefaultConfig;
        }

        @Override
        public NetworkSecurityConfig getLocalhostConfig() {
            return mLocalhostConfig;
        }

        @Override
        public Set<Pair<Domain, NetworkSecurityConfig>> getPerDomainConfigs() {
            return null;
Loading