Skip to content

Commit

Permalink
Support for dual (perpetual + annual) certificates (qzind#708)
Browse files Browse the repository at this point in the history
Add support for multiple Trusted CAs when signing
Add ability to create demo cet from Site Manager Dialog
Add a Strict Mode to block QZ issued certs
Fix Travis-CI
Various UI improvements
  • Loading branch information
tresf authored Apr 27, 2021
1 parent 5f9ff02 commit f12bfc0
Showing 19 changed files with 690 additions and 240 deletions.
12 changes: 9 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -18,7 +18,13 @@ matrix:
osx_image: xcode12.2
language: java
dist: trusty
before_script:
- sw_vers -productVersion && brew update && brew install ant; ant -version
- test -e /etc/lsb-release && sudo apt-get update -qq && sudo apt-get install -y makeself nsis; echo;
addons:
homebrew:
packages:
- ant
apt:
packages:
- ant
- makeself
- nsis
script: ant $TARGET
6 changes: 1 addition & 5 deletions src/org/jdesktop/swinghelper/tray/JXTrayIcon.java
Original file line number Diff line number Diff line change
@@ -128,11 +128,7 @@ public static void main(String[] args) throws Exception {

UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

SwingUtilities.invokeLater(new Runnable() {
public void run() {
createGui();
}
});
SwingUtilities.invokeLater(() -> createGui());
}

static Image createImage() {
262 changes: 154 additions & 108 deletions src/qz/auth/Certificate.java

Large diffs are not rendered by default.

17 changes: 13 additions & 4 deletions src/qz/common/Constants.java
Original file line number Diff line number Diff line change
@@ -58,19 +58,28 @@ public class Constants {
public static final String PREFS_NOTIFICATIONS = "tray.notifications";
public static final String PREFS_HEADLESS = "tray.headless";
public static final String PREFS_MONOCLE = "tray.monocle";
public static final String PREFS_STRICT_MODE = "tray.strictmode";

public static final String WHITE_LIST = "Permanently allowed \"%s\" to access local resources";
public static final String BLACK_LIST = "Permanently blocked \"%s\" from accessing local resources";
public static final String ALLOW_SITES_TEXT = "Permanently allowed \"%s\" to access local resources";
public static final String BLOCK_SITES_TEXT = "Permanently blocked \"%s\" from accessing local resources";

public static final String REMEMBER_THIS_DECISION = "Remember this decision";
public static final String STRICT_MODE_LABEL = "Use strict certificate mode";
public static final String STRICT_MODE_TOOLTIP = String.format("Prevents the ability to select \"%s\" for most websites", REMEMBER_THIS_DECISION);
public static final String STRICT_MODE_CONFIRM = String.format("Set strict certificate mode? Most websites will stop working with %s.", ABOUT_TITLE);
public static final String ALLOW_SITES_LABEL = "Sites permanently allowed access";
public static final String BLOCK_SITES_LABEL = "Sites permanently blocked from access";

public static final String WHITE_SITES = "Sites permanently allowed access";
public static final String BLACK_SITES = "Sites permanently blocked from access";

public static final String ALLOWED = "Allowed";
public static final String BLOCKED = "Blocked";

public static final String OVERRIDE_CERT = "override.crt";
public static final String WHITELIST_CERT_DIR = "whitelist";

public static final String SIGNING_PRIVATE_KEY = "private-key.pem";
public static final String SIGNING_CERTIFICATE = "digital-certificate.txt";

public static final long VALID_SIGNING_PERIOD = 15 * 60 * 1000; //millis
public static final int EXPIRY_WARN = 30; // days
public static final Color WARNING_COLOR_LITE = Color.RED;
11 changes: 7 additions & 4 deletions src/qz/common/TrayManager.java
Original file line number Diff line number Diff line change
@@ -18,7 +18,6 @@
import org.slf4j.LoggerFactory;
import qz.auth.Certificate;
import qz.auth.RequestState;
import qz.installer.certificate.firefox.FirefoxCertificateInstaller;
import qz.installer.shortcut.ShortcutCreator;
import qz.ui.*;
import qz.ui.component.IconCache;
@@ -33,6 +32,7 @@
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.File;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@@ -88,6 +88,9 @@ public TrayManager(boolean isHeadless) {

prefs = new PropertyHelper(FileUtilities.USER_DIR + File.separator + Constants.PREFS_FILE + ".properties");

// Set strict certificate mode preference
Certificate.setTrustBuiltIn(!prefs.getBoolean(Constants.PREFS_STRICT_MODE, false));

//headless if turned on by user or unsupported by environment
headless = isHeadless || prefs.getBoolean(Constants.PREFS_HEADLESS, false) || GraphicsEnvironment.isHeadless();
if (headless) {
@@ -212,7 +215,7 @@ private void addMenuItems() {
JMenuItem sitesItem = new JMenuItem("Site Manager...", iconCache.getIcon(IconCache.Icon.SAVED_ICON));
sitesItem.setMnemonic(KeyEvent.VK_M);
sitesItem.addActionListener(savedListener);
sitesDialog = new SiteManagerDialog(sitesItem, iconCache);
sitesDialog = new SiteManagerDialog(sitesItem, iconCache, prefs);
componentList.add(sitesDialog);

JMenuItem diagnosticMenu = new JMenu("Diagnostic");
@@ -473,15 +476,15 @@ public boolean showGatewayDialog(final RequestState request, final String prompt

private void whiteList(Certificate cert) {
if (FileUtilities.printLineToFile(Constants.ALLOW_FILE, cert.data())) {
displayInfoMessage(String.format(Constants.WHITE_LIST, cert.getOrganization()));
displayInfoMessage(String.format(Constants.ALLOW_SITES_TEXT, cert.getOrganization()));
} else {
displayErrorMessage("Failed to write to file (Insufficient user privileges)");
}
}

private void blackList(Certificate cert) {
if (FileUtilities.printLineToFile(Constants.BLOCK_FILE, cert.data())) {
displayInfoMessage(String.format(Constants.BLACK_LIST, cert.getOrganization()));
displayInfoMessage(String.format(Constants.BLOCK_SITES_TEXT, cert.getOrganization()));
} else {
displayErrorMessage("Failed to write to file (Insufficient user privileges)");
}
4 changes: 2 additions & 2 deletions src/qz/installer/certificate/ExpiryTask.java
Original file line number Diff line number Diff line change
@@ -26,7 +26,7 @@
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.cert.CertificateParsingException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.*;

@@ -243,7 +243,7 @@ public static String[] parseHostNames(X509Certificate cert) {
log.error("getSubjectAlternativeNames is null?");
}
log.debug("Parsed hostNames: {}", String.join(", ", hostNameList));
} catch(CertificateParsingException e) {
} catch(CertificateException e) {
log.warn("Can't parse hostNames from this cert. Cert renewals will contain default values instead");
}
return hostNameList.toArray(new String[hostNameList.size()]);
9 changes: 9 additions & 0 deletions src/qz/ui/BasicDialog.java
Original file line number Diff line number Diff line change
@@ -116,6 +116,15 @@ public JComponent setContent(JComponent contentComponent, boolean autoCenter) {
return contentComponent;
}

public void addPanelComponent(JComponent component) {
for(Component c : buttonPanel.getComponents()) {
if(component.equals(c)) {
return; // don't add twice
}
}
buttonPanel.add(component, buttonPanel.getComponents().length - stockButtonCount);
}

public JButton addPanelButton(String title, IconCache.Icon icon, int mnemonic) {
return addPanelButton(title, iconCache == null? null:iconCache.getIcon(icon), mnemonic);
}
4 changes: 2 additions & 2 deletions src/qz/ui/GatewayDialog.java
Original file line number Diff line number Diff line change
@@ -84,7 +84,7 @@ private void initComponents() {

bottomPanel = new JPanel();
bottomPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 10, 5));
persistentCheckBox = new JCheckBox("Remember this decision", false);
persistentCheckBox = new JCheckBox(Constants.REMEMBER_THIS_DECISION, false);
persistentCheckBox.setMnemonic(KeyEvent.VK_R);
persistentCheckBox.addActionListener(e -> allowButton.setEnabled(!persistentCheckBox.isSelected() || request.isVerified()));
persistentCheckBox.setAlignmentX(RIGHT_ALIGNMENT);
@@ -130,7 +130,7 @@ public void actionPerformed(ActionEvent e) {
// Require confirmation for permanent block
if (!approved && persistent) {
ConfirmDialog confirmDialog = new ConfirmDialog(null, "Please Confirm", iconCache);
String message = Constants.BLACK_LIST.replace(" blocked ", " block ") + "?";
String message = Constants.BLOCK_SITES_TEXT.replace(" blocked ", " block ") + "?";
message = String.format(message, request.hasCertificate()? request.getCertName():"");
if (!confirmDialog.prompt(message)) {
persistent = false;
11 changes: 4 additions & 7 deletions src/qz/ui/LogDialog.java
Original file line number Diff line number Diff line change
@@ -63,13 +63,10 @@ public void actionPerformed(ActionEvent e) {
// add new appender to Log4J just for text area
logStream = new WriterAppender(new PatternLayout("[%p] %d{ISO8601} @ %c:%L%n\t%m%n"), new OutputStream() {
@Override
public void write(final int b) throws IOException {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
logArea.append(String.valueOf((char)b));
logPane.getVerticalScrollBar().setValue(logPane.getVerticalScrollBar().getMaximum());
}
public void write(final int b) {
SwingUtilities.invokeLater(() -> {
logArea.append(String.valueOf((char)b));
logPane.getVerticalScrollBar().setValue(logPane.getVerticalScrollBar().getMaximum());
});
}
});
Loading

0 comments on commit f12bfc0

Please sign in to comment.