/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
* or http://forgerock.org/license/CDDLv1.0.html.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at legal-notices/CDDLv1_0.txt.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Copyright 2008-2010 Sun Microsystems, Inc.
* Portions Copyright 2013-2015 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()
{
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()
{
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()
{
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()
{
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();
}
}
}