mirror of
https://github.com/TeamVanced/VancedMicroG
synced 2024-11-19 02:29:25 +01:00
Make SafetyNet configurable
This commit is contained in:
parent
d991888b89
commit
170d5e4524
2
extern/UnifiedNlp
vendored
2
extern/UnifiedNlp
vendored
@ -1 +1 @@
|
||||
Subproject commit ea09d3ff063c8ad32db492343bd640c3ac53bf2c
|
||||
Subproject commit c161d40f1bfe1c185b67d8120e4d51339d31e280
|
@ -383,8 +383,8 @@
|
||||
|
||||
<!-- Chimera spoof -->
|
||||
<provider
|
||||
android:authorities="com.google.android.gms.chimera"
|
||||
android:name="org.microg.gms.ChimeraSpoofProvider"
|
||||
android:authorities="com.google.android.gms.chimera"
|
||||
android:exported="true"/>
|
||||
|
||||
<!-- microG custom UI -->
|
||||
@ -426,6 +426,11 @@
|
||||
android:label="@string/service_name_mcs"
|
||||
android:theme="@style/Theme.AppCompat.Settings"/>
|
||||
|
||||
<activity
|
||||
android:name="org.microg.gms.ui.SafetyNetFragment$AsActivity"
|
||||
android:label="@string/service_name_snet"
|
||||
android:theme="@style/Theme.AppCompat.Settings"/>
|
||||
|
||||
<activity
|
||||
android:name="org.microg.gms.ui.SelfCheckFragment$AsActivity"
|
||||
android:label="@string/self_check_title"
|
||||
|
@ -53,7 +53,6 @@ import okio.ByteString;
|
||||
|
||||
public class Attestation {
|
||||
private static final String TAG = "GmsSafetyNetAttest";
|
||||
private static final String ATTEST_URL = "https://www.googleapis.com/androidcheck/v1/attestations/attest?alt=PROTO&key=AIzaSyDqVnJBjE5ymo--oBJt3On7HQx9xNm1RHA";
|
||||
|
||||
private Context context;
|
||||
private String packageName;
|
||||
@ -144,14 +143,11 @@ public class Attestation {
|
||||
if (payload == null) {
|
||||
throw new IllegalStateException("missing payload");
|
||||
}
|
||||
if (droidGaurdResult == null || droidGaurdResult.isEmpty()) {
|
||||
throw new IllegalStateException("missing droidGuard");
|
||||
}
|
||||
return attest(new AttestRequest(ByteString.of(payload), droidGaurdResult)).result;
|
||||
}
|
||||
|
||||
private AttestResponse attest(AttestRequest request) throws IOException {
|
||||
HttpURLConnection connection = (HttpURLConnection) new URL(ATTEST_URL).openConnection();
|
||||
HttpURLConnection connection = (HttpURLConnection) new URL(SafetyNetPrefs.get(context).getServiceUrl()).openConnection();
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setDoInput(true);
|
||||
connection.setDoOutput(true);
|
||||
@ -180,9 +176,13 @@ public class Attestation {
|
||||
}
|
||||
|
||||
InputStream is = connection.getInputStream();
|
||||
AttestResponse response = new Wire().parseFrom(new GZIPInputStream(is), AttestResponse.class);
|
||||
is.close();
|
||||
return response;
|
||||
byte[] bytes = Utils.readStreamToEnd(new GZIPInputStream(is));
|
||||
try {
|
||||
return new Wire().parseFrom(bytes, AttestResponse.class);
|
||||
} catch (IOException e) {
|
||||
Log.d(TAG, Base64.encodeToString(bytes, 0));
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -56,6 +56,12 @@ public class SafetyNetClientServiceImpl extends ISafetyNetService.Stub {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SafetyNetPrefs.get(context).isEnabled()) {
|
||||
Log.d(TAG, "ignoring SafetyNet request, it's disabled");
|
||||
callbacks.onAttestationData(Status.CANCELED, null);
|
||||
return;
|
||||
}
|
||||
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -65,10 +71,11 @@ public class SafetyNetClientServiceImpl extends ISafetyNetService.Stub {
|
||||
RemoteDroidGuardConnector conn = new RemoteDroidGuardConnector(context);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("contentBinding", attestation.getPayloadHashBase64());
|
||||
RemoteDroidGuardConnector.Result dg = conn.guard("attest", Long.toString(LastCheckinInfo.read(context).androidId),
|
||||
bundle, Utils.getDeviceIdentifier(context).meid, Utils.getPhoneInfo(context).imsi);
|
||||
if (dg != null && dg.getStatusCode() == 0 && dg.getResult() != null) {
|
||||
attestation.setDroidGaurdResult(Base64.encodeToString(dg.getResult(), Base64.NO_WRAP + Base64.NO_PADDING + Base64.URL_SAFE));
|
||||
RemoteDroidGuardConnector.Result dg = conn.guard("attest", Long.toString(LastCheckinInfo.read(context).androidId), bundle);
|
||||
if (!SafetyNetPrefs.get(context).isOfficial() || dg != null && dg.getStatusCode() == 0 && dg.getResult() != null) {
|
||||
if (dg != null && dg.getStatusCode() == 0 && dg.getResult() != null) {
|
||||
attestation.setDroidGaurdResult(Base64.encodeToString(dg.getResult(), Base64.NO_WRAP + Base64.NO_PADDING + Base64.URL_SAFE));
|
||||
}
|
||||
AttestationData data = new AttestationData(attestation.attest());
|
||||
callbacks.onAttestationData(Status.SUCCESS, data);
|
||||
} else {
|
||||
|
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2017 microG Project Team
|
||||
*
|
||||
* 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 org.microg.gms.snet;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
public class SafetyNetPrefs implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
private static final String OFFICIAL_ATTEST_URL = "https://www.googleapis.com/androidcheck/v1/attestations/attest?alt=PROTO&key=AIzaSyDqVnJBjE5ymo--oBJt3On7HQx9xNm1RHA";
|
||||
|
||||
public static final String PREF_SNET_DISABLED = "snet_disabled";
|
||||
public static final String PREF_SNET_OFFICIAL = "snet_official";
|
||||
public static final String PREF_SNET_THIRD_PARTY = "snet_third_party";
|
||||
public static final String PREF_SNET_CUSTOM_URL = "snet_custom_url";
|
||||
|
||||
private static SafetyNetPrefs INSTANCE;
|
||||
|
||||
public static SafetyNetPrefs get(Context context) {
|
||||
if (INSTANCE == null) {
|
||||
if (context == null) return new SafetyNetPrefs(null);
|
||||
INSTANCE = new SafetyNetPrefs(context.getApplicationContext());
|
||||
}
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private boolean disabled;
|
||||
private boolean official;
|
||||
private boolean thirdParty;
|
||||
private String customUrl;
|
||||
|
||||
private SharedPreferences defaultPreferences;
|
||||
|
||||
private SafetyNetPrefs(Context context) {
|
||||
if (context != null) {
|
||||
defaultPreferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
defaultPreferences.registerOnSharedPreferenceChangeListener(this);
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
public void update() {
|
||||
disabled = defaultPreferences.getBoolean(PREF_SNET_DISABLED, true);
|
||||
official = defaultPreferences.getBoolean(PREF_SNET_OFFICIAL, false);
|
||||
thirdParty = defaultPreferences.getBoolean(PREF_SNET_THIRD_PARTY, false);
|
||||
customUrl = defaultPreferences.getString(PREF_SNET_CUSTOM_URL, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) {
|
||||
update();
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return !disabled && (official || thirdParty);
|
||||
}
|
||||
|
||||
public boolean isOfficial() {
|
||||
return official;
|
||||
}
|
||||
|
||||
public String getServiceUrl() {
|
||||
if (official) return OFFICIAL_ATTEST_URL;
|
||||
return customUrl;
|
||||
}
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (C) 2017 microG Project Team
|
||||
*
|
||||
* 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 org.microg.gms.ui;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v7.preference.Preference;
|
||||
|
||||
import com.google.android.gms.R;
|
||||
|
||||
import org.microg.tools.ui.AbstractSettingsActivity;
|
||||
import org.microg.tools.ui.RadioButtonPreference;
|
||||
import org.microg.tools.ui.ResourceSettingsFragment;
|
||||
|
||||
import static org.microg.gms.snet.SafetyNetPrefs.PREF_SNET_DISABLED;
|
||||
import static org.microg.gms.snet.SafetyNetPrefs.PREF_SNET_OFFICIAL;
|
||||
import static org.microg.gms.snet.SafetyNetPrefs.PREF_SNET_THIRD_PARTY;
|
||||
|
||||
public class SafetyNetFragment extends ResourceSettingsFragment {
|
||||
|
||||
public SafetyNetFragment() {
|
||||
preferencesResource = R.xml.preferences_snet;
|
||||
}
|
||||
|
||||
private RadioButtonPreference radioDisabled;
|
||||
private RadioButtonPreference radioOfficial;
|
||||
private RadioButtonPreference radioThirdParty;
|
||||
|
||||
@Override
|
||||
public void onCreatePreferencesFix(@Nullable Bundle savedInstanceState, String rootKey) {
|
||||
super.onCreatePreferencesFix(savedInstanceState, rootKey);
|
||||
|
||||
radioDisabled = (RadioButtonPreference) findPreference(PREF_SNET_DISABLED);
|
||||
radioOfficial = (RadioButtonPreference) findPreference(PREF_SNET_OFFICIAL);
|
||||
radioThirdParty = (RadioButtonPreference) findPreference(PREF_SNET_THIRD_PARTY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceTreeClick(Preference preference) {
|
||||
if (preference == radioDisabled) {
|
||||
radioDisabled.setChecked(true);
|
||||
radioOfficial.setChecked(false);
|
||||
radioThirdParty.setChecked(false);
|
||||
return true;
|
||||
} else if (preference == radioOfficial) {
|
||||
radioDisabled.setChecked(false);
|
||||
radioOfficial.setChecked(true);
|
||||
radioThirdParty.setChecked(false);
|
||||
return true;
|
||||
} else if (preference == radioThirdParty) {
|
||||
radioDisabled.setChecked(false);
|
||||
radioOfficial.setChecked(false);
|
||||
radioThirdParty.setChecked(true);
|
||||
return true;
|
||||
}
|
||||
return super.onPreferenceTreeClick(preference);
|
||||
}
|
||||
|
||||
public static class AsActivity extends AbstractSettingsActivity {
|
||||
public AsActivity() {
|
||||
showHomeAsUp = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Fragment getFragment() {
|
||||
return new SafetyNetFragment();
|
||||
}
|
||||
}
|
||||
}
|
@ -19,12 +19,12 @@ package org.microg.gms.ui;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v7.preference.PreferenceManager;
|
||||
|
||||
import com.google.android.gms.R;
|
||||
|
||||
import org.microg.gms.gcm.GcmDatabase;
|
||||
import org.microg.gms.gcm.GcmPrefs;
|
||||
import org.microg.gms.snet.SafetyNetPrefs;
|
||||
import org.microg.tools.ui.AbstractDashboardActivity;
|
||||
import org.microg.tools.ui.ResourceSettingsFragment;
|
||||
|
||||
@ -45,6 +45,7 @@ public class SettingsActivity extends AbstractDashboardActivity {
|
||||
|
||||
public static final String PREF_ABOUT = "pref_about";
|
||||
public static final String PREF_GCM = "pref_gcm";
|
||||
public static final String PREF_SNET = "pref_snet";
|
||||
|
||||
public FragmentImpl() {
|
||||
preferencesResource = R.xml.preferences_start;
|
||||
@ -53,16 +54,26 @@ public class SettingsActivity extends AbstractDashboardActivity {
|
||||
@Override
|
||||
public void onCreatePreferencesFix(@Nullable Bundle savedInstanceState, String rootKey) {
|
||||
super.onCreatePreferencesFix(savedInstanceState, rootKey);
|
||||
PreferenceManager prefs = getPreferenceManager();
|
||||
prefs.findPreference(PREF_ABOUT).setSummary(getString(R.string.about_version_str, AboutFragment.getSelfVersion(getContext())));
|
||||
updateDetails();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
updateDetails();
|
||||
}
|
||||
|
||||
private void updateDetails() {
|
||||
findPreference(PREF_ABOUT).setSummary(getString(R.string.about_version_str, AboutFragment.getSelfVersion(getContext())));
|
||||
if (GcmPrefs.get(getContext()).isGcmEnabled()) {
|
||||
GcmDatabase database = new GcmDatabase(getContext());
|
||||
int regCount = database.getRegistrationList().size();
|
||||
database.close();
|
||||
prefs.findPreference(PREF_GCM).setSummary(getString(R.string.v7_preference_on) + " / " + getContext().getString(R.string.gcm_registered_apps_counter, regCount));
|
||||
findPreference(PREF_GCM).setSummary(getString(R.string.v7_preference_on) + " / " + getContext().getString(R.string.gcm_registered_apps_counter, regCount));
|
||||
} else {
|
||||
prefs.findPreference(PREF_GCM).setSummary(R.string.v7_preference_off);
|
||||
findPreference(PREF_GCM).setSummary(R.string.v7_preference_off);
|
||||
}
|
||||
findPreference(PREF_SNET).setSummary(SafetyNetPrefs.get(getContext()).isEnabled() ? R.string.service_status_enabled : R.string.service_status_disabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
13
play-services-core/src/main/res/drawable/certificate.xml
Normal file
13
play-services-core/src/main/res/drawable/certificate.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M4,3C2.89,3 2,3.89 2,5V15A2,2 0 0,0 4,17H12V22L15,19L18,22V17H20A2,2 0 0,0
|
||||
22,15V8L22,6V5A2,2 0 0,0
|
||||
20,3H16V3H4M12,5L15,7L18,5V8.5L21,10L18,11.5V15L15,13L12,15V11.5L9,10L12,8.5V5M4,5H9V7H4V5M4,9H7V11H4V9M4,13H9V15H4V13Z" />
|
||||
</vector>
|
@ -55,6 +55,10 @@ This can take a couple of minutes."</string>
|
||||
|
||||
<string name="service_name_checkin">Google device registration</string>
|
||||
<string name="service_name_mcs">Google Cloud Messaging</string>
|
||||
<string name="service_name_snet">Google SafetyNet</string>
|
||||
|
||||
<string name="service_status_disabled">Disabled</string>
|
||||
<string name="service_status_enabled">Enabled</string>
|
||||
|
||||
<string name="pref_checkin_enable_summary">Registers your device to Google services and creates a unique device identifier. microG strips identifying bits other than your Google account name from registration data.</string>
|
||||
<string name="pref_gcm_enable_mcs_summary">Google Cloud Messaging is a push notification provider used by many third-party applications. To use it you must enable device registration.</string>
|
||||
@ -138,4 +142,20 @@ This can take a couple of minutes."</string>
|
||||
<string name="network_type_wifi">Wi-Fi</string>
|
||||
<string name="network_type_roaming">Roaming</string>
|
||||
<string name="network_type_other">Other networks</string>
|
||||
|
||||
<string name="snet_intro">Google SafetyNet is a device certification system, ensuring that the device is properly secured and compatible with Android CTS. Some applications use SafetyNet for security reasons or as a prerequisite for tamper-protection.\n\nmicroG GmsCore contains a free implementation of SafetyNet, but the official server requires SafetyNet requests to be signed using the proprietary DroidGuard system. A sandboxed version of DroidGuard is available as a separate “DroidGuard Helper” app.</string>
|
||||
|
||||
<string name="prefcat_configuration">Configuration</string>
|
||||
|
||||
<string name="pref_snet_status_disabled_title">Disabled</string>
|
||||
<string name="pref_snet_status_disabled_summary">Completely disable SafetyNet</string>
|
||||
<string name="pref_snet_status_official_title">Use official server</string>
|
||||
<string name="pref_snet_status_official_summary">Requires an unrooted system, device registration enabled and microG DroidGuard Helper installed</string>
|
||||
<string name="pref_snet_status_third_party_title">Use third-party server</string>
|
||||
<string name="pref_snet_status_third_party_summary">Third-party servers might be able to reply to SafetyNet requests without DroidGuard signature</string>
|
||||
<string name="pref_snet_custom_url_title">Custom server URL</string>
|
||||
<string name="pref_snet_custom_url_summary">Full URL of the third-party server answering SafetyNet attestation requests</string>
|
||||
|
||||
<string name="prefcat_test">Test</string>
|
||||
<string name="pref_snet_testdrive_title">Try SafetyNet attestation</string>
|
||||
</resources>
|
||||
|
53
play-services-core/src/main/res/xml/preferences_snet.xml
Normal file
53
play-services-core/src/main/res/xml/preferences_snet.xml
Normal file
@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2017 microG Project Team
|
||||
~
|
||||
~ 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.
|
||||
-->
|
||||
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<Preference
|
||||
android:selectable="false"
|
||||
android:summary="@string/snet_intro"/>
|
||||
<PreferenceCategory android:title="@string/prefcat_configuration">
|
||||
<org.microg.tools.ui.RadioButtonPreference
|
||||
android:defaultValue="true"
|
||||
android:key="snet_disabled"
|
||||
android:summary="@string/pref_snet_status_disabled_summary"
|
||||
android:title="@string/pref_snet_status_disabled_title"/>
|
||||
<org.microg.tools.ui.RadioButtonPreference
|
||||
android:checked="false"
|
||||
android:key="snet_official"
|
||||
android:summary="@string/pref_snet_status_official_summary"
|
||||
android:title="@string/pref_snet_status_official_title"/>
|
||||
<org.microg.tools.ui.RadioButtonPreference
|
||||
android:checked="false"
|
||||
android:key="snet_third_party"
|
||||
android:summary="@string/pref_snet_status_third_party_summary"
|
||||
android:title="@string/pref_snet_status_third_party_title"/>
|
||||
<EditTextPreference
|
||||
android:dependency="snet_third_party"
|
||||
android:hint="https://example.com/server?key=123"
|
||||
android:key="snet_custom_url"
|
||||
android:summary="@string/pref_snet_custom_url_summary"
|
||||
android:title="@string/pref_snet_custom_url_title"/>
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory android:title="@string/prefcat_test">
|
||||
<Preference
|
||||
android:enabled="false"
|
||||
android:key="pref_snet_run_attest"
|
||||
android:summary="Not yet available"
|
||||
android:title="@string/pref_snet_testdrive_title"/>
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
@ -41,6 +41,14 @@
|
||||
android:targetClass="org.microg.gms.ui.GcmFragment$AsActivity"
|
||||
android:targetPackage="com.google.android.gms"/>
|
||||
</org.microg.tools.ui.TintIconPreference>
|
||||
<org.microg.tools.ui.TintIconPreference
|
||||
android:icon="@drawable/certificate"
|
||||
android:key="pref_snet"
|
||||
android:title="@string/service_name_snet">
|
||||
<intent
|
||||
android:targetClass="org.microg.gms.ui.SafetyNetFragment$AsActivity"
|
||||
android:targetPackage="com.google.android.gms"/>
|
||||
</org.microg.tools.ui.TintIconPreference>
|
||||
<org.microg.tools.ui.TintIconPreference
|
||||
android:icon="@drawable/location_marker"
|
||||
android:title="@string/nlp_settings_label">
|
||||
|
Loading…
Reference in New Issue
Block a user