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

Verified Commit 56b8bc9f authored by Marvin W.'s avatar Marvin W. 🐿️
Browse files

Update DroidGuard + SafetyNet

parent ee91cc9b
Loading
Loading
Loading
Loading
+0 −114
Original line number Diff line number Diff line
/*
 * SPDX-FileCopyrightText: 2021, microG Project Team
 * SPDX-License-Identifier: Apache-2.0
 */

package org.microg.gms.safetynet;

import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;

import org.microg.gms.common.PackageUtils;

import java.io.File;

public class SafetyNetPrefs implements SharedPreferences.OnSharedPreferenceChangeListener {
    private static final String OFFICIAL_ATTEST_BASE_URL = "https://www.googleapis.com/androidcheck/v1/attestations/attest";

    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";
    public static final String PREF_SNET_SELF_SIGNED = "snet_self_signed";

    private static SafetyNetPrefs INSTANCE;

    public static SafetyNetPrefs get(Context context) {
        if (INSTANCE == null) {
            PackageUtils.warnIfNotMainProcess(context, SafetyNetPrefs.class);
            if (context == null) return new SafetyNetPrefs(null);
            INSTANCE = new SafetyNetPrefs(context.getApplicationContext());
        }
        return INSTANCE;
    }

    private boolean disabled;
    private boolean official;
    private boolean selfSigned;
    private boolean thirdParty;
    private String customUrl;

    private SharedPreferences preferences;
    private SharedPreferences systemDefaultPreferences;

    private SafetyNetPrefs(Context context) {
        if (context != null) {
            preferences = PreferenceManager.getDefaultSharedPreferences(context);
            preferences.registerOnSharedPreferenceChangeListener(this);
            try {
                systemDefaultPreferences = (SharedPreferences) Context.class.getDeclaredMethod("getSharedPreferences", File.class, int.class).invoke(context, new File("/system/etc/microg.xml"), Context.MODE_PRIVATE);
            } catch (Exception ignored) {
            }
            update();
        }
    }

    private boolean getSettingsBoolean(String key, boolean def) {
        if (systemDefaultPreferences != null) {
            def = systemDefaultPreferences.getBoolean(key, def);
        }
        return preferences.getBoolean(key, def);
    }

    private String getSettingsString(String key, String def) {
        if (systemDefaultPreferences != null) {
            def = systemDefaultPreferences.getString(key, def);
        }
        return preferences.getString(key, def);
    }

    public void update() {
        disabled = getSettingsBoolean(PREF_SNET_DISABLED, true);
        official = getSettingsBoolean(PREF_SNET_OFFICIAL, false);
        selfSigned = getSettingsBoolean(PREF_SNET_SELF_SIGNED, false);
        thirdParty = getSettingsBoolean(PREF_SNET_THIRD_PARTY, false);
        customUrl = getSettingsString(PREF_SNET_CUSTOM_URL, null);
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) {
        update();
    }

    public boolean isEnabled() {
        return !disabled && (official || selfSigned || thirdParty);
    }

    public void setEnabled(boolean enabled) {
        SharedPreferences.Editor edit = preferences.edit();
        edit.putBoolean(PREF_SNET_DISABLED, !enabled);
        if (enabled && !isEnabled()) {
            official = true;
            edit.putBoolean(PREF_SNET_OFFICIAL, true);
        }
        edit.commit();
    }

    public boolean isSelfSigned() {
        return selfSigned;
    }

    public boolean isOfficial() {
        return official;
    }

    public boolean isThirdParty() {
        return thirdParty;
    }

    public String getServiceUrl() {
        if (official) return OFFICIAL_ATTEST_BASE_URL;
        return customUrl;
    }
}
+0 −90
Original line number Diff line number Diff line
/*
 * SPDX-FileCopyrightText: 2021, microG Project Team
 * SPDX-License-Identifier: Apache-2.0
 */

package org.microg.gms.safetynet

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.util.Log
import java.io.Serializable
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine

private const val ACTION_SERVICE_INFO_REQUEST = "org.microg.gms.snet.SERVICE_INFO_REQUEST"
private const val ACTION_UPDATE_CONFIGURATION = "org.microg.gms.snet.UPDATE_CONFIGURATION"
private const val ACTION_SERVICE_INFO_RESPONSE = "org.microg.gms.snet.SERVICE_INFO_RESPONSE"
private const val EXTRA_SERVICE_INFO = "org.microg.gms.snet.SERVICE_INFO"
private const val EXTRA_CONFIGURATION = "org.microg.gms.snet.CONFIGURATION"
private const val TAG = "GmsSafetyNetStatusInfo"

data class ServiceInfo(val configuration: ServiceConfiguration) : Serializable

data class ServiceConfiguration(val enabled: Boolean) : Serializable {
    fun saveToPrefs(context: Context) {
        SafetyNetPrefs.get(context).isEnabled = enabled
    }
}

private fun SafetyNetPrefs.toConfiguration(): ServiceConfiguration = ServiceConfiguration(isEnabled)

class ServiceInfoReceiver : BroadcastReceiver() {
    private fun sendInfoResponse(context: Context) {
        context.sendOrderedBroadcast(Intent(ACTION_SERVICE_INFO_RESPONSE).apply {
            setPackage(context.packageName)
            putExtra(EXTRA_SERVICE_INFO, ServiceInfo(SafetyNetPrefs.get(context).toConfiguration()))
        }, null)
    }

    override fun onReceive(context: Context, intent: Intent) {
        try {
            when (intent.action) {
                ACTION_UPDATE_CONFIGURATION -> {
                    (intent.getSerializableExtra(EXTRA_CONFIGURATION) as? ServiceConfiguration)?.saveToPrefs(context)
                }
            }
            sendInfoResponse(context)
        } catch (e: Exception) {
            Log.w(TAG, e)
        }
    }
}

private suspend fun sendToServiceInfoReceiver(intent: Intent, context: Context): ServiceInfo = suspendCoroutine {
    context.registerReceiver(object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            context.unregisterReceiver(this)
            val serviceInfo = try {
                intent.getSerializableExtra(EXTRA_SERVICE_INFO) as ServiceInfo
            } catch (e: Exception) {
                it.resumeWithException(e)
                return
            }
            try {
                it.resume(serviceInfo)
            } catch (e: Exception) {
                Log.w(TAG, e)
            }
        }
    }, IntentFilter(ACTION_SERVICE_INFO_RESPONSE))
    try {
        context.sendOrderedBroadcast(intent, null)
    } catch (e: Exception) {
        it.resumeWithException(e)
    }
}

suspend fun getSafetyNetServiceInfo(context: Context): ServiceInfo = sendToServiceInfoReceiver(
        Intent(context, ServiceInfoReceiver::class.java).apply {
            action = ACTION_SERVICE_INFO_REQUEST
        }, context)

suspend fun setSafetyNetServiceConfiguration(context: Context, configuration: ServiceConfiguration): ServiceInfo = sendToServiceInfoReceiver(
        Intent(context, ServiceInfoReceiver::class.java).apply {
            action = ACTION_UPDATE_CONFIGURATION
            putExtra(EXTRA_CONFIGURATION, configuration)
        }, context)
+1 −1
Original line number Diff line number Diff line
@@ -11,7 +11,7 @@

    <application>
        <service
            android:name="org.microg.gms.droidguard.DroidGuardService"
            android:name=".DroidGuardService"
            android:enabled="true"
            android:exported="true"
            android:process="com.google.android.gms.unstable">
+2 −3
Original line number Diff line number Diff line
@@ -6,7 +6,6 @@
package com.google.android.gms.droidguard;

import android.content.Intent;
import android.os.Debug;
import android.os.Handler;
import android.os.IBinder;
import android.util.Base64;
@@ -16,9 +15,9 @@ import androidx.annotation.Nullable;

import com.google.android.gms.framework.tracing.wrapper.TracingIntentService;

import org.microg.gms.droidguard.DroidGuardServiceBroker;
import org.microg.gms.droidguard.core.DroidGuardServiceBroker;
import org.microg.gms.droidguard.GuardCallback;
import org.microg.gms.droidguard.HandleProxyFactory;
import org.microg.gms.droidguard.core.HandleProxyFactory;
import org.microg.gms.droidguard.PingData;
import org.microg.gms.droidguard.Request;

+1 −1
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@ import androidx.annotation.Nullable;
import com.google.android.chimera.IntentService;

import org.microg.gms.utils.PackageManagerWrapper;
import org.microg.gms.droidguard.VersionUtil;
import org.microg.gms.droidguard.core.VersionUtil;

public abstract class TracingIntentService extends IntentService {
    private static final String TAG = "TracingIntentService";
Loading