From 322f9019c0ca410c0d72190dd17bc316351d35db Mon Sep 17 00:00:00 2001 From: Martin Brabham Date: Fri, 9 Jan 2015 16:20:34 -0800 Subject: [PATCH] DNSCrypt: Encrypt dns queries - Add DNS encryption settings constants. - Listen for settings changes and handle rerouting dns queries - Handle switching servers Change-Id: Ic97285ac6924aa0c930ff59709da384e197cd3ca --- core/java/android/provider/Settings.java | 22 ++++ .../com/android/server/ConnectivityService.java | 116 ++++++++++++++++++--- 2 files changed, 123 insertions(+), 15 deletions(-) diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index f6642d8..9905483 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -4058,6 +4058,28 @@ public final class Settings { public static final class Secure extends NameValueTable { public static final String SYS_PROP_SETTING_VERSION = "sys.settings_secure_version"; + // DNS Encryption + + /** + * @hide + */ + public static final String DNS_ENCRYPTION_TOGGLE = "dns_enc_toggle"; + + /** + * @hide + */ + public static final int DNS_ENCRYPTION_TOGGLE_DEFAULT = 0; + + /** + * @hide + */ + public static final String DNS_ENCRYPTION_SERVER = "dns_enc_server"; + + /** + * @hide + */ + public static final String DNS_ENCRYPTION_SERVER_DEFAULT = "opendns"; + /** * The content:// style URL for this table */ diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 2a47460..0e6578f 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -91,6 +91,8 @@ import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; +import android.provider.Settings.Secure; +import android.provider.Settings.SettingNotFoundException; import android.security.Credentials; import android.security.KeyStore; import android.telephony.TelephonyManager; @@ -167,6 +169,9 @@ public class ConnectivityService extends IConnectivityManager.Stub implements PendingIntent.OnFinished { private static final String TAG = "ConnectivityService"; + private static final String NETID_UPDATE = + "org.codeaurora.NETID_UPDATE"; + private static final boolean DBG = true; private static final boolean VDBG = false; @@ -229,6 +234,16 @@ public class ConnectivityService extends IConnectivityManager.Stub private static final int ENABLED = 1; private static final int DISABLED = 0; + // DNS Encryption variables + private static final String DNSCRYPT_SERVICE = "dnscrypt-proxy"; + private static final String LOOPBACK_ADDR = "127.0.0.1"; + private static final String NULL_DOMAIN = ""; + private boolean mDnsEncryptionEnabled = false; + private String mDnsEncryptionServer = Secure.DNS_ENCRYPTION_SERVER_DEFAULT; + private Collection mActualDnses = new ArrayList(); + private int mNetId = -1; + private String mActualDomains = null; + private enum ReapUnvalidatedNetworks { // Tear down networks that have no chance (e.g. even if validated) of becoming // the highest scoring network satisfying a NetworkRequest. This should be passed when @@ -827,6 +842,13 @@ public class ConnectivityService extends IConnectivityManager.Stub mSettingsObserver.observe( Settings.Global.getUriFor(Settings.Global.MOBILE_DATA_ALWAYS_ON), EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON); + + // Watch for whether or not to use DNScrypt + resolver.registerContentObserver(Settings.Secure.getUriFor( + Secure.DNS_ENCRYPTION_TOGGLE), false, this); + resolver.registerContentObserver(Settings.Secure.getUriFor(Secure + .DNS_ENCRYPTION_SERVER), false, this); + onPreferencesChanged(); } private synchronized int nextNetworkRequestId() { @@ -3027,7 +3049,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - private static class SettingsObserver extends ContentObserver { + private class SettingsObserver extends ContentObserver { final private HashMap mUriEventMap; final private Context mContext; final private Handler mHandler; @@ -3058,7 +3080,70 @@ public class ConnectivityService extends IConnectivityManager.Stub } else { loge("No matching event to send for URI=" + uri); } + onPreferencesChanged(); + } + } + + /** + * Called when preference are updated from Settings + * {@hide} + */ + private void onPreferencesChanged() { + setDnsEncryptionDns(); + } + + /** + * Updates the DNS to either encrypted or regular + */ + private void setDnsEncryptionDns() { + try { + mDnsEncryptionEnabled = Secure.getIntForUser(mContext.getContentResolver(), + Secure.DNS_ENCRYPTION_TOGGLE, UserHandle.USER_CURRENT) != 0; + } catch (SettingNotFoundException e) { + loge("Exception getting dns enabled setting: " + e); + } + String serverName = Secure.getStringForUser(mContext.getContentResolver(), + Secure.DNS_ENCRYPTION_SERVER, UserHandle.USER_CURRENT); + serverName = (TextUtils.isEmpty(serverName)) ? Secure.DNS_ENCRYPTION_SERVER_DEFAULT : + serverName; + + // If they aren't equal, then we have a change! + boolean changed = !mDnsEncryptionServer.equals(serverName); + + // Set last server name + mDnsEncryptionServer = serverName; + + log("DNS Encryption Enabled: " + mDnsEncryptionEnabled); + Collection dnses = mActualDnses; + String domains = mActualDomains; + if (mDnsEncryptionEnabled) { + if (changed) { + // If we had a server change, need to restart service to pick up new server + SystemProperties.set("ctl.stop", DNSCRYPT_SERVICE); + SystemProperties.set("net.dnscrypt_resolver", mDnsEncryptionServer); + } + SystemProperties.set("ctl.start", DNSCRYPT_SERVICE); + dnses = new ArrayList(); + dnses.add(NetworkUtils.numericToInetAddress(LOOPBACK_ADDR)); + domains = NULL_DOMAIN; + } else { + SystemProperties.set("ctl.stop", DNSCRYPT_SERVICE); + } + updateDnsesInternal(dnses, mNetId, domains); + } + + private void updateDnsesInternal(Collection dnses, int netId, String domains) { + if (DBG) log("Setting Dns servers for network " + netId + " to " + dnses); + try { + mNetd.setDnsServersForNetwork(netId, NetworkUtils.makeStrings(dnses), domains); + } catch (Exception e) { + loge("Exception in setDnsServersForNetwork: " + e); + } + NetworkAgentInfo defaultNai = mNetworkForRequestId.get(mDefaultRequest.requestId); + if (defaultNai != null && defaultNai.network.netId == netId) { + setDefaultDnsSystemProperties(dnses); } + flushVmDnsCache(); } private static void log(String s) { @@ -4122,27 +4207,28 @@ public class ConnectivityService extends IConnectivityManager.Stub private void updateDnses(LinkProperties newLp, LinkProperties oldLp, int netId, boolean flush, boolean useDefaultDns) { - if (oldLp == null || (newLp.isIdenticalDnses(oldLp) == false)) { - Collection dnses = newLp.getDnsServers(); + if (oldLp == null || !newLp.isIdenticalDnses(oldLp)) { + Collection dnses = newLp.getDnsServers(); if (dnses.size() == 0 && mDefaultDns != null && useDefaultDns) { - dnses = new ArrayList(); + dnses = new ArrayList(); dnses.add(mDefaultDns); if (DBG) { loge("no dns provided for netId " + netId + ", so using defaults"); } } - if (DBG) log("Setting Dns servers for network " + netId + " to " + dnses); - try { - mNetd.setDnsServersForNetwork(netId, NetworkUtils.makeStrings(dnses), - newLp.getDomains()); - } catch (Exception e) { - loge("Exception in setDnsServersForNetwork: " + e); - } - final NetworkAgentInfo defaultNai = getDefaultNetwork(); - if (defaultNai != null && defaultNai.network.netId == netId) { - setDefaultDnsSystemProperties(dnses); + + // Set tracking fields + mNetId = netId; + mActualDnses = dnses; + mActualDomains = newLp.getDomains(); + + String domains = mActualDomains; + if (mDnsEncryptionEnabled) { + dnses = new ArrayList(); + dnses.add(NetworkUtils.numericToInetAddress(LOOPBACK_ADDR)); + domains = NULL_DOMAIN; } - flushVmDnsCache(); + updateDnsesInternal(dnses, netId, domains); } else if (flush) { try { mNetd.flushNetworkDnsCache(netId); -- 2.7.4