open-keychain/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/SecurityProblemPresenter.java
2021-02-26 15:11:54 +01:00

260 lines
10 KiB
Java

/*
* Copyright (C) 2017 Schürmann & Breitmoser GbR
*
* 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 3 of the License, or
* (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.remote.ui;
import java.io.Serializable;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.Drawable;
import org.sufficientlysecure.keychain.pgp.DecryptVerifySecurityProblem;
import org.sufficientlysecure.keychain.pgp.SecurityProblem.InsecureBitStrength;
import org.sufficientlysecure.keychain.pgp.SecurityProblem.InsecureSigningAlgorithm;
import org.sufficientlysecure.keychain.pgp.SecurityProblem.InsecureEncryptionAlgorithm;
import org.sufficientlysecure.keychain.pgp.SecurityProblem.KeySecurityProblem;
import org.sufficientlysecure.keychain.pgp.SecurityProblem.MissingMdc;
import org.sufficientlysecure.keychain.pgp.SecurityProblem.NotSecureCurve;
import org.sufficientlysecure.keychain.pgp.SecurityProblem.EncryptionAlgorithmProblem;
import org.sufficientlysecure.keychain.pgp.SecurityProblem.UnidentifiedKeyProblem;
import org.sufficientlysecure.keychain.daos.OverriddenWarningsDao;
import org.sufficientlysecure.keychain.ui.keyview.ViewKeyActivity;
class SecurityProblemPresenter {
private static final int OVERRIDE_REQUIRED_COUNT = 3;
private final Context context;
private final PackageManager packageManager;
private final OverriddenWarningsDao overriddenWarningsDao;
private RemoteSecurityProblemView view;
private Long viewKeyMasterKeyId;
private int overrideCounter;
private String securityProblemIdentifier;
private String packageName;
private Serializable securityProblem;
private boolean supportOverride;
SecurityProblemPresenter(Context context) {
this.context = context;
packageManager = context.getPackageManager();
overriddenWarningsDao = OverriddenWarningsDao.create(context);
}
public void setView(RemoteSecurityProblemView view) {
this.view = view;
}
void setupFromIntentData(String packageName, Serializable securityProblem, boolean supportOverride) {
this.packageName = packageName;
this.securityProblem = securityProblem;
this.supportOverride = supportOverride;
refreshSecurityProblemDisplay();
refreshPackageInfo();
}
private void refreshSecurityProblemDisplay() {
if (securityProblem instanceof DecryptVerifySecurityProblem) {
setupFromDecryptVerifySecurityProblem((DecryptVerifySecurityProblem) securityProblem);
} else {
throw new IllegalArgumentException("Unhandled security problem type!");
}
}
private void setupFromDecryptVerifySecurityProblem(DecryptVerifySecurityProblem securityProblem) {
if (securityProblem.encryptionKeySecurityProblem != null) {
setupFromEncryptionKeySecurityProblem(securityProblem.encryptionKeySecurityProblem);
} else if (securityProblem.signingKeySecurityProblem != null) {
setupFromSigningKeySecurityProblem(securityProblem.signingKeySecurityProblem);
} else if (securityProblem.symmetricSecurityProblem != null) {
setupFromEncryptionAlgorithmSecurityProblem(securityProblem.symmetricSecurityProblem);
} else if (securityProblem.signatureSecurityProblem != null) {
setupFromSignatureSecurityProblem(securityProblem.signatureSecurityProblem);
}
}
private void setupFromEncryptionKeySecurityProblem(KeySecurityProblem keySecurityProblem) {
viewKeyMasterKeyId = keySecurityProblem.masterKeyId;
view.showViewKeyButton();
if (keySecurityProblem instanceof InsecureBitStrength) {
InsecureBitStrength problem = (InsecureBitStrength) keySecurityProblem;
view.showLayoutEncryptInsecureBitsize(problem.algorithm, problem.bitStrength);
} else if (keySecurityProblem instanceof NotSecureCurve) {
NotSecureCurve problem = (NotSecureCurve) keySecurityProblem;
view.showLayoutEncryptNotSecureCurve(problem.curveOid);
} else if (keySecurityProblem instanceof UnidentifiedKeyProblem) {
view.showLayoutEncryptUnidentifiedKeyProblem();
} else {
throw new IllegalArgumentException("Unhandled key security problem type!");
}
if (keySecurityProblem.isIdentifiable()) {
securityProblemIdentifier = keySecurityProblem.getIdentifier();
refreshOverrideStatusView();
}
}
private void setupFromSigningKeySecurityProblem(KeySecurityProblem keySecurityProblem) {
viewKeyMasterKeyId = keySecurityProblem.masterKeyId;
view.showViewKeyButton();
if (keySecurityProblem instanceof InsecureBitStrength) {
InsecureBitStrength problem = (InsecureBitStrength) keySecurityProblem;
view.showLayoutSignInsecureBitsize(problem.algorithm, problem.bitStrength);
} else if (keySecurityProblem instanceof NotSecureCurve) {
NotSecureCurve problem = (NotSecureCurve) keySecurityProblem;
view.showLayoutSignNotSecureCurve(problem.curveOid);
} else if (keySecurityProblem instanceof UnidentifiedKeyProblem) {
view.showLayoutSignUnidentifiedKeyProblem();
} else {
throw new IllegalArgumentException("Unhandled key security problem type!");
}
if (keySecurityProblem.isIdentifiable()) {
securityProblemIdentifier = keySecurityProblem.getIdentifier();
refreshOverrideStatusView();
}
}
private void setupFromEncryptionAlgorithmSecurityProblem(EncryptionAlgorithmProblem securityProblem) {
if (securityProblem instanceof MissingMdc) {
view.showLayoutMissingMdc();
} else if (securityProblem instanceof InsecureEncryptionAlgorithm) {
InsecureEncryptionAlgorithm insecureSymmetricAlgorithm = (InsecureEncryptionAlgorithm) securityProblem;
view.showLayoutInsecureSymmetric(insecureSymmetricAlgorithm.symmetricAlgorithm);
} else {
throw new IllegalArgumentException("Unhandled symmetric algorithm problem type!");
}
if (securityProblem.isIdentifiable()) {
securityProblemIdentifier = securityProblem.getIdentifier();
refreshOverrideStatusView();
}
}
private void refreshOverrideStatusView() {
if (supportOverride) {
if (overriddenWarningsDao.isWarningOverridden(securityProblemIdentifier)) {
view.showOverrideUndoButton();
} else {
view.showOverrideButton();
}
}
}
private void setupFromSignatureSecurityProblem(InsecureSigningAlgorithm signatureSecurityProblem) {
view.showLayoutInsecureHashAlgorithm(signatureSecurityProblem.hashAlgorithm);
}
private void refreshPackageInfo() {
ApplicationInfo applicationInfo;
try {
applicationInfo = packageManager.getApplicationInfo(packageName, 0);
} catch (NameNotFoundException e) {
throw new IllegalStateException("Could not retrieve package info!");
}
Drawable appIcon = packageManager.getApplicationIcon(applicationInfo);
// CharSequence appName = packageManager.getApplicationLabel(applicationInfo);
view.setTitleClientIcon(appIcon);
}
private void incrementOverrideAndDisplayOrTrigger() {
int overrideCountLeft = OVERRIDE_REQUIRED_COUNT - overrideCounter;
if (overrideCountLeft > 0) {
overrideCounter++;
view.showOverrideMessage(overrideCountLeft);
} else {
overriddenWarningsDao.putOverride(securityProblemIdentifier);
view.finishAsSuppressed();
}
}
private void resetOverrideStatus() {
overrideCounter = 0;
overriddenWarningsDao.deleteOverride(securityProblemIdentifier);
}
void onClickGotIt() {
view.finishAsCancelled();
}
void onClickViewKey() {
Intent intent = new Intent(context, ViewKeyActivity.class);
intent.putExtra(ViewKeyActivity.EXTRA_MASTER_KEY_ID, viewKeyMasterKeyId);
context.startActivity(intent);
}
void onClickOverride() {
incrementOverrideAndDisplayOrTrigger();
}
void onClickOverrideUndo() {
resetOverrideStatus();
refreshSecurityProblemDisplay();
}
void onClickOverrideBack() {
resetOverrideStatus();
refreshSecurityProblemDisplay();
}
void onClickOverrideConfirm() {
incrementOverrideAndDisplayOrTrigger();
}
void onCancel() {
view.finishAsCancelled();
}
interface RemoteSecurityProblemView {
void finishAsCancelled();
void finishAsSuppressed();
void setTitleClientIcon(Drawable drawable);
void showLayoutEncryptInsecureBitsize(int algorithmId, int bitStrength);
void showLayoutEncryptNotSecureCurve(String curveOid);
void showLayoutEncryptUnidentifiedKeyProblem();
void showLayoutSignInsecureBitsize(int algorithmId, int bitStrength);
void showLayoutSignNotSecureCurve(String curveOid);
void showLayoutSignUnidentifiedKeyProblem();
void showLayoutMissingMdc();
void showLayoutInsecureSymmetric(int symmetricAlgorithm);
void showLayoutInsecureHashAlgorithm(int hashAlgorithm);
void showOverrideMessage(int countdown);
void showViewKeyButton();
void showOverrideButton();
void showOverrideUndoButton();
}
}