/*
|
* The contents of this file are subject to the terms of the Common Development and
|
* Distribution License (the License). You may not use this file except in compliance with the
|
* License.
|
*
|
* You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
|
* specific language governing permission and limitations under the License.
|
*
|
* When distributing Covered Software, include this CDDL Header Notice in each file and include
|
* the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
|
* Header, with the fields enclosed by brackets [] replaced by your own identifying
|
* information: "Portions Copyright [year] [name of copyright owner]".
|
*
|
* Copyright 2008-2010 Sun Microsystems, Inc.
|
* Portions Copyright 2013-2016 ForgeRock AS.
|
*/
|
package org.opends.quicksetup.installer.ui;
|
|
import java.awt.Component;
|
import java.awt.GridBagConstraints;
|
import java.awt.GridBagLayout;
|
import java.awt.Insets;
|
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionListener;
|
import java.awt.event.WindowAdapter;
|
import java.awt.event.WindowEvent;
|
import java.io.File;
|
import java.security.KeyStoreException;
|
import java.util.ArrayList;
|
import java.util.Arrays;
|
|
import javax.swing.Box;
|
import javax.swing.ButtonGroup;
|
import javax.swing.JButton;
|
import javax.swing.JCheckBox;
|
import javax.swing.JComponent;
|
import javax.swing.JDialog;
|
import javax.swing.JFrame;
|
import javax.swing.JLabel;
|
import javax.swing.JPanel;
|
import javax.swing.JPasswordField;
|
import javax.swing.JRadioButton;
|
import javax.swing.JTextField;
|
import javax.swing.SwingUtilities;
|
import javax.swing.text.JTextComponent;
|
|
import org.opends.quicksetup.SecurityOptions;
|
import org.opends.quicksetup.event.BrowseActionListener;
|
import org.opends.quicksetup.event.MinimumSizeComponentListener;
|
import org.opends.quicksetup.installer.Installer;
|
import org.opends.quicksetup.ui.UIFactory;
|
import org.opends.quicksetup.ui.Utilities;
|
import org.opends.quicksetup.util.BackgroundTask;
|
import org.opends.quicksetup.util.Utils;
|
import org.opends.server.util.CertificateManager;
|
import org.opends.server.util.StaticUtils;
|
import org.forgerock.i18n.LocalizableMessage;
|
|
import static org.opends.messages.QuickSetupMessages.*;
|
import static com.forgerock.opendj.cli.Utils.getThrowableMsg;
|
|
/**
|
* This class is a dialog that appears when the user wants to configure
|
* security parameters for the new OpenDS instance.
|
*/
|
public class SecurityOptionsDialog extends JDialog
|
{
|
private static final long serialVersionUID = 4083707346899442215L;
|
|
private JCheckBox cbEnableSSL;
|
private JCheckBox cbEnableStartTLS;
|
private JTextField tfPort;
|
private JRadioButton rbUseSelfSignedCertificate;
|
private JRadioButton rbUseExistingCertificate;
|
private JLabel lKeystoreType;
|
private JRadioButton rbPKCS11;
|
private JRadioButton rbJKS;
|
private JRadioButton rbJCEKS;
|
private JRadioButton rbPKCS12;
|
private JLabel lKeystorePath;
|
private JTextField tfKeystorePath;
|
private JButton browseButton;
|
private JLabel lKeystorePwd;
|
private JPasswordField tfKeystorePwd;
|
|
private JButton cancelButton;
|
private JButton okButton;
|
|
private SelectAliasDialog aliasDlg;
|
|
private boolean isCanceled = true;
|
|
private SecurityOptions securityOptions;
|
|
private String[] aliases;
|
private boolean certificateHasAlias;
|
private String selectedAlias;
|
|
private final int DEFAULT_PORT = 636;
|
|
/**
|
* Constructor of the SecurityOptionsDialog.
|
* @param parent the parent frame for this dialog.
|
* @param options the SecurityOptions used to populate this dialog.
|
* @throws IllegalArgumentException if options is null.
|
*/
|
public SecurityOptionsDialog(JFrame parent, SecurityOptions options)
|
throws IllegalArgumentException
|
{
|
super(parent);
|
setTitle(INFO_SECURITY_OPTIONS_DIALOG_TITLE.get().toString());
|
securityOptions = options;
|
getContentPane().add(createPanel());
|
pack();
|
|
updateContents();
|
|
int minWidth = (int) getPreferredSize().getWidth();
|
int minHeight = (int) getPreferredSize().getHeight();
|
addComponentListener(new MinimumSizeComponentListener(this, minWidth,
|
minHeight));
|
getRootPane().setDefaultButton(okButton);
|
|
addWindowListener(new WindowAdapter()
|
{
|
@Override
|
public void windowClosing(WindowEvent e)
|
{
|
cancelClicked();
|
}
|
});
|
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
|
|
Utilities.centerOnComponent(this, parent);
|
}
|
|
/**
|
* Returns <CODE>true</CODE> if the user clicked on cancel and
|
* <CODE>false</CODE> otherwise.
|
* @return <CODE>true</CODE> if the user clicked on cancel and
|
* <CODE>false</CODE> otherwise.
|
*/
|
public boolean isCanceled()
|
{
|
return isCanceled;
|
}
|
|
/**
|
* Displays this dialog and populates its contents with the provided
|
* SecurityOptions object.
|
* @param options the SecurityOptions used to populate this dialog.
|
* @throws IllegalArgumentException if options is null.
|
*/
|
public void display(SecurityOptions options) throws IllegalArgumentException
|
{
|
if (options == null)
|
{
|
throw new IllegalArgumentException("options parameter cannot be null.");
|
}
|
UIFactory.setTextStyle(cbEnableSSL,
|
UIFactory.TextStyle.SECONDARY_FIELD_VALID);
|
UIFactory.setTextStyle(lKeystorePath,
|
UIFactory.TextStyle.SECONDARY_FIELD_VALID);
|
UIFactory.setTextStyle(lKeystorePwd,
|
UIFactory.TextStyle.SECONDARY_FIELD_VALID);
|
|
securityOptions = options;
|
updateContents();
|
|
isCanceled = true;
|
|
setVisible(true);
|
}
|
|
/**
|
* Returns the security options object representing the input of the user
|
* in this panel.
|
* @return the security options object representing the input of the user
|
* in this panel.
|
*/
|
public SecurityOptions getSecurityOptions()
|
{
|
SecurityOptions ops;
|
|
boolean enableSSL = cbEnableSSL.isSelected();
|
boolean enableStartTLS = cbEnableStartTLS.isSelected();
|
if (enableSSL || enableStartTLS)
|
{
|
int sslPort = -1;
|
try
|
{
|
sslPort = Integer.parseInt(tfPort.getText());
|
}
|
catch (Throwable t)
|
{
|
}
|
if (rbUseSelfSignedCertificate.isSelected())
|
{
|
ops = SecurityOptions.createSelfSignedCertificateOptions(
|
enableSSL, enableStartTLS, sslPort);
|
}
|
else if (rbJKS.isSelected())
|
{
|
ops = SecurityOptions.createJKSCertificateOptions(
|
tfKeystorePath.getText(),
|
String.valueOf(tfKeystorePwd.getPassword()), enableSSL,
|
enableStartTLS, sslPort, Arrays.asList(selectedAlias));
|
}
|
else if (rbJCEKS.isSelected())
|
{
|
ops = SecurityOptions.createJCEKSCertificateOptions(
|
tfKeystorePath.getText(),
|
String.valueOf(tfKeystorePwd.getPassword()), enableSSL,
|
enableStartTLS, sslPort, Arrays.asList(selectedAlias));
|
}
|
else if (rbPKCS11.isSelected())
|
{
|
ops = SecurityOptions.createPKCS11CertificateOptions(
|
String.valueOf(tfKeystorePwd.getPassword()), enableSSL,
|
enableStartTLS, sslPort, Arrays.asList(selectedAlias));
|
}
|
else if (rbPKCS12.isSelected())
|
{
|
ops = SecurityOptions.createPKCS12CertificateOptions(
|
tfKeystorePath.getText(),
|
String.valueOf(tfKeystorePwd.getPassword()), enableSSL,
|
enableStartTLS, sslPort, Arrays.asList(selectedAlias));
|
}
|
else
|
{
|
throw new IllegalStateException("No certificate options selected.");
|
}
|
}
|
else
|
{
|
ops = SecurityOptions.createNoCertificateOptions();
|
}
|
return ops;
|
}
|
|
/**
|
* Creates and returns the panel of the dialog.
|
* @return the panel of the dialog.
|
*/
|
private JPanel createPanel()
|
{
|
GridBagConstraints gbc = new GridBagConstraints();
|
|
JPanel contentPanel = new JPanel(new GridBagLayout());
|
contentPanel.setBackground(UIFactory.DEFAULT_BACKGROUND);
|
gbc.fill = GridBagConstraints.BOTH;
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
gbc.weightx = 1.0;
|
|
JPanel topPanel = new JPanel(new GridBagLayout());
|
topPanel.setBorder(UIFactory.DIALOG_PANEL_BORDER);
|
topPanel.setBackground(UIFactory.CURRENT_STEP_PANEL_BACKGROUND);
|
Insets insets = UIFactory.getCurrentStepPanelInsets();
|
|
gbc.weighty = 0.0;
|
insets.bottom = 0;
|
gbc.insets = insets;
|
topPanel.add(createTitlePanel(), gbc);
|
gbc.insets.top = UIFactory.TOP_INSET_INSTRUCTIONS_SUBPANEL;
|
topPanel.add(createInstructionsPane(), gbc);
|
gbc.insets.top = UIFactory.TOP_INSET_INPUT_SUBPANEL;
|
gbc.insets.bottom = UIFactory.TOP_INSET_INPUT_SUBPANEL;
|
topPanel.add(createInputPanel(), gbc);
|
gbc.weighty = 1.0;
|
gbc.insets = UIFactory.getEmptyInsets();
|
topPanel.add(Box.createVerticalGlue(), gbc);
|
contentPanel.add(topPanel, gbc);
|
gbc.weighty = 0.0;
|
gbc.insets = UIFactory.getButtonsPanelInsets();
|
contentPanel.add(createButtonsPanel(), gbc);
|
|
return contentPanel;
|
}
|
|
/**
|
* Creates and returns the title sub panel.
|
* @return the title sub panel.
|
*/
|
private Component createTitlePanel()
|
{
|
JPanel titlePanel = new JPanel(new GridBagLayout());
|
GridBagConstraints gbc = new GridBagConstraints();
|
titlePanel.setOpaque(false);
|
gbc.anchor = GridBagConstraints.NORTHWEST;
|
gbc.fill = GridBagConstraints.BOTH;
|
gbc.weightx = 0.0;
|
gbc.gridwidth = GridBagConstraints.RELATIVE;
|
|
LocalizableMessage title = INFO_SECURITY_OPTIONS_TITLE.get();
|
JLabel l =
|
UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, title,
|
UIFactory.TextStyle.TITLE);
|
l.setOpaque(false);
|
titlePanel.add(l, gbc);
|
|
gbc.gridwidth = GridBagConstraints.RELATIVE;
|
gbc.anchor = GridBagConstraints.NORTHWEST;
|
gbc.weightx = 1.0;
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
gbc.insets.left = 0;
|
gbc.weightx = 1.0;
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
titlePanel.add(Box.createHorizontalGlue(), gbc);
|
|
return titlePanel;
|
}
|
|
/**
|
* Creates and returns the instructions sub panel.
|
* @return the instructions sub panel.
|
*/
|
private Component createInstructionsPane()
|
{
|
LocalizableMessage instructions = INFO_SECURITY_OPTIONS_INSTRUCTIONS.get();
|
|
JTextComponent instructionsPane =
|
UIFactory.makeHtmlPane(instructions, UIFactory.INSTRUCTIONS_FONT);
|
instructionsPane.setOpaque(false);
|
instructionsPane.setEditable(false);
|
|
return instructionsPane;
|
}
|
|
/**
|
* Creates and returns the input sub panel: the panel with all the widgets
|
* that are used to define the security options.
|
* @return the input sub panel.
|
*/
|
private Component createInputPanel()
|
{
|
JPanel inputPanel = new JPanel(new GridBagLayout());
|
inputPanel.setOpaque(false);
|
|
ActionListener l = new ActionListener()
|
{
|
@Override
|
public void actionPerformed(ActionEvent ev)
|
{
|
updateEnablingState();
|
}
|
};
|
|
cbEnableSSL = UIFactory.makeJCheckBox(INFO_ENABLE_SSL_LABEL.get(),
|
INFO_ENABLE_SSL_TOOLTIP.get(), UIFactory.TextStyle.PRIMARY_FIELD_VALID);
|
cbEnableSSL.addActionListener(l);
|
String sPort = "";
|
int port = securityOptions.getSslPort();
|
if (port > 0)
|
{
|
sPort = String.valueOf(port);
|
}
|
tfPort = UIFactory.makeJTextField(LocalizableMessage.raw(sPort),
|
INFO_SSL_PORT_TEXTFIELD_TOOLTIP.get(), UIFactory.PORT_FIELD_SIZE,
|
UIFactory.TextStyle.TEXTFIELD);
|
cbEnableStartTLS = UIFactory.makeJCheckBox(INFO_ENABLE_STARTTLS_LABEL.get(),
|
INFO_ENABLE_STARTTLS_TOOLTIP.get(),
|
UIFactory.TextStyle.SECONDARY_FIELD_VALID);
|
cbEnableStartTLS.addActionListener(l);
|
rbUseSelfSignedCertificate = UIFactory.makeJRadioButton(
|
INFO_USE_SELF_SIGNED_LABEL.get(),
|
INFO_USE_SELF_SIGNED_TOOLTIP.get(),
|
UIFactory.TextStyle.SECONDARY_FIELD_VALID);
|
rbUseSelfSignedCertificate.addActionListener(l);
|
rbUseExistingCertificate = UIFactory.makeJRadioButton(
|
INFO_USE_EXISTING_CERTIFICATE_LABEL.get(),
|
INFO_USE_EXISTING_CERTIFICATE_TOOLTIP.get(),
|
UIFactory.TextStyle.SECONDARY_FIELD_VALID);
|
rbUseExistingCertificate.addActionListener(l);
|
ButtonGroup group1 = new ButtonGroup();
|
group1.add(rbUseSelfSignedCertificate);
|
group1.add(rbUseExistingCertificate);
|
|
lKeystoreType = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
|
INFO_KEYSTORE_TYPE_LABEL.get(),
|
UIFactory.TextStyle.SECONDARY_FIELD_VALID);
|
lKeystoreType.setOpaque(false);
|
rbJKS = UIFactory.makeJRadioButton(
|
INFO_JKS_CERTIFICATE_LABEL.get(),
|
INFO_JKS_CERTIFICATE_TOOLTIP.get(),
|
UIFactory.TextStyle.SECONDARY_FIELD_VALID);
|
rbJKS.addActionListener(l);
|
rbJCEKS = UIFactory.makeJRadioButton(
|
INFO_JCEKS_CERTIFICATE_LABEL.get(),
|
INFO_JCEKS_CERTIFICATE_TOOLTIP.get(),
|
UIFactory.TextStyle.SECONDARY_FIELD_VALID);
|
rbJCEKS.addActionListener(l);
|
rbPKCS11 = UIFactory.makeJRadioButton(
|
INFO_PKCS11_CERTIFICATE_LABEL.get(),
|
INFO_PKCS11_CERTIFICATE_TOOLTIP.get(),
|
UIFactory.TextStyle.SECONDARY_FIELD_VALID);
|
rbPKCS11.addActionListener(l);
|
rbPKCS12 = UIFactory.makeJRadioButton(
|
INFO_PKCS12_CERTIFICATE_LABEL.get(),
|
INFO_PKCS12_CERTIFICATE_TOOLTIP.get(),
|
UIFactory.TextStyle.SECONDARY_FIELD_VALID);
|
rbPKCS12.addActionListener(l);
|
ButtonGroup group2 = new ButtonGroup();
|
group2.add(rbJKS);
|
group2.add(rbJCEKS);
|
group2.add(rbPKCS11);
|
group2.add(rbPKCS12);
|
lKeystoreType.setLabelFor(rbJKS);
|
|
lKeystorePath = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
|
INFO_KEYSTORE_PATH_LABEL.get(),
|
UIFactory.TextStyle.SECONDARY_FIELD_VALID);
|
lKeystorePath.setOpaque(false);
|
tfKeystorePath = UIFactory.makeJTextField(LocalizableMessage.EMPTY,
|
INFO_KEYSTORE_PATH_TOOLTIP.get(),
|
UIFactory.HOST_FIELD_SIZE, UIFactory.TextStyle.TEXTFIELD);
|
lKeystorePath.setLabelFor(tfKeystorePath);
|
browseButton =
|
UIFactory.makeJButton(INFO_BROWSE_BUTTON_LABEL.get(),
|
INFO_BROWSE_BUTTON_TOOLTIP.get());
|
|
BrowseActionListener browseListener =
|
new BrowseActionListener(tfKeystorePath,
|
BrowseActionListener.BrowseType.GENERIC_FILE,
|
this);
|
browseButton.addActionListener(browseListener);
|
|
lKeystorePwd = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
|
INFO_KEYSTORE_PWD_LABEL.get(),
|
UIFactory.TextStyle.SECONDARY_FIELD_VALID);
|
lKeystorePwd.setOpaque(false);
|
tfKeystorePwd = UIFactory.makeJPasswordField(LocalizableMessage.EMPTY,
|
INFO_KEYSTORE_PWD_TOOLTIP.get(),
|
UIFactory.PASSWORD_FIELD_SIZE, UIFactory.TextStyle.PASSWORD_FIELD);
|
lKeystorePwd.setLabelFor(tfKeystorePwd);
|
|
GridBagConstraints gbc = new GridBagConstraints();
|
gbc.anchor = GridBagConstraints.WEST;
|
gbc.weightx = 0.0;
|
gbc.gridwidth = GridBagConstraints.RELATIVE;
|
gbc.insets = UIFactory.getEmptyInsets();
|
gbc.fill = GridBagConstraints.HORIZONTAL;
|
inputPanel.add(UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
|
INFO_SSL_ACCESS_LABEL.get(), UIFactory.TextStyle.PRIMARY_FIELD_VALID),
|
gbc);
|
|
JPanel auxPanel = new JPanel(new GridBagLayout());
|
auxPanel.setOpaque(false);
|
gbc.gridwidth = 4;
|
gbc.fill = GridBagConstraints.NONE;
|
auxPanel.add(cbEnableSSL, gbc);
|
gbc.gridwidth--;
|
gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD;
|
auxPanel.add(tfPort, gbc);
|
gbc.gridwidth = GridBagConstraints.RELATIVE;
|
auxPanel.add(UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
|
getPortHelpMessage(), UIFactory.TextStyle.SECONDARY_FIELD_VALID), gbc);
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
gbc.fill = GridBagConstraints.HORIZONTAL;
|
gbc.weightx = 1.0;
|
auxPanel.add(Box.createHorizontalGlue(), gbc);
|
|
gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD;
|
gbc.weightx = 1.0;
|
inputPanel.add(auxPanel, gbc);
|
|
gbc.insets = UIFactory.getEmptyInsets();
|
gbc.insets.top = UIFactory.TOP_INSET_SECONDARY_FIELD;
|
gbc.gridwidth = GridBagConstraints.RELATIVE;
|
gbc.weightx = 0.0;
|
inputPanel.add(UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
|
INFO_STARTTLS_ACCESS_LABEL.get(),
|
UIFactory.TextStyle.PRIMARY_FIELD_VALID),
|
gbc);
|
auxPanel = new JPanel(new GridBagLayout());
|
auxPanel.setOpaque(false);
|
gbc.gridwidth = GridBagConstraints.RELATIVE;
|
gbc.insets = UIFactory.getEmptyInsets();
|
auxPanel.add(cbEnableStartTLS, gbc);
|
gbc.weightx = 1.0;
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
auxPanel.add(Box.createHorizontalGlue(), gbc);
|
gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD;
|
gbc.insets.top = UIFactory.TOP_INSET_SECONDARY_FIELD;
|
inputPanel.add(auxPanel, gbc);
|
|
gbc.insets = UIFactory.getEmptyInsets();
|
gbc.insets.top = UIFactory.TOP_INSET_SECONDARY_FIELD;
|
gbc.anchor = GridBagConstraints.NORTHWEST;
|
gbc.gridwidth = GridBagConstraints.RELATIVE;
|
gbc.weightx = 0.0;
|
JLabel lCertificate = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
|
INFO_CERTIFICATE_LABEL.get(), UIFactory.TextStyle.PRIMARY_FIELD_VALID);
|
int additionalInset = Math.abs(lCertificate.getPreferredSize().height -
|
rbUseSelfSignedCertificate.getPreferredSize().height) / 2;
|
gbc.insets.top += additionalInset;
|
inputPanel.add(lCertificate, gbc);
|
auxPanel = new JPanel(new GridBagLayout());
|
auxPanel.setOpaque(false);
|
gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD;
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
gbc.weightx = 1.0;
|
gbc.insets.top = UIFactory.TOP_INSET_SECONDARY_FIELD;
|
inputPanel.add(auxPanel, gbc);
|
|
gbc.insets = UIFactory.getEmptyInsets();
|
gbc.anchor = GridBagConstraints.WEST;
|
JPanel aux2Panel = new JPanel(new GridBagLayout());
|
aux2Panel.setOpaque(false);
|
gbc.gridwidth = GridBagConstraints.RELATIVE;
|
aux2Panel.add(rbUseSelfSignedCertificate, gbc);
|
gbc.weightx = 1.0;
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
aux2Panel.add(Box.createHorizontalGlue(), gbc);
|
auxPanel.add(aux2Panel, gbc);
|
|
aux2Panel = new JPanel(new GridBagLayout());
|
aux2Panel.setOpaque(false);
|
gbc.gridwidth = GridBagConstraints.RELATIVE;
|
gbc.insets = UIFactory.getEmptyInsets();
|
gbc.weightx = 0.0;
|
aux2Panel.add(rbUseExistingCertificate, gbc);
|
gbc.weightx = 1.0;
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
aux2Panel.add(Box.createHorizontalGlue(), gbc);
|
gbc.insets.top = UIFactory.TOP_INSET_SECONDARY_FIELD;
|
auxPanel.add(aux2Panel, gbc);
|
|
additionalInset = Math.abs(lKeystoreType.getPreferredSize().height -
|
rbJKS.getPreferredSize().height) / 2;
|
aux2Panel = new JPanel(new GridBagLayout());
|
aux2Panel.setOpaque(false);
|
gbc.insets.top -= additionalInset;
|
gbc.insets.left = UIFactory.LEFT_INSET_RADIO_SUBORDINATE;
|
auxPanel.add(aux2Panel, gbc);
|
|
gbc.gridwidth = GridBagConstraints.RELATIVE;
|
gbc.insets = UIFactory.getEmptyInsets();
|
gbc.weightx = 0.0;
|
gbc.anchor = GridBagConstraints.NORTHWEST;
|
gbc.insets.top = additionalInset;
|
aux2Panel.add(lKeystoreType, gbc);
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
gbc.insets.top = 0;
|
aux2Panel.add(rbJKS, gbc);
|
|
gbc.insets.top = UIFactory.TOP_INSET_RADIOBUTTON;
|
gbc.gridwidth = GridBagConstraints.RELATIVE;
|
aux2Panel.add(Box.createHorizontalGlue(), gbc);
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
aux2Panel.add(rbJCEKS, gbc);
|
gbc.gridwidth = GridBagConstraints.RELATIVE;
|
aux2Panel.add(Box.createHorizontalGlue(), gbc);
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
aux2Panel.add(rbPKCS12, gbc);
|
gbc.gridwidth = GridBagConstraints.RELATIVE;
|
aux2Panel.add(Box.createHorizontalGlue(), gbc);
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
aux2Panel.add(rbPKCS11, gbc);
|
|
gbc.gridwidth = GridBagConstraints.RELATIVE;
|
gbc.insets.left = 0;
|
gbc.weightx = 0.0;
|
gbc.anchor = GridBagConstraints.WEST;
|
aux2Panel.add(lKeystorePath, gbc);
|
JPanel aux3Panel = new JPanel(new GridBagLayout());
|
aux3Panel.setOpaque(false);
|
gbc.weightx = 1.0;
|
gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD;
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
aux2Panel.add(aux3Panel, gbc);
|
gbc.insets = UIFactory.getEmptyInsets();
|
gbc.gridwidth = GridBagConstraints.RELATIVE;
|
aux3Panel.add(tfKeystorePath, gbc);
|
gbc.insets.left = UIFactory.LEFT_INSET_BROWSE;
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
gbc.weightx = 0.0;
|
aux3Panel.add(browseButton, gbc);
|
|
gbc.insets.left = 0;
|
gbc.insets.top = UIFactory.TOP_INSET_SECONDARY_FIELD;
|
gbc.gridwidth = GridBagConstraints.RELATIVE;
|
gbc.weightx = 0.0;
|
gbc.anchor = GridBagConstraints.WEST;
|
aux2Panel.add(lKeystorePwd, gbc);
|
gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD;
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
gbc.fill = GridBagConstraints.NONE;
|
aux2Panel.add(tfKeystorePwd, gbc);
|
|
return inputPanel;
|
}
|
|
/**
|
* Creates and returns the buttons OK/CANCEL sub panel.
|
* @return the buttons OK/CANCEL sub panel.
|
*/
|
private Component createButtonsPanel()
|
{
|
JPanel buttonsPanel = new JPanel(new GridBagLayout());
|
buttonsPanel.setOpaque(false);
|
GridBagConstraints gbc = new GridBagConstraints();
|
gbc.fill = GridBagConstraints.HORIZONTAL;
|
gbc.gridwidth = 4;
|
gbc.insets = UIFactory.getEmptyInsets();
|
gbc.insets.left = UIFactory.getCurrentStepPanelInsets().left;
|
buttonsPanel.add(UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
|
null, UIFactory.TextStyle.NO_STYLE), gbc);
|
gbc.weightx = 1.0;
|
gbc.gridwidth--;
|
gbc.insets.left = 0;
|
buttonsPanel.add(Box.createHorizontalGlue(), gbc);
|
gbc.gridwidth = GridBagConstraints.RELATIVE;
|
gbc.fill = GridBagConstraints.NONE;
|
gbc.weightx = 0.0;
|
okButton =
|
UIFactory.makeJButton(INFO_OK_BUTTON_LABEL.get(),
|
INFO_SECURITY_OPTIONS_OK_BUTTON_TOOLTIP.get());
|
buttonsPanel.add(okButton, gbc);
|
okButton.addActionListener(new ActionListener()
|
{
|
@Override
|
public void actionPerformed(ActionEvent ev)
|
{
|
okClicked();
|
}
|
});
|
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
gbc.insets.left = UIFactory.HORIZONTAL_INSET_BETWEEN_BUTTONS;
|
cancelButton =
|
UIFactory.makeJButton(INFO_CANCEL_BUTTON_LABEL.get(),
|
INFO_SECURITY_OPTIONS_CANCEL_BUTTON_TOOLTIP.get());
|
buttonsPanel.add(cancelButton, gbc);
|
cancelButton.addActionListener(new ActionListener()
|
{
|
@Override
|
public void actionPerformed(ActionEvent ev)
|
{
|
cancelClicked();
|
}
|
});
|
|
return buttonsPanel;
|
}
|
|
/** Method called when user clicks on cancel. */
|
private void cancelClicked()
|
{
|
isCanceled = true;
|
dispose();
|
}
|
|
/** Method called when user clicks on OK. */
|
private void okClicked()
|
{
|
BackgroundTask<ArrayList<LocalizableMessage>> worker =
|
new BackgroundTask<ArrayList<LocalizableMessage>>()
|
{
|
@Override
|
public ArrayList<LocalizableMessage> processBackgroundTask()
|
{
|
ArrayList<LocalizableMessage> errorMsgs = new ArrayList<>();
|
errorMsgs.addAll(checkPort());
|
errorMsgs.addAll(checkKeystore());
|
return errorMsgs;
|
}
|
|
@Override
|
public void backgroundTaskCompleted(ArrayList<LocalizableMessage> returnValue,
|
Throwable throwable)
|
{
|
if (throwable != null)
|
{
|
// Bug
|
throwable.printStackTrace();
|
displayError(
|
getThrowableMsg(INFO_BUG_MSG.get(), throwable),
|
INFO_ERROR_TITLE.get());
|
cancelButton.setEnabled(true);
|
okButton.setEnabled(true);
|
}
|
else
|
{
|
cancelButton.setEnabled(true);
|
okButton.setEnabled(true);
|
|
if (!returnValue.isEmpty())
|
{
|
displayError(Utils.getMessageFromCollection(returnValue, "\n"),
|
INFO_ERROR_TITLE.get());
|
}
|
else if (rbUseExistingCertificate.isSelected()
|
&& (cbEnableSSL.isSelected() || cbEnableStartTLS.isSelected()))
|
{
|
if (!certificateHasAlias)
|
{
|
selectedAlias = null;
|
isCanceled = false;
|
dispose();
|
}
|
else if (aliases.length > 1)
|
{
|
if (aliasDlg == null)
|
{
|
aliasDlg = new SelectAliasDialog(SecurityOptionsDialog.this);
|
}
|
aliasDlg.display(aliases);
|
|
if (!aliasDlg.isCanceled())
|
{
|
selectedAlias = aliasDlg.getSelectedAlias();
|
isCanceled = false;
|
dispose();
|
}
|
}
|
else
|
{
|
selectedAlias = aliases[0];
|
isCanceled = false;
|
dispose();
|
}
|
}
|
else
|
{
|
isCanceled = false;
|
dispose();
|
}
|
}
|
}
|
};
|
cancelButton.setEnabled(false);
|
okButton.setEnabled(false);
|
worker.startBackgroundTask();
|
}
|
|
/**
|
* Displays an error message dialog.
|
*
|
* @param msg
|
* the error message.
|
* @param title
|
* the title for the dialog.
|
*/
|
private void displayError(LocalizableMessage msg, LocalizableMessage title)
|
{
|
Utilities.displayError(this, msg, title);
|
toFront();
|
}
|
|
/** Updates the widgets on the dialog with the contents of the securityOptions object. */
|
private void updateContents()
|
{
|
cbEnableSSL.setSelected(securityOptions.getEnableSSL());
|
cbEnableStartTLS.setSelected(securityOptions.getEnableStartTLS());
|
if (securityOptions.getEnableSSL())
|
{
|
int port = securityOptions.getSslPort();
|
if (port > 0)
|
{
|
tfPort.setText(String.valueOf(port));
|
}
|
}
|
|
switch (securityOptions.getCertificateType())
|
{
|
case NO_CERTIFICATE:
|
// Nothing else to do
|
break;
|
|
case SELF_SIGNED_CERTIFICATE:
|
rbUseSelfSignedCertificate.setSelected(true);
|
break;
|
|
case JKS:
|
rbUseExistingCertificate.setSelected(true);
|
rbJKS.setSelected(true);
|
tfKeystorePath.setText(securityOptions.getKeystorePath());
|
tfKeystorePwd.setText(securityOptions.getKeystorePassword());
|
break;
|
|
case JCEKS:
|
rbUseExistingCertificate.setSelected(true);
|
rbJCEKS.setSelected(true);
|
tfKeystorePath.setText(securityOptions.getKeystorePath());
|
tfKeystorePwd.setText(securityOptions.getKeystorePassword());
|
break;
|
|
case PKCS11:
|
rbUseExistingCertificate.setSelected(true);
|
rbPKCS11.setSelected(true);
|
tfKeystorePwd.setText(securityOptions.getKeystorePassword());
|
break;
|
|
case PKCS12:
|
rbUseExistingCertificate.setSelected(true);
|
rbPKCS12.setSelected(true);
|
tfKeystorePath.setText(securityOptions.getKeystorePath());
|
tfKeystorePwd.setText(securityOptions.getKeystorePassword());
|
break;
|
|
default:
|
throw new IllegalStateException("Unknown certificate type.");
|
}
|
|
updateEnablingState();
|
}
|
|
/**
|
* Enables/disables and makes visible/invisible the objects according to what
|
* the user selected.
|
*/
|
private void updateEnablingState()
|
{
|
boolean enableSSL = cbEnableSSL.isSelected();
|
boolean enableStartTLS = cbEnableStartTLS.isSelected();
|
|
boolean useSSL = enableSSL || enableStartTLS;
|
|
if (useSSL && !rbUseSelfSignedCertificate.isSelected() &&
|
!rbUseExistingCertificate.isSelected())
|
{
|
rbUseSelfSignedCertificate.setSelected(true);
|
}
|
|
if (useSSL && rbUseExistingCertificate.isSelected() &&
|
!rbJKS.isSelected() && !rbJCEKS.isSelected() &&
|
!rbPKCS11.isSelected() && !rbPKCS12.isSelected())
|
{
|
rbJKS.setSelected(true);
|
}
|
tfPort.setEnabled(enableSSL);
|
|
rbUseSelfSignedCertificate.setEnabled(useSSL);
|
|
rbUseExistingCertificate.setEnabled(useSSL);
|
lKeystoreType.setEnabled(
|
rbUseExistingCertificate.isSelected() && useSSL);
|
rbJKS.setEnabled(rbUseExistingCertificate.isSelected() && useSSL);
|
rbJCEKS.setEnabled(rbUseExistingCertificate.isSelected() && useSSL);
|
rbPKCS11.setEnabled(rbUseExistingCertificate.isSelected() && useSSL);
|
rbPKCS12.setEnabled(rbUseExistingCertificate.isSelected() && useSSL);
|
|
lKeystorePath.setEnabled(
|
rbUseExistingCertificate.isSelected() && useSSL);
|
tfKeystorePath.setEnabled(
|
rbUseExistingCertificate.isSelected() && useSSL);
|
browseButton.setEnabled(rbUseExistingCertificate.isSelected() && useSSL);
|
lKeystorePwd.setEnabled(
|
rbUseExistingCertificate.isSelected() && useSSL);
|
tfKeystorePwd.setEnabled(
|
rbUseExistingCertificate.isSelected() && useSSL);
|
|
lKeystorePath.setVisible(!rbPKCS11.isSelected());
|
tfKeystorePath.setVisible(!rbPKCS11.isSelected());
|
browseButton.setVisible(!rbPKCS11.isSelected());
|
}
|
|
/**
|
* Returns the port help message that we display when we cannot use the
|
* default port (636).
|
* @return the port help message that we display when we cannot use the
|
* default port (636).
|
*/
|
private LocalizableMessage getPortHelpMessage()
|
{
|
LocalizableMessage s = LocalizableMessage.EMPTY;
|
if (securityOptions.getSslPort() != DEFAULT_PORT)
|
{
|
s = INFO_CANNOT_USE_DEFAULT_SECURE_PORT.get();
|
}
|
return s;
|
}
|
|
/**
|
* Checks the port.
|
* @return the error messages found while checking the port.
|
*/
|
private ArrayList<LocalizableMessage> checkPort()
|
{
|
ArrayList<LocalizableMessage> errorMsgs = new ArrayList<>();
|
|
if (cbEnableSSL.isSelected())
|
{
|
/* Check the port. */
|
String sPort = tfPort.getText();
|
int port = -1;
|
try
|
{
|
port = Integer.parseInt(sPort);
|
if (port < Installer.MIN_PORT_VALUE
|
|| port > Installer.MAX_PORT_VALUE)
|
{
|
errorMsgs.add(INFO_INVALID_SECURE_PORT_VALUE_RANGE.get(
|
Installer.MIN_PORT_VALUE, Installer.MAX_PORT_VALUE));
|
}
|
else if (!Utils.canUseAsPort(port))
|
{
|
if (Utils.isPrivilegedPort(port))
|
{
|
errorMsgs.add(INFO_CANNOT_BIND_PRIVILEDGED_PORT.get(port));
|
}
|
else
|
{
|
errorMsgs.add(INFO_CANNOT_BIND_PORT.get(port));
|
}
|
}
|
}
|
catch (NumberFormatException nfe)
|
{
|
errorMsgs.add(INFO_INVALID_SECURE_PORT_VALUE_RANGE.get(
|
Installer.MIN_PORT_VALUE, Installer.MAX_PORT_VALUE));
|
}
|
}
|
setValidLater(cbEnableSSL, errorMsgs.isEmpty());
|
return errorMsgs;
|
}
|
|
/**
|
* Checks the existing keystore parameters.
|
* @return the error messages found while checking existing keystore
|
* parameters.
|
*/
|
private ArrayList<LocalizableMessage> checkKeystore()
|
{
|
ArrayList<LocalizableMessage> errorMsgs = new ArrayList<>();
|
|
boolean pathValid = true;
|
boolean pwdValid = true;
|
|
if (rbUseExistingCertificate.isSelected() &&
|
(cbEnableSSL.isSelected() || cbEnableStartTLS.isSelected()))
|
{
|
String path = tfKeystorePath.getText();
|
if (rbJKS.isSelected() || rbJCEKS.isSelected() || rbPKCS12.isSelected())
|
{
|
/* Check the path */
|
if (path == null || path.length() == 0)
|
{
|
errorMsgs.add(INFO_KEYSTORE_PATH_NOT_PROVIDED.get());
|
}
|
else
|
{
|
File f = new File(path);
|
if (!f.exists())
|
{
|
errorMsgs.add(INFO_KEYSTORE_PATH_DOES_NOT_EXIST.get());
|
}
|
else if (!f.isFile())
|
{
|
errorMsgs.add(INFO_KEYSTORE_PATH_NOT_A_FILE.get());
|
}
|
}
|
|
pathValid = errorMsgs.isEmpty();
|
}
|
|
String pwd = String.valueOf(tfKeystorePwd.getPassword());
|
if (pathValid)
|
{
|
try
|
{
|
CertificateManager certManager;
|
if (rbJKS.isSelected())
|
{
|
certManager = new CertificateManager(
|
path,
|
CertificateManager.KEY_STORE_TYPE_JKS,
|
pwd);
|
}
|
else if (rbJCEKS.isSelected())
|
{
|
certManager = new CertificateManager(
|
path,
|
CertificateManager.KEY_STORE_TYPE_JCEKS,
|
pwd);
|
}
|
else if (rbPKCS12.isSelected())
|
{
|
certManager = new CertificateManager(
|
path,
|
CertificateManager.KEY_STORE_TYPE_PKCS12,
|
pwd);
|
}
|
else if (rbPKCS11.isSelected())
|
{
|
certManager = new CertificateManager(
|
CertificateManager.KEY_STORE_PATH_PKCS11,
|
CertificateManager.KEY_STORE_TYPE_PKCS11,
|
pwd);
|
}
|
else
|
{
|
throw new IllegalStateException("No keystore type selected.");
|
}
|
aliases = certManager.getCertificateAliases();
|
if (aliases == null || aliases.length == 0)
|
{
|
// Could not retrieve any certificate
|
if (rbPKCS11.isSelected())
|
{
|
errorMsgs.add(INFO_PKCS11_KEYSTORE_DOES_NOT_EXIST.get());
|
}
|
else
|
{
|
if (rbJKS.isSelected())
|
{
|
errorMsgs.add(INFO_JKS_KEYSTORE_DOES_NOT_EXIST.get());
|
}
|
else if (rbJCEKS.isSelected())
|
{
|
errorMsgs.add(INFO_JCEKS_KEYSTORE_DOES_NOT_EXIST.get());
|
}
|
else
|
{
|
errorMsgs.add(INFO_PKCS12_KEYSTORE_DOES_NOT_EXIST.get());
|
}
|
pathValid = false;
|
}
|
}
|
else
|
{
|
certificateHasAlias = certManager.hasRealAliases();
|
}
|
}
|
catch (KeyStoreException ke)
|
{
|
// issue OPENDJ-18, related to JDK bug
|
if (StaticUtils
|
.stackTraceContainsCause(ke, ArithmeticException.class))
|
{
|
errorMsgs.add(INFO_ERROR_ACCESSING_KEYSTORE_JDK_BUG.get());
|
}
|
else
|
{
|
pwdValid = false;
|
if (!rbPKCS11.isSelected())
|
{
|
pathValid = false;
|
}
|
// Could not access to the keystore: because the password is
|
// no good, because the provided file is not a valid keystore, etc.
|
if (rbPKCS11.isSelected())
|
{
|
errorMsgs.add(INFO_ERROR_ACCESSING_PKCS11_KEYSTORE.get());
|
}
|
else
|
{
|
if (rbJKS.isSelected())
|
{
|
errorMsgs.add(INFO_ERROR_ACCESSING_JKS_KEYSTORE.get());
|
}
|
else if (rbJCEKS.isSelected())
|
{
|
errorMsgs.add(INFO_ERROR_ACCESSING_JCEKS_KEYSTORE.get());
|
}
|
else
|
{
|
errorMsgs.add(INFO_ERROR_ACCESSING_PKCS12_KEYSTORE.get());
|
}
|
pathValid = false;
|
}
|
}
|
}
|
}
|
}
|
|
setValidLater(lKeystorePath, pathValid);
|
setValidLater(lKeystorePwd, pwdValid);
|
|
return errorMsgs;
|
}
|
|
/**
|
* Method that updates the text style of a provided component by calling
|
* SwingUtilities.invokeLater. This method is aimed to be called outside
|
* the event thread (calling it from the event thread will also work though).
|
* @param comp the component to be updated.
|
* @param valid whether to use a TextStyle to mark the component as valid
|
* or as invalid.
|
*/
|
private void setValidLater(final JComponent comp, final boolean valid)
|
{
|
SwingUtilities.invokeLater(new Runnable()
|
{
|
@Override
|
public void run()
|
{
|
UIFactory.setTextStyle(comp,
|
valid ? UIFactory.TextStyle.SECONDARY_FIELD_VALID :
|
UIFactory.TextStyle.SECONDARY_FIELD_INVALID);
|
}
|
});
|
}
|
|
/**
|
* Method written for testing purposes.
|
* @param args the arguments to be passed to the test program.
|
*/
|
public static void main(String[] args)
|
{
|
try
|
{
|
// UIFactory.initialize();
|
SecurityOptionsDialog dlg = new SecurityOptionsDialog(new JFrame(),
|
SecurityOptions.createNoCertificateOptions());
|
dlg.pack();
|
dlg.setVisible(true);
|
} catch (Exception ex)
|
{
|
ex.printStackTrace();
|
}
|
}
|
}
|