android: Add manager for managed trusted certificates

This is used to install, replace or delete currently installed trusted
certificates based on the app's current managed configuration.

Certificates that are shared between multiple profiles are protected
and not uninstalled if a profile that uses it remains.
This commit is contained in:
Markus Pfeiffer 2023-11-21 15:37:24 +01:00 committed by Tobias Brunner
parent 9cb23f650a
commit aa06d75491

View File

@ -0,0 +1,125 @@
/*
* Copyright (C) 2023 Relution GmbH
*
* Copyright (C) secunet Security Networks AG
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
package org.strongswan.android.logic;
import android.content.Context;
import android.os.Handler;
import android.util.Log;
import org.strongswan.android.data.DatabaseHelper;
import org.strongswan.android.data.ManagedConfigurationService;
import org.strongswan.android.data.ManagedTrustedCertificate;
import org.strongswan.android.data.ManagedTrustedCertificateRepository;
import org.strongswan.android.utils.Difference;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import androidx.annotation.NonNull;
import androidx.core.util.Pair;
public class ManagedTrustedCertificateManager
{
private static final String TAG = ManagedTrustedCertificateManager.class.getSimpleName();
@NonNull
private final ExecutorService executorService;
@NonNull
private final Handler handler;
@NonNull
private final ManagedTrustedCertificateRepository certificateRepository;
@NonNull
private final ManagedTrustedCertificateInstaller certificateInstaller;
public ManagedTrustedCertificateManager(
@NonNull final Context context,
@NonNull final ExecutorService executorService,
@NonNull final Handler handler,
@NonNull final ManagedConfigurationService managedConfigurationService,
@NonNull final DatabaseHelper databaseHelper)
{
this.executorService = executorService;
this.handler = handler;
this.certificateRepository = new ManagedTrustedCertificateRepository(managedConfigurationService, databaseHelper);
this.certificateInstaller = new ManagedTrustedCertificateInstaller(context);
}
public void update(@NonNull final Runnable onUpdateCompleted)
{
executorService.execute(() -> {
final List<ManagedTrustedCertificate> configured = certificateRepository.getConfiguredCertificates();
final List<ManagedTrustedCertificate> installed = certificateRepository.getInstalledCertificates();
final Difference<ManagedTrustedCertificate> diff = Difference.between(installed, configured, ManagedTrustedCertificate::getVpnProfileUuid);
if (diff.isEmpty())
{
Log.d(TAG, "No trusted certificates changed, nothing to do");
handler.post(onUpdateCompleted);
return;
}
Log.d(TAG, "Trusted certificates changed " + diff);
final Set<String> protectedAliases = new HashSet<>();
for (final ManagedTrustedCertificate unchanged : diff.getUnchanged())
{
protectedAliases.add(unchanged.getAlias());
}
for (final ManagedTrustedCertificate delete : diff.getDeletes())
{
remove(delete, !protectedAliases.contains(delete.getAlias()));
}
for (final Pair<ManagedTrustedCertificate, ManagedTrustedCertificate> update : diff.getUpdates())
{
remove(update.first, !protectedAliases.contains(update.first.getAlias()));
install(update.second);
}
for (final ManagedTrustedCertificate insert : diff.getInserts())
{
install(insert);
}
TrustedCertificateManager.getInstance().reset();
TrustedCertificateManager.getInstance().load();
handler.post(onUpdateCompleted);
});
}
private void install(@NonNull final ManagedTrustedCertificate trustedCertificate)
{
if (certificateInstaller.tryInstall(trustedCertificate))
{
certificateRepository.addInstalledCertificate(trustedCertificate);
}
}
private void remove(@NonNull final ManagedTrustedCertificate trustedCertificate, boolean uninstall)
{
if (uninstall)
{
certificateInstaller.tryRemove(trustedCertificate);
}
certificateRepository.removeInstalledCertificate(trustedCertificate);
}
}