From 64bd7d81b0185b28332abb260379a0a259506d7b Mon Sep 17 00:00:00 2001 From: Vzor- Date: Thu, 12 Sep 2024 17:39:02 -0400 Subject: [PATCH] Revert Certificate --- src/qz/auth/Certificate.java | 126 +++++----------------- src/qz/ui/SiteManagerDialog.java | 6 +- src/qz/ui/component/CertificateTable.java | 70 ++++++++++-- 3 files changed, 90 insertions(+), 112 deletions(-) diff --git a/src/qz/auth/Certificate.java b/src/qz/auth/Certificate.java index aa0eab31..19e00c9b 100644 --- a/src/qz/auth/Certificate.java +++ b/src/qz/auth/Certificate.java @@ -20,7 +20,10 @@ import java.nio.file.Path; import java.security.*; import java.security.cert.*; -import java.time.*; +import java.time.DateTimeException; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; import java.util.*; @@ -32,7 +35,6 @@ public class Certificate { private static final Logger log = LogManager.getLogger(Certificate.class); private static final String QUIETLY_FAIL = "quiet"; - private static final String NOT_PROVIDED = "Not Provided"; public enum Algorithm { SHA1("SHA1withRSA"), @@ -46,39 +48,6 @@ public enum Algorithm { } } - public enum Field { - ORGANIZATION("Organization"), - COMMON_NAME("Common Name"), - TRUSTED("Trusted"), - VALID_FROM("Valid From"), - VALID_TO("Valid To"), - FINGERPRINT("Fingerprint"), - VALID("Valid"); - - String description; - - // List of fields needed to construct a new cert. - public static final Field[] saveFields = new Field[] {FINGERPRINT, COMMON_NAME, ORGANIZATION, VALID_FROM, VALID_TO, VALID}; - public static final Field[] displayFields = new Field[] {ORGANIZATION, COMMON_NAME, TRUSTED, VALID_FROM, VALID_TO, FINGERPRINT}; - - Field(String description) { - this.description = description; - } - - @Override - public String toString() { - return description; - } - - public String getDescription() { - return description; - } - - public static int size() { - return values().length; - } - } - public static ArrayList rootCAs = new ArrayList<>(); public static Certificate builtIn; private static CertPathValidator validator; @@ -87,12 +56,15 @@ public static int size() { // id-at-description used for storing renewal information private static ASN1ObjectIdentifier RENEWAL_OF = new ASN1ObjectIdentifier("2.5.4.13"); + public static final String[] saveFields = new String[] {"fingerprint", "commonName", "organization", "validFrom", "validTo", "valid"}; + public static final String SPONSORED_CN_PREFIX = "Sponsored:"; // Valid date range allows UI to only show "Expired" text for valid certificates private static final Instant UNKNOWN_MIN = LocalDateTime.MIN.toInstant(ZoneOffset.UTC); private static final Instant UNKNOWN_MAX = LocalDateTime.MAX.toInstant(ZoneOffset.UTC); + // This `dateFormat` corresponds to the `dateParse` in CertificateTable. If this line is changed, change it there as well. private static DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); private static DateTimeFormatter dateParse = DateTimeFormatter.ofPattern("uuuu-MM-dd['T'][ ]HH:mm:ss[.n]['Z']"); //allow parsing of both ISO and custom formatted dates @@ -114,13 +86,13 @@ public static int size() { public static final Certificate UNKNOWN; static { - HashMap map = new HashMap<>(); - map.put(Field.FINGERPRINT, "UNKNOWN REQUEST"); - map.put(Field.COMMON_NAME, "An anonymous request"); - map.put(Field.ORGANIZATION, "Unknown"); - map.put(Field.VALID_FROM, UNKNOWN_MIN.toString()); - map.put(Field.VALID_TO, UNKNOWN_MAX.toString()); - map.put(Field.VALID, "false"); + HashMap map = new HashMap<>(); + map.put("fingerprint", "UNKNOWN REQUEST"); + map.put("commonName", "An anonymous request"); + map.put("organization", "Unknown"); + map.put("validFrom", UNKNOWN_MIN.toString()); + map.put("validTo", UNKNOWN_MAX.toString()); + map.put("valid", "false"); UNKNOWN = Certificate.loadCertificate(map); } @@ -344,16 +316,16 @@ private Certificate() {} /** * Used to rebuild a certificate for the 'Saved Sites' screen without having to decrypt the certificates again */ - public static Certificate loadCertificate(HashMap data) { + public static Certificate loadCertificate(HashMap data) { Certificate cert = new Certificate(); - cert.fingerprint = data.get(Field.FINGERPRINT); - cert.commonName = data.get(Field.COMMON_NAME); - cert.organization = data.get(Field.ORGANIZATION); + cert.fingerprint = data.get("fingerprint"); + cert.commonName = data.get("commonName"); + cert.organization = data.get("organization"); try { - cert.validFrom = Instant.from(LocalDateTime.from(dateParse.parse(data.get(Field.VALID_FROM))).atZone(ZoneOffset.UTC)); - cert.validTo = Instant.from(LocalDateTime.from(dateParse.parse(data.get(Field.VALID_TO))).atZone(ZoneOffset.UTC)); + cert.validFrom = Instant.from(LocalDateTime.from(dateParse.parse(data.get("validFrom"))).atZone(ZoneOffset.UTC)); + cert.validTo = Instant.from(LocalDateTime.from(dateParse.parse(data.get("validTo"))).atZone(ZoneOffset.UTC)); } catch(DateTimeException e) { cert.validFrom = UNKNOWN_MIN; @@ -362,7 +334,7 @@ public static Certificate loadCertificate(HashMap data) { log.warn("Unable to parse certificate date: {}", e.getMessage()); } - cert.valid = Boolean.parseBoolean(data.get(Field.VALID)); + cert.valid = Boolean.parseBoolean(data.get("valid")); return cert; } @@ -434,30 +406,6 @@ private static boolean existsInAnyFile(String fingerprint, File... files) { return false; } - public String get(Field field) { - return get(field, null); - } - - public String get(Field field, Object optArg) { - switch(field) { - case ORGANIZATION: - return getOrganization(); - case COMMON_NAME: - return getCommonName(); - case TRUSTED: - return String.valueOf(isTrusted()); - case VALID_FROM: - return getValidFrom((TimeZone)optArg); - case VALID_TO: - return getValidTo((TimeZone)optArg); - case FINGERPRINT: - return getFingerprint(); - case VALID: - return String.valueOf(isValid()); - default: - return null; - } - } public String getFingerprint() { return fingerprint; @@ -472,41 +420,19 @@ public String getOrganization() { } public String getValidFrom() { - return getValidFrom(null); - } - - public String getValidFrom(TimeZone timeZone) { if (validFrom.isAfter(UNKNOWN_MIN)) { - return formatDate(validFrom, timeZone); + return dateFormat.format(validFrom.atZone(ZoneOffset.UTC)); } else { - return NOT_PROVIDED; + return "Not Provided"; } } public String getValidTo() { - return getValidTo(null); - } - - public String getValidTo(TimeZone timeZone) { if (validTo.isBefore(UNKNOWN_MAX)) { - return formatDate(validTo, timeZone); - } else { - return NOT_PROVIDED; - } - } - - private static String formatDate(Instant date, TimeZone timeZone) { - ZoneId zoneId; - String timeZoneString; - if (timeZone == null) { - zoneId = ZoneOffset.UTC; - timeZoneString = ""; // If no timezone was included, don't append a timezone ID. + return dateFormat.format(validTo.atZone(ZoneOffset.UTC)); } else { - zoneId = timeZone.toZoneId(); - timeZoneString = " " + timeZone.getDisplayName(false, TimeZone.SHORT); + return "Not Provided"; } - - return dateFormat.format(date.atZone(zoneId)) + timeZoneString; } public Instant getValidFromDate() { @@ -609,4 +535,4 @@ private static String getSubjectX509Principal(X509Certificate cert, ASN1ObjectId return ""; } -} +} \ No newline at end of file diff --git a/src/qz/ui/SiteManagerDialog.java b/src/qz/ui/SiteManagerDialog.java index 734403bf..a9235b2c 100644 --- a/src/qz/ui/SiteManagerDialog.java +++ b/src/qz/ui/SiteManagerDialog.java @@ -554,10 +554,10 @@ public ArrayList readCertificates(ArrayList dataMap = new HashMap<>(); + if (data.length == Certificate.saveFields.length) { + HashMap dataMap = new HashMap<>(); for(int i = 0; i < data.length; i++) { - dataMap.put(Certificate.Field.saveFields[i], data[i]); + dataMap.put(Certificate.saveFields[i], data[i]); } CertificateDisplay certificate = new CertificateDisplay(Certificate.loadCertificate(dataMap), local); diff --git a/src/qz/ui/component/CertificateTable.java b/src/qz/ui/component/CertificateTable.java index a90ef429..ce239bcf 100644 --- a/src/qz/ui/component/CertificateTable.java +++ b/src/qz/ui/component/CertificateTable.java @@ -9,8 +9,14 @@ import java.awt.*; import java.awt.event.*; import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; +import java.time.temporal.TemporalAccessor; import java.util.TimeZone; +import java.util.function.Function; /** * Created by Tres on 2/22/2015. @@ -20,13 +26,59 @@ public class CertificateTable extends DisplayTable implements Themeable { private Certificate cert; private static final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone("UTC"); + private static DateTimeFormatter dateParse = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + private Instant warn; private Instant now; private boolean useLocalTimezoneValidTo = false; private boolean useLocalTimezoneValidFrom = false; + enum CertificateField { + ORGANIZATION("Organization", (Certificate cert) -> cert.getOrganization()), + COMMON_NAME("Common Name", (Certificate cert) -> cert.getCommonName()), + TRUSTED("Trusted", (Certificate cert) -> cert.isTrusted()), + VALID_FROM("Valid From", (Certificate cert) -> cert.getValidFrom()), + VALID_TO("Valid To", (Certificate cert) -> cert.getValidTo()), + FINGERPRINT("Fingerprint", (Certificate cert) -> cert.getFingerprint()); + + String description; + Function getter; + + CertificateField(String description, Function getter) { + this.description = description; + this.getter = getter; + } + + public String getValue(Certificate cert, TimeZone timeZone) { + switch(this) { + case VALID_FROM: + case VALID_TO: + TemporalAccessor parsedDate = dateParse.parse(getter.apply(cert).toString()); // parse date string from cert + ZonedDateTime utcTime = LocalDateTime.from(parsedDate).atZone(ZoneOffset.UTC); // shift the timezone + return dateParse.format(Instant.from(utcTime).atZone(timeZone.toZoneId())) + " " + timeZone.getDisplayName(false, TimeZone.SHORT); + default: + return getter.apply(cert).toString(); + } + } + + @Override + public String toString() { + return description; + } + + public String getDescription() { + return description; + } + + public static int size() { + return values().length; + } + } + public CertificateTable(IconCache iconCache) { super(iconCache); + + setDefaultRenderer(Object.class, new CertificateTableCellRenderer()); addMouseListener(new MouseAdapter() { int lastRow = -1; @@ -40,12 +92,12 @@ public void mousePressed(MouseEvent e) { int col = target.getSelectedColumn(); // Only trigger after the cell is click AND highlighted. This make copying text easier. if (row == lastRow && col == lastCol) { - Certificate.Field rowKey = (Certificate.Field)target.getValueAt(row, 0); - if (rowKey == Certificate.Field.VALID_TO) { + CertificateField rowKey = (CertificateField)target.getValueAt(row, 0); + if (rowKey == CertificateField.VALID_TO) { useLocalTimezoneValidTo = !useLocalTimezoneValidTo; refreshComponents(); changeSelection(row, col, false, false); - } else if (rowKey == Certificate.Field.VALID_FROM) { + } else if (rowKey == CertificateField.VALID_FROM) { useLocalTimezoneValidFrom = !useLocalTimezoneValidFrom; refreshComponents(); changeSelection(row, col, false, false); @@ -80,7 +132,7 @@ public void refreshComponents() { removeRows(); // First Column - for(Certificate.Field field : Certificate.Field.displayFields) { + for(CertificateField field : CertificateField.values()) { TimeZone timeZone = null; switch(field){ case TRUSTED: @@ -95,7 +147,7 @@ public void refreshComponents() { default: break; } - model.addRow(new Object[] {field, cert.get(field, timeZone)}); + model.addRow(new Object[] {field, field.getValue(cert, timeZone)}); } repaint(); @@ -108,7 +160,7 @@ public void refresh() { } public void autoSize() { - super.autoSize(Certificate.Field.displayFields.length, 2); + super.autoSize(CertificateField.size(), 2); } /** Custom cell renderer for JTable to allow colors and styles not directly available in a JTable */ @@ -119,8 +171,8 @@ public Component getTableCellRendererComponent(JTable table, Object value, boole JLabel label = (JLabel)super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col); // First Column - if (value instanceof Certificate.Field) { - switch((Certificate.Field)value) { + if (value instanceof CertificateField) { + switch((CertificateField)value) { case VALID_FROM: boolean futureExpiration = cert.getValidFromDate().isAfter(now); label = stylizeLabel(futureExpiration? STATUS_WARNING:STATUS_NORMAL, label, isSelected, "future inception"); @@ -145,7 +197,7 @@ public Component getTableCellRendererComponent(JTable table, Object value, boole // Second Column if (cert == null || col < 1) { return stylizeLabel(STATUS_NORMAL, label, isSelected); } - Certificate.Field field = (Certificate.Field)table.getValueAt(row, col - 1); + CertificateField field = (CertificateField)table.getValueAt(row, col - 1); if (field == null) { return stylizeLabel(STATUS_NORMAL, label, isSelected); } switch(field) { case TRUSTED: