Commit ea136498 authored by Albert Vaca Cintora's avatar Albert Vaca Cintora Committed by Albert Vaca Cintora

Re-generate cert if it's for a different device ID

This would happen to people who transferred their KDE Connect config from
one phone to another (mostly with backup apps that only work on rooted
phones). This led to a state where other devices would always reject the
connection because the certificate CN didn't match the device ID.

On the PC side this is not a problem because the certificate is the source
of truth for the device ID.
parent 1e82c653
......@@ -29,8 +29,11 @@ import android.util.Log;
import org.kde.kdeconnect.Helpers.DeviceHelper;
import org.kde.kdeconnect.Helpers.RandomHelper;
import org.spongycastle.asn1.x500.RDN;
import org.spongycastle.asn1.x500.X500Name;
import org.spongycastle.asn1.x500.X500NameBuilder;
import org.spongycastle.asn1.x500.style.BCStyle;
import org.spongycastle.asn1.x500.style.IETFUtils;
import org.spongycastle.cert.X509CertificateHolder;
import org.spongycastle.cert.X509v3CertificateBuilder;
import org.spongycastle.cert.jcajce.JcaX509CertificateConverter;
......@@ -62,6 +65,7 @@ import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import javax.security.auth.x500.X500Principal;
public class SslHelper {
......@@ -80,12 +84,39 @@ public class SslHelper {
Log.e("SslHelper", "Error getting keys, can't create certificate");
return;
}
String deviceId = DeviceHelper.getDeviceId(context);
boolean needsToGenerateCertificate = false;
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
if (!settings.contains("certificate")) {
if (settings.contains("certificate")) {
try {
SharedPreferences globalSettings = PreferenceManager.getDefaultSharedPreferences(context);
byte[] certificateBytes = Base64.decode(globalSettings.getString("certificate", ""), 0);
X509CertificateHolder certificateHolder = new X509CertificateHolder(certificateBytes);
X509Certificate cert = new JcaX509CertificateConverter().setProvider(BC).getCertificate(certificateHolder);
String certDeviceId = getCommonNameFromCertificate(cert);
if (!certDeviceId.equals(deviceId)) {
Log.e("KDE/SslHelper", "The certificate stored is from a different device id! (found: " + certDeviceId + " expected:" + deviceId + ")");
needsToGenerateCertificate = true;
} else {
certificate = cert;
}
} catch (Exception e) {
Log.e("KDE/SslHelper", "Exception reading own certificate", e);
needsToGenerateCertificate = true;
}
} else {
needsToGenerateCertificate = true;
}
if (needsToGenerateCertificate) {
Log.i("KDE/SslHelper", "Generating a certificate");
try {
X500NameBuilder nameBuilder = new X500NameBuilder(BCStyle.INSTANCE);
nameBuilder.addRDN(BCStyle.CN, DeviceHelper.getDeviceId(context));
nameBuilder.addRDN(BCStyle.CN, deviceId);
nameBuilder.addRDN(BCStyle.OU, "KDE Connect");
nameBuilder.addRDN(BCStyle.O, "KDE");
Calendar calendar = Calendar.getInstance();
......@@ -107,20 +138,9 @@ public class SslHelper {
SharedPreferences.Editor edit = settings.edit();
edit.putString("certificate", Base64.encodeToString(certificate.getEncoded(), 0));
edit.apply();
} catch (Exception e) {
Log.e("KDE/initialiseCert", "Exception", e);
}
} else {
try {
SharedPreferences globalSettings = PreferenceManager.getDefaultSharedPreferences(context);
byte[] certificateBytes = Base64.decode(globalSettings.getString("certificate", ""), 0);
X509CertificateHolder certificateHolder = new X509CertificateHolder(certificateBytes);
certificate = new JcaX509CertificateConverter().setProvider(BC).getCertificate(certificateHolder);
} catch (Exception e) {
Log.e("KDE/SslHelper", "Exception reading own certificate", e);
}
}
}
......@@ -247,4 +267,11 @@ public class SslHelper {
return new JcaX509CertificateConverter().setProvider(BC).getCertificate(certificateHolder);
}
private static String getCommonNameFromCertificate(X509Certificate cert) {
X500Principal principal = cert.getSubjectX500Principal();
X500Name x500name = new X500Name(principal.getName());
RDN rdn = x500name.getRDNs(BCStyle.CN)[0];
return IETFUtils.valueToString(rdn.getFirst().getValue());
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment