- Moved certificate-related utilities to separate class - Added settings method to return an entire SSLSettings object; refactored methods using separate parameters to take single SSLSettings parameter - Advanced Settings section on login page now hides / shows along with other buttons to prevent it from showing up in front of the loading spinner - Fixed star imports - Refactored applySslSettings as per code from merge request - Fixed formatting
117 lines
4.5 KiB
Java
117 lines
4.5 KiB
Java
package com.github.gotify.api;
|
|
|
|
import android.annotation.SuppressLint;
|
|
import com.github.gotify.Utils;
|
|
import com.github.gotify.log.Log;
|
|
import java.io.IOException;
|
|
import java.security.GeneralSecurityException;
|
|
import java.security.KeyStore;
|
|
import java.security.SecureRandom;
|
|
import java.security.cert.Certificate;
|
|
import java.security.cert.CertificateFactory;
|
|
import java.security.cert.X509Certificate;
|
|
import java.util.Collection;
|
|
import javax.net.ssl.KeyManager;
|
|
import javax.net.ssl.SSLContext;
|
|
import javax.net.ssl.TrustManager;
|
|
import javax.net.ssl.TrustManagerFactory;
|
|
import javax.net.ssl.X509TrustManager;
|
|
import okhttp3.OkHttpClient;
|
|
|
|
public class CertUtils {
|
|
public static class SSLSettings {
|
|
boolean validateSSL;
|
|
String cert;
|
|
|
|
public SSLSettings(boolean validateSSL, String cert) {
|
|
this.validateSSL = validateSSL;
|
|
this.cert = cert;
|
|
}
|
|
}
|
|
|
|
private static final X509TrustManager trustAll =
|
|
new X509TrustManager() {
|
|
@SuppressLint("TrustAllX509TrustManager")
|
|
@Override
|
|
public void checkClientTrusted(X509Certificate[] chain, String authType) {}
|
|
|
|
@SuppressLint("TrustAllX509TrustManager")
|
|
@Override
|
|
public void checkServerTrusted(X509Certificate[] chain, String authType) {}
|
|
|
|
@Override
|
|
public X509Certificate[] getAcceptedIssuers() {
|
|
return new X509Certificate[] {};
|
|
}
|
|
};
|
|
|
|
public static Certificate parseCertificate(String cert) {
|
|
try {
|
|
CertificateFactory certificateFactory = CertificateFactory.getInstance("X509");
|
|
|
|
return certificateFactory.generateCertificate(Utils.stringToInputStream(cert));
|
|
} catch (Exception e) {
|
|
throw new IllegalArgumentException("certificate is invalid");
|
|
}
|
|
}
|
|
|
|
public static void applySslSettings(OkHttpClient.Builder builder, SSLSettings settings) {
|
|
// Modified from ApiClient.applySslSettings in the client package.
|
|
|
|
try {
|
|
if (!settings.validateSSL) {
|
|
SSLContext context = SSLContext.getInstance("TLS");
|
|
context.init(
|
|
new KeyManager[] {}, new TrustManager[] {trustAll}, new SecureRandom());
|
|
builder.sslSocketFactory(context.getSocketFactory(), trustAll);
|
|
builder.hostnameVerifier((a, b) -> true);
|
|
return;
|
|
}
|
|
|
|
if (settings.cert != null) {
|
|
TrustManager[] trustManagers = certToTrustManager(settings.cert);
|
|
|
|
if (trustManagers != null && trustManagers.length > 0) {
|
|
SSLContext context = SSLContext.getInstance("TLS");
|
|
context.init(new KeyManager[] {}, trustManagers, new SecureRandom());
|
|
builder.sslSocketFactory(
|
|
context.getSocketFactory(), (X509TrustManager) trustManagers[0]);
|
|
builder.hostnameVerifier((a, b) -> true);
|
|
}
|
|
}
|
|
} catch (Exception e) {
|
|
// We shouldn't have issues since the cert is verified on login.
|
|
Log.e("Failed to apply SSL settings", e);
|
|
}
|
|
}
|
|
|
|
private static TrustManager[] certToTrustManager(String cert) throws GeneralSecurityException {
|
|
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
|
|
Collection<? extends Certificate> certificates =
|
|
certificateFactory.generateCertificates(Utils.stringToInputStream(cert));
|
|
if (certificates.isEmpty()) {
|
|
throw new IllegalArgumentException("expected non-empty set of trusted certificates");
|
|
}
|
|
KeyStore caKeyStore = newEmptyKeyStore();
|
|
int index = 0;
|
|
for (Certificate certificate : certificates) {
|
|
String certificateAlias = "ca" + Integer.toString(index++);
|
|
caKeyStore.setCertificateEntry(certificateAlias, certificate);
|
|
}
|
|
TrustManagerFactory trustManagerFactory =
|
|
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
|
trustManagerFactory.init(caKeyStore);
|
|
return trustManagerFactory.getTrustManagers();
|
|
}
|
|
|
|
private static KeyStore newEmptyKeyStore() throws GeneralSecurityException {
|
|
try {
|
|
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
|
keyStore.load(null, null);
|
|
return keyStore;
|
|
} catch (IOException e) {
|
|
throw new AssertionError(e);
|
|
}
|
|
}
|
|
}
|