diff --git a/app/src/main/java/eu/faircode/email/FragmentMessages.java b/app/src/main/java/eu/faircode/email/FragmentMessages.java index 703e6a184e..d77baada8e 100644 --- a/app/src/main/java/eu/faircode/email/FragmentMessages.java +++ b/app/src/main/java/eu/faircode/email/FragmentMessages.java @@ -154,8 +154,11 @@ import java.nio.charset.StandardCharsets; import java.security.KeyStore; import java.security.PrivateKey; import java.security.cert.CertPathBuilder; +import java.security.cert.CertPathBuilderResult; +import java.security.cert.CertPathValidator; import java.security.cert.CertStore; import java.security.cert.CertStoreParameters; +import java.security.cert.Certificate; import java.security.cert.CertificateFactory; import java.security.cert.CollectionCertStoreParameters; import java.security.cert.PKIXBuilderParameters; @@ -4787,6 +4790,16 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. args.putString("sender", sender); args.putBoolean("known", known); + List certs = new ArrayList<>(); + try { + for (Object m : store.getMatches(null)) { + X509CertificateHolder h = (X509CertificateHolder) m; + certs.add(new JcaX509CertificateConverter().getCertificate(h)); + } + } catch (Throwable ex) { + Log.w(ex); + } + try { // https://tools.ietf.org/html/rfc3852#section-10.2.3 KeyStore ks = KeyStore.getInstance("AndroidCAStore"); @@ -4795,12 +4808,6 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. X509CertSelector target = new X509CertSelector(); target.setCertificate(cert); - List certs = new ArrayList<>(); - for (Object m : store.getMatches(null)) { - X509CertificateHolder h = (X509CertificateHolder) m; - certs.add(new JcaX509CertificateConverter().getCertificate(h)); - } - PKIXBuilderParameters params = new PKIXBuilderParameters(ks, target); CertStoreParameters intermediates = new CollectionCertStoreParameters(certs); params.addCertStore(CertStore.getInstance("Collection", intermediates)); @@ -4808,11 +4815,29 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. params.setDate(new Date(message.received)); CertPathBuilder builder = CertPathBuilder.getInstance("PKIX"); - builder.build(params); + CertPathBuilderResult path = builder.build(params); + + CertPathValidator cpv = CertPathValidator.getInstance("PKIX"); + cpv.validate(path.getCertPath(), params); args.putBoolean("valid", true); + + ArrayList trace = new ArrayList<>(); + for (Certificate c : path.getCertPath().getCertificates()) + if (c instanceof X509Certificate) { + EntityCertificate record = EntityCertificate.from((X509Certificate) c, null); + trace.add(record.subject); + } + args.putStringArrayList("trace", trace); } catch (Throwable ex) { Log.w(ex); + + ArrayList trace = new ArrayList<>(); + for (X509Certificate c : certs) { + EntityCertificate record = EntityCertificate.from(c, null); + trace.add(record.subject); + } + args.putStringArrayList("trace", trace); } result = cert; @@ -4952,6 +4977,7 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. String sender = args.getString("sender"); boolean known = args.getBoolean("known"); boolean valid = args.getBoolean("valid"); + final ArrayList trace = args.getStringArrayList("trace"); if (cert == null) Snackbar.make(view, R.string.title_signature_invalid, Snackbar.LENGTH_LONG).show(); @@ -4992,6 +5018,23 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. tvBefore.setText(record.before == null ? null : TF.format(record.before)); tvExpired.setVisibility(record.isExpired() ? View.VISIBLE : View.GONE); + if (trace != null && trace.size() > 0) + tvSubject.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < trace.size(); i++) { + if (i > 0) + sb.append("\n\n"); + sb.append(i + 1).append(") ").append(trace.get(i)); + } + + new AlertDialog.Builder(getContext()) + .setMessage(sb.toString()) + .show(); + } + }); + AlertDialog.Builder builder = new AlertDialog.Builder(getContext()) .setView(dview) .setNegativeButton(android.R.string.cancel, null); @@ -5019,7 +5062,6 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. String fingerprint = EntityCertificate.getFingerprint(cert); List emails = EntityCertificate.getAltSubjectName(cert); - String subject = EntityCertificate.getSubject(cert); for (String email : emails) { EntityCertificate record = db.certificate().getCertificate(fingerprint, email); if (record == null) {