Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SPARK-1926, SPARK-1927, SPARK-1928, SPARK-1929, SPARK-1938 and SPARK-1937 #344

Merged
merged 8 commits into from
Jun 7, 2017
1 change: 1 addition & 0 deletions core/src/main/java/org/jivesoftware/resource/Default.java
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ public class Default {
public static final String SSO_DISABLED = "SSO_DISABLED";
public static final String PROXY_DISABLED = "PROXY_DISABLED";
public static final String PKI_DISABLED = "PKI_DISABLED";
public static final String CERTIFICATES_MANAGER_DISABLED = "CERTIFICATES_MANAGER_DISABLED";
public static final String HELP_USER_GUIDE = "HELP_USER_GUIDE";
public static final String BROADCAST_IN_CHATWINDOW = "BROADCAST_IN_CHATWINDOW";
public static final String MENUBAR_TEXT = "MENUBAR_TEXT";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package org.jivesoftware.spark.ui.login;

import static java.awt.GridBagConstraints.HORIZONTAL;
import static java.awt.GridBagConstraints.WEST;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import org.jivesoftware.resource.Res;
import org.jivesoftware.spark.util.ResourceUtils;
import org.jivesoftware.sparkimpl.certificates.CertificateController;
import org.jivesoftware.sparkimpl.settings.local.LocalPreferences;

/**
* This class serve as visual in implementation of manageable list of certificates. Together with CertificateController
* and CertificateModel Classes this apply MVC pattern.
*
* @author Paweł Ścibiorski
*
*/
public class CertificatesManagerSettingsPanel extends JPanel implements ActionListener {

private final static Insets DEFAULT_INSETS = new Insets(5, 5, 5, 5);
private final LocalPreferences localPreferences;
private JDialog optionsDialog;
private CertificateController certControll;
private JTable certTable = new JTable();
private JCheckBox acceptAll = new JCheckBox();
private JCheckBox acceptExpired = new JCheckBox();
private JCheckBox acceptRevoked = new JCheckBox();
private JCheckBox acceptSelfSigned = new JCheckBox();
private JCheckBox checkCRL = new JCheckBox();
private JCheckBox checkOCSP = new JCheckBox();
private JScrollPane scrollPane;

public CertificatesManagerSettingsPanel(LocalPreferences localPreferences, JDialog optionsDialog) {

this.localPreferences = localPreferences;
this.optionsDialog = optionsDialog;
certControll = new CertificateController(localPreferences);
setLayout(new GridBagLayout());

certTable.setModel(certControll.getTableModel());
scrollPane = new JScrollPane(certTable);
certTable.setFillsViewportHeight(true);

ResourceUtils.resButton(acceptAll, Res.getString("checkbox.accept.all"));
ResourceUtils.resButton(acceptExpired, Res.getString("checkbox.accept.expired"));
ResourceUtils.resButton(acceptRevoked, Res.getString("checkbox.accept.invalid"));
ResourceUtils.resButton(acceptSelfSigned, Res.getString("checkbox.accept.self.signed"));
ResourceUtils.resButton(checkCRL, Res.getString("checkbox.check.crl"));
ResourceUtils.resButton(checkOCSP, Res.getString("checkbox.check.ocsp"));

acceptAll.addActionListener(this);

add(scrollPane, new GridBagConstraints(0, 0, 6, 1, 0.0, 1.0, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0));
add(acceptAll, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.5, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0));
add(acceptSelfSigned, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.5, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0));
add(acceptExpired, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.5, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0));
add(acceptRevoked, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.5, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0));
add(checkCRL, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.5, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0));
add(checkOCSP, new GridBagConstraints(1, 3, 1, 1, 0.0, 0.5, WEST, HORIZONTAL, DEFAULT_INSETS, 0, 0));
}

@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == acceptAll && acceptAll.isSelected()) {
acceptSelfSigned.setSelected(true);
acceptExpired.setSelected(true);
acceptRevoked.setSelected(true);

acceptSelfSigned.setEnabled(false);
acceptExpired.setEnabled(false);
acceptRevoked.setEnabled(false);
} else if (e.getSource() == acceptAll && !acceptAll.isSelected()) {
acceptSelfSigned.setEnabled(true);
acceptExpired.setEnabled(true);
acceptRevoked.setEnabled(true);
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public class LoginSettingDialog implements PropertyChangeListener
private ProxyLoginSettingsPanel proxyPanel;
private PkiLoginSettingsPanel pkiPanel;
private SsoLoginSettingsPanel ssoPanel;
private CertificatesManagerSettingsPanel certManager;

/**
* Empty Constructor.
Expand All @@ -53,6 +54,7 @@ public LoginSettingDialog()
proxyPanel = new ProxyLoginSettingsPanel( localPreferences, optionsDialog );
ssoPanel = new SsoLoginSettingsPanel( localPreferences, optionsDialog );
pkiPanel = new PkiLoginSettingsPanel( localPreferences, optionsDialog );
certManager = new CertificatesManagerSettingsPanel(localPreferences, optionsDialog);
}

/**
Expand Down Expand Up @@ -82,7 +84,10 @@ public boolean invoke( JFrame owner )
{
tabbedPane.addTab( Res.getString( "tab.pki" ), pkiPanel );
}

if ( !Default.getBoolean(Default.CERTIFICATES_MANAGER_DISABLED))
{
// tabbedPane.addTab( Res.getString( "tab.certificates" ), certManager );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although this will obviously do the trick, isn't the purpose of this if statement to enable/disable things, from the value of CERTIFICATES_MANAGER_DISABLED? Shouldn't we use that?

}
// Construct main panel w/ layout.
final JPanel mainPanel = new JPanel();
mainPanel.setLayout( new BorderLayout() );
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package org.jivesoftware.sparkimpl.certificates;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import javax.swing.table.DefaultTableModel;
import org.jivesoftware.resource.Res;
import org.jivesoftware.spark.util.log.Log;
import org.jivesoftware.sparkimpl.settings.local.LocalPreferences;

/**
* This class serve to extract certificates, storage them during runtime and format them and support management of them.
* Together with CertificateManagerSettingsPanel and CertificateModel Classes this apply MVC pattern.
*
* @author Paweł Ścibiorski
*
*/

public class CertificateController {
List<CertificateModel> certificates;
DefaultTableModel tableModel;
Object[] certEntry;
LocalPreferences localPreferences;
private static final String[] COLUMN_NAMES = { Res.getString("table.column.certificate.certificate"),
Res.getString("table.column.certificate.subject"), Res.getString("table.column.certificate.valid"),
Res.getString("table.column.certificate.exempted") };
private static final int NUMBER_OF_COLUMNS = COLUMN_NAMES.length;
KeyStore trustStore;

public CertificateController(LocalPreferences localPreferences) {
if (localPreferences == null) {
throw new IllegalArgumentException("localPreferences cannot be null");
}

this.localPreferences = localPreferences;
certificates = new ArrayList<>();
tableModel = new DefaultTableModel() {
// return adequate classes for columns so last column is Boolean
// displayed as checkbox
public Class<?> getColumnClass(int column) {
switch (column) {

case 0:
return String.class;
case 1:
return String.class;
case 2:
return String.class;
case 3:
return Boolean.class;
default:
return String.class;

}
}
};

tableModel.setColumnIdentifiers(COLUMN_NAMES);
certEntry = new Object[NUMBER_OF_COLUMNS];

try {
FileInputStream input = new FileInputStream(localPreferences.getTrustStorePath());
trustStore = KeyStore.getInstance(localPreferences.getPKIStore().toString());
trustStore.load(input, localPreferences.getTrustStorePassword().toCharArray());

Enumeration store = trustStore.aliases();
while (store.hasMoreElements()) {
String alias = (String) store.nextElement();
X509Certificate certificate = (X509Certificate) trustStore.getCertificate(alias);
certificates.add(new CertificateModel(certificate));
}

// put certificate from arrayList into rows with chosen columns
for (CertificateModel cert : certificates) {
certEntry[0] = cert.getIssuer();
certEntry[1] = cert.getSubject();
certEntry[2] = cert.isValid();
certEntry[3] = cert.isExempted();
tableModel.addRow(certEntry);
}
} catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e) {
Log.warning("Cannot acces Truststore, it might be not set up", e);
}
}

public DefaultTableModel getTableModel() {
return tableModel;
}

public void setTableModel(DefaultTableModel tableModel) {
this.tableModel = tableModel;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
package org.jivesoftware.sparkimpl.certificates;

import java.security.cert.X509Certificate;
import java.util.List;
import org.jivesoftware.spark.util.log.Log;

/**
* Model that keep certificate fields as String values.Together with CertificateController and
* CertificateManagerSettingsPanel classes this apply MVC pattern.
*/
public class CertificateModel {

private int version;
private String serialNumber;
private String signatureValue;
private String signatureAlgorithm;
private String issuer;
private String subject;
private String notBefore;
private String notAfter;
private String publicKey;
private String publicKeyAlgorithm;
private String issuerUniqueID;
private String subjectUniqueID;

private boolean valid;
private boolean exempted;
// List<String> extensionList;

/**
* Creates certificate model.
*
* @param version
* @param serialNumber
* @param signatureValue
* @param signatureAlgorithm
* @param issuer
* @param issuerUniqueID
* @param subject
* @param notBefore
* @param notAfter
* @param publickKeyInfo
*/
public CertificateModel(int version, String serialNumber, String signatureValue, String signatureAlgorithm,
String issuer, String subject, String notBefore, String notAfter, String publicKey,
String publicKeyAlgorithm, String issuerUniqueID, String subjectUniqueID, boolean valid, Boolean exempted) {

if (version != 3 || version != 2 || version != 1) {
throw new IllegalArgumentException("Version have to be 1, 2 or 3");
}
if (serialNumber == null || signatureValue == null || signatureAlgorithm == null || issuer == null
|| subject == null || notBefore == null || notAfter == null || publicKey == null
|| publicKeyAlgorithm == null || exempted == null) {
throw new IllegalArgumentException("Value cannot be null");
}
if (version == 1 && issuerUniqueID != null) {
throw new IllegalArgumentException(
"Unique Identifiers are present then certificate version must be 2 or 3");
}

this.version = version;
this.serialNumber = serialNumber;
this.signatureValue = signatureValue;
this.signatureAlgorithm = signatureAlgorithm;
this.issuer = issuer;
this.subject = subject;
this.notBefore = notBefore;
this.notAfter = notAfter;
this.publicKey = publicKey;
this.publicKeyAlgorithm = publicKeyAlgorithm;
this.issuerUniqueID = issuerUniqueID;
this.subjectUniqueID = subjectUniqueID;
this.valid = valid;
this.exempted = exempted;
// this.extensionList = extensionList;
}

public CertificateModel(X509Certificate certificate) {
this.version = certificate.getVersion();
this.serialNumber = certificate.getSerialNumber().toString();
this.signatureValue = certificate.getSignature().toString();
this.signatureAlgorithm = certificate.getSigAlgName();
this.issuer = certificate.getIssuerX500Principal().toString();
this.subject = certificate.getSubjectX500Principal().getName().toString();
this.notBefore = certificate.getNotBefore().toString();
this.notAfter = certificate.getNotAfter().toString();
this.publicKey = certificate.getPublicKey().toString();
this.publicKeyAlgorithm = certificate.getPublicKey().getAlgorithm().toString();
try {
this.issuerUniqueID = certificate.getIssuerUniqueID().toString();
} catch (NullPointerException e) {
Log.warning("Certificate doesn't have issuerUniqueID ", e);
}
try {
this.subjectUniqueID = certificate.getIssuerUniqueID().toString();
} catch (NullPointerException e) {
Log.warning("Certificate doesn't have subjectUniqueID ", e);
}
this.valid = valid;
this.exempted = exempted;
}

public int getVersion() {
return version;
}

public String getSerialNumber() {
return serialNumber;
}

public String getSignatureValue() {
return signatureValue;
}

public String getSignatureAlgorithm() {
return signatureAlgorithm;
}

public String getIssuer() {
return issuer;
}

public String getSubject() {
return subject;
}

public String getNotBefore() {
return notBefore;
}

public String getNotAfter() {
return notAfter;
}

public String getPublicKey() {
return publicKey;
}

public String getPublicKeyAlgorithm() {
return publicKeyAlgorithm;
}

public String getIssuerUniqueID() {
return issuerUniqueID;
}

public boolean isValid() {
return valid;
}

public boolean isExempted() {
return exempted;
}

}
2 changes: 2 additions & 0 deletions core/src/main/resources/default.properties
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ SSO_DISABLED = false
PKI_DISABLED = false
#Removes Proxy Tab
PROXY_DISABLED = false
#Removes Certificates Tab
CERTIFICATES_MANAGER_DISABLED = false


# Show Password Reset Button on LoginDialog.
Expand Down
Loading