From c6435f2e9831b6c99836701b42a45a10ea81bb61 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 11 Nov 2022 02:15:20 +0100 Subject: implement motd download in ProviderAPI Service, persist motd --- .../bitmaskclient/base/utils/PreferenceHelper.java | 70 +++++++++++++++++++--- .../bitmaskclient/providersetup/ProviderAPI.java | 1 + .../providersetup/ProviderApiManagerBase.java | 48 ++++++++++++++- 3 files changed, 111 insertions(+), 8 deletions(-) (limited to 'app/src/main/java/se') diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java index 4abeed1a..76e54794 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java @@ -20,6 +20,10 @@ import static se.leap.bitmaskclient.base.models.Constants.PREFERRED_CITY; import static se.leap.bitmaskclient.base.models.Constants.PREFER_UDP; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_CONFIGURED; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_EIP_DEFINITION; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD_HASHES; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD_LAST_SEEN; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD_LAST_UPDATED; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PRIVATE_KEY; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE; import static se.leap.bitmaskclient.base.models.Constants.RESTART_ON_UPDATE; @@ -62,11 +66,16 @@ public class PreferenceHelper { provider.setProviderIp(preferences.getString(Provider.PROVIDER_IP, "")); provider.setProviderApiIp(preferences.getString(Provider.PROVIDER_API_IP, "")); provider.setGeoipUrl(preferences.getString(Provider.GEOIP_URL, "")); + provider.setMotdUrl(preferences.getString(Provider.MOTD_URL, "")); provider.define(new JSONObject(preferences.getString(Provider.KEY, ""))); provider.setCaCert(preferences.getString(Provider.CA_CERT, "")); provider.setVpnCertificate(preferences.getString(PROVIDER_VPN_CERTIFICATE, "")); provider.setPrivateKey(preferences.getString(PROVIDER_PRIVATE_KEY, "")); provider.setEipServiceJson(new JSONObject(preferences.getString(PROVIDER_EIP_DEFINITION, ""))); + provider.setMotdJson(new JSONObject(preferences.getString(PROVIDER_MOTD, ""))); + provider.setLastMotdSeen(preferences.getLong(PROVIDER_MOTD_LAST_SEEN, 0L)); + provider.setLastMotdUpdate(preferences.getLong(PROVIDER_MOTD_LAST_UPDATED, 0L)); + provider.setMotdLastSeenHashes(preferences.getStringSet(PROVIDER_MOTD_HASHES, new HashSet<>())); } catch (MalformedURLException | JSONException e) { e.printStackTrace(); } @@ -78,12 +87,31 @@ public class PreferenceHelper { return preferences.getString(toFetch + "." + providerDomain, ""); } + public static long getLongFromPersistedProvider(String toFetch, String providerDomain, SharedPreferences preferences) { + return preferences.getLong(toFetch + "." + providerDomain, 0L); + } + + public static Set getStringSetFromPersistedProvider(String toFetch, String providerDomain, SharedPreferences preferences) { + return preferences.getStringSet(toFetch + "." + providerDomain, new HashSet<>()); + } + + public static void persistProvider(Context context, Provider provider) { + SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + storeProviderInPreferences(preferences, provider, true); + } + + public static void storeProviderInPreferences(SharedPreferences preferences, Provider provider) { + storeProviderInPreferences(preferences, provider, false); + } + // TODO: replace commit with apply after refactoring EIP //FIXME: don't save private keys in shared preferences! use the keystore - public static void storeProviderInPreferences(SharedPreferences preferences, Provider provider) { - preferences.edit().putBoolean(PROVIDER_CONFIGURED, true). + public static void storeProviderInPreferences(SharedPreferences preferences, Provider provider, boolean apply) { + SharedPreferences.Editor editor = preferences.edit(); + editor.putBoolean(PROVIDER_CONFIGURED, true). putString(Provider.PROVIDER_IP, provider.getProviderIp()). putString(Provider.GEOIP_URL, provider.getGeoipUrl().toString()). + putString(Provider.MOTD_URL, provider.getMotdUrl().toString()). putString(Provider.PROVIDER_API_IP, provider.getProviderApiIp()). putString(Provider.MAIN_URL, provider.getMainUrlString()). putString(Provider.KEY, provider.getDefinitionString()). @@ -91,7 +119,15 @@ public class PreferenceHelper { putString(PROVIDER_EIP_DEFINITION, provider.getEipServiceJsonString()). putString(PROVIDER_PRIVATE_KEY, provider.getPrivateKey()). putString(PROVIDER_VPN_CERTIFICATE, provider.getVpnCertificate()). - commit(); + putString(PROVIDER_MOTD, provider.getMotdJsonString()). + putStringSet(PROVIDER_MOTD_HASHES, provider.getMotdLastSeenHashes()). + putLong(PROVIDER_MOTD_LAST_SEEN, provider.getLastMotdSeen()). + putLong(PROVIDER_MOTD_LAST_UPDATED, provider.getLastMotdUpdate()); + if (apply) { + editor.apply(); + } else { + editor.commit(); + } String providerDomain = provider.getDomain(); preferences.edit().putBoolean(PROVIDER_CONFIGURED, true). @@ -99,9 +135,14 @@ public class PreferenceHelper { putString(Provider.PROVIDER_API_IP + "." + providerDomain, provider.getProviderApiIp()). putString(Provider.MAIN_URL + "." + providerDomain, provider.getMainUrlString()). putString(Provider.GEOIP_URL + "." + providerDomain, provider.getGeoipUrl().toString()). + putString(Provider.MOTD_URL + "." + providerDomain, provider.getMotdUrl().toString()). putString(Provider.KEY + "." + providerDomain, provider.getDefinitionString()). putString(Provider.CA_CERT + "." + providerDomain, provider.getCaCert()). putString(PROVIDER_EIP_DEFINITION + "." + providerDomain, provider.getEipServiceJsonString()). + putString(PROVIDER_MOTD + "." + providerDomain, provider.getMotdJsonString()). + putStringSet(PROVIDER_MOTD_HASHES + "." + providerDomain, provider.getMotdLastSeenHashes()). + putLong(PROVIDER_MOTD_LAST_SEEN + "." + providerDomain, provider.getLastMotdSeen()). + putLong(PROVIDER_MOTD_LAST_UPDATED + "." + providerDomain, provider.getLastMotdUpdate()). apply(); } @@ -132,9 +173,14 @@ public class PreferenceHelper { remove(Provider.PROVIDER_API_IP + "." + providerDomain). remove(Provider.MAIN_URL + "." + providerDomain). remove(Provider.GEOIP_URL + "." + providerDomain). + remove(Provider.MOTD_URL + "." + providerDomain). remove(PROVIDER_EIP_DEFINITION + "." + providerDomain). remove(PROVIDER_PRIVATE_KEY + "." + providerDomain). remove(PROVIDER_VPN_CERTIFICATE + "." + providerDomain). + remove(PROVIDER_MOTD + "." + providerDomain). + remove(PROVIDER_MOTD_HASHES + "." + providerDomain). + remove(PROVIDER_MOTD_LAST_SEEN + "." + providerDomain). + remove(PROVIDER_MOTD_LAST_UPDATED + "." + providerDomain). apply(); } @@ -146,9 +192,14 @@ public class PreferenceHelper { remove(Provider.PROVIDER_API_IP). remove(Provider.MAIN_URL). remove(Provider.GEOIP_URL). + remove(Provider.MOTD_URL). remove(PROVIDER_EIP_DEFINITION). remove(PROVIDER_PRIVATE_KEY). remove(PROVIDER_VPN_CERTIFICATE). + remove(PROVIDER_MOTD). + remove(PROVIDER_MOTD_HASHES). + remove(PROVIDER_MOTD_LAST_SEEN). + remove(PROVIDER_MOTD_LAST_UPDATED). apply(); } @@ -360,10 +411,7 @@ public class PreferenceHelper { } public static void setExcludedApps(Context context, Set apps) { - SharedPreferences prefs = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); - SharedPreferences.Editor prefsedit = prefs.edit(); - prefsedit.putStringSet(EXCLUDED_APPS, apps); - prefsedit.apply(); + putStringSet(context, EXCLUDED_APPS, apps); } public static Set getExcludedApps(Context context) { @@ -415,6 +463,14 @@ public class PreferenceHelper { preferences.edit().putString(key, value).apply(); } + public static void putStringSet(Context context, String key, Set value) { + if (context == null) { + return; + } + SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); + preferences.edit().putStringSet(key, value).apply(); + } + public static boolean getBoolean(Context context, String key, Boolean defValue) { if (context == null) { return false; diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderAPI.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderAPI.java index e45add50..86ce577b 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderAPI.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderAPI.java @@ -60,6 +60,7 @@ public class ProviderAPI extends JobIntentService implements ProviderApiManagerB SET_UP_PROVIDER = "setUpProvider", UPDATE_PROVIDER_DETAILS = "updateProviderDetails", DOWNLOAD_GEOIP_JSON = "downloadGeoIpJson", + DOWNLOAD_MOTD = "downloadMotd", SIGN_UP = "srpRegister", LOG_IN = "srpAuth", LOG_OUT = "logOut", diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java index 7b6a3ad6..14308875 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java @@ -35,10 +35,15 @@ import static se.leap.bitmaskclient.base.models.Constants.CREDENTIALS_PASSWORD; import static se.leap.bitmaskclient.base.models.Constants.CREDENTIALS_USERNAME; import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_START; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD_HASHES; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD_LAST_SEEN; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD_LAST_UPDATED; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PRIVATE_KEY; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE; import static se.leap.bitmaskclient.base.models.Provider.CA_CERT; import static se.leap.bitmaskclient.base.models.Provider.GEOIP_URL; +import static se.leap.bitmaskclient.base.models.Provider.MOTD_URL; import static se.leap.bitmaskclient.base.models.Provider.PROVIDER_API_IP; import static se.leap.bitmaskclient.base.models.Provider.PROVIDER_IP; import static se.leap.bitmaskclient.base.utils.ConfigHelper.getDomainFromMainURL; @@ -47,6 +52,8 @@ import static se.leap.bitmaskclient.base.utils.ConfigHelper.getProviderFormatted import static se.leap.bitmaskclient.base.utils.ConfigHelper.parseRsaKeyFromString; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.deleteProviderDetailsFromPreferences; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getFromPersistedProvider; +import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getLongFromPersistedProvider; +import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getStringSetFromPersistedProvider; import static se.leap.bitmaskclient.providersetup.ProviderAPI.BACKEND_ERROR_KEY; import static se.leap.bitmaskclient.providersetup.ProviderAPI.BACKEND_ERROR_MESSAGE; import static se.leap.bitmaskclient.providersetup.ProviderAPI.CORRECTLY_DOWNLOADED_EIP_SERVICE; @@ -55,6 +62,7 @@ import static se.leap.bitmaskclient.providersetup.ProviderAPI.CORRECTLY_DOWNLOAD import static se.leap.bitmaskclient.providersetup.ProviderAPI.CORRECTLY_UPDATED_INVALID_VPN_CERTIFICATE; import static se.leap.bitmaskclient.providersetup.ProviderAPI.DELAY; import static se.leap.bitmaskclient.providersetup.ProviderAPI.DOWNLOAD_GEOIP_JSON; +import static se.leap.bitmaskclient.providersetup.ProviderAPI.DOWNLOAD_MOTD; import static se.leap.bitmaskclient.providersetup.ProviderAPI.DOWNLOAD_SERVICE_JSON; import static se.leap.bitmaskclient.providersetup.ProviderAPI.DOWNLOAD_VPN_CERTIFICATE; import static se.leap.bitmaskclient.providersetup.ProviderAPI.ERRORID; @@ -124,6 +132,7 @@ import java.security.interfaces.RSAPrivateKey; import java.util.ArrayList; import java.util.List; import java.util.NoSuchElementException; +import java.util.Set; import java.util.concurrent.TimeoutException; import javax.net.ssl.SSLHandshakeException; @@ -138,6 +147,7 @@ import se.leap.bitmaskclient.base.models.ProviderObservable; import se.leap.bitmaskclient.base.utils.ConfigHelper; import se.leap.bitmaskclient.base.utils.PreferenceHelper; import se.leap.bitmaskclient.eip.EipStatus; +import se.leap.bitmaskclient.motd.MotdClient; import se.leap.bitmaskclient.providersetup.connectivity.OkHttpClientGenerator; import se.leap.bitmaskclient.providersetup.models.LeapSRPSession; import se.leap.bitmaskclient.providersetup.models.SrpCredentials; @@ -299,6 +309,17 @@ public abstract class ProviderApiManagerBase { } ProviderObservable.getInstance().setProviderForDns(null); break; + case DOWNLOAD_MOTD: + MotdClient client = new MotdClient(provider); + JSONObject motd = client.fetchJson(); + if (motd != null) { + provider.setMotdJson(motd); + provider.setLastMotdUpdate(System.currentTimeMillis()); + } + PreferenceHelper.storeProviderInPreferences(preferences, provider); + ProviderObservable.getInstance().updateProvider(provider); + break; + case UPDATE_INVALID_VPN_CERTIFICATE: ProviderObservable.getInstance().setProviderForDns(provider); result = updateVpnCertificate(provider); @@ -914,7 +935,11 @@ public abstract class ProviderApiManagerBase { provider.setVpnCertificate(getPersistedVPNCertificate(providerDomain)); provider.setProviderApiIp(getPersistedProviderApiIp(providerDomain)); provider.setProviderIp(getPersistedProviderIp(providerDomain)); - provider.setGeoipUrl(getPersistedGeoIp(providerDomain)); + provider.setGeoipUrl(getPersistedGeoIp(providerDomain)); // TODO: do we really need to persist the Geoip URL?? + provider.setLastMotdSeen(getPersistedMotdLastSeen(providerDomain)); + provider.setMotdLastSeenHashes(getPersistedMotdHashes(providerDomain)); + provider.setLastMotdUpdate(getPersistedMotdLastUpdate(providerDomain)); + provider.setMotdJson(getPersistedMotd(providerDomain)); } } @@ -1045,6 +1070,27 @@ public abstract class ProviderApiManagerBase { return getFromPersistedProvider(GEOIP_URL, providerDomain, preferences); } + protected JSONObject getPersistedMotd(String providerDomain) { + try { + return new JSONObject(getFromPersistedProvider(PROVIDER_MOTD, providerDomain, preferences)); + } catch (JSONException e) { + return new JSONObject(); + } + } + + protected long getPersistedMotdLastSeen(String providerDomain) { + return getLongFromPersistedProvider(PROVIDER_MOTD_LAST_SEEN, providerDomain, preferences); + } + + protected long getPersistedMotdLastUpdate(String providerDomain) { + return getLongFromPersistedProvider(PROVIDER_MOTD_LAST_UPDATED, providerDomain, preferences); + } + + protected Set getPersistedMotdHashes(String providerDomain) { + return getStringSetFromPersistedProvider(PROVIDER_MOTD_HASHES, providerDomain, preferences); + } + + protected boolean hasUpdatedProviderDetails(String domain) { return preferences.contains(Provider.KEY + "." + domain) && preferences.contains(CA_CERT + "." + domain); } -- cgit v1.2.3