opends/src/ads/org/opends/admin/ads/util/ApplicationTrustManager.java
@@ -369,11 +369,13 @@ { LdapName dn = new LdapName(chain[0].getSubjectX500Principal().getName()); Rdn rdn = dn.getRdn(0); Rdn rdn = dn.getRdn(dn.getRdns().size() - 1); String value = rdn.getValue().toString(); matches = host.equalsIgnoreCase(value); if (!matches) { LOG.log(Level.WARNING, "Subject DN RDN value is: "+value+ " and does not match host value: "+host); // Try with the accepted hosts names for (int i =0; i<acceptedHosts.size() && !matches; i++) { opends/src/guitools/org/opends/guitools/statuspanel/StatusPanelController.java
@@ -34,6 +34,8 @@ import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.SwingUtilities; @@ -52,6 +54,7 @@ import org.opends.quicksetup.ui.Utilities; import org.opends.quicksetup.util.BackgroundTask; import org.opends.quicksetup.util.HtmlProgressMessageFormatter; import org.opends.quicksetup.util.UIKeyStore; import org.opends.quicksetup.util.Utils; import org.opends.messages.Message; @@ -100,6 +103,9 @@ private static final ConnectionProtocolPolicy CONNECTION_POLICY = ConnectionProtocolPolicy.USE_MOST_SECURE_AVAILABLE; private static final Logger LOG = Logger.getLogger( StatusPanelController.class.getName()); /** * This method creates the control panel dialogs and to check the current * install status. This method must be called outside the event thread because @@ -119,7 +125,16 @@ { DirectoryServer.bootstrapClient(); initLookAndFeel(); trustManager = new ApplicationTrustManager(null); try { trustManager = new ApplicationTrustManager(UIKeyStore.getInstance()); } catch (Throwable t) { LOG.log(Level.WARNING, "Error retrieving UI key store: "+t, t); trustManager = new ApplicationTrustManager(null); } /* Call this methods to create the dialogs (the control panel dialog * is generated when we call getLoginDialog()). */ getLoginDialog(); opends/src/guitools/org/opends/guitools/statuspanel/ui/LoginDialog.java
@@ -65,6 +65,7 @@ import org.opends.quicksetup.ui.UIFactory; import org.opends.quicksetup.ui.Utilities; import org.opends.quicksetup.util.BackgroundTask; import org.opends.quicksetup.util.UIKeyStore; import org.opends.quicksetup.util.Utils; import org.opends.messages.Message; @@ -759,7 +760,8 @@ CertificateDialog dlg = new CertificateDialog(parent, ce); dlg.pack(); dlg.setVisible(true); if (dlg.isAccepted()) if (dlg.getUserAnswer() != CertificateDialog.ReturnType.NOT_ACCEPTED) { X509Certificate[] chain = ce.getChain(); String authType = ce.getAuthType(); @@ -797,6 +799,22 @@ } } } if (dlg.getUserAnswer() == CertificateDialog.ReturnType.ACCEPTED_PERMANENTLY) { X509Certificate[] chain = ce.getChain(); if (chain != null) { try { UIKeyStore.acceptCertificate(chain); } catch (Throwable t) { LOG.log(Level.WARNING, "Error accepting certificate: "+t, t); } } } } /** opends/src/guitools/org/opends/guitools/uninstaller/Uninstaller.java
@@ -44,9 +44,11 @@ import org.opends.guitools.uninstaller.ui.ConfirmUninstallPanel; import org.opends.guitools.uninstaller.ui.LoginDialog; import org.opends.quicksetup.ui.*; import static org.opends.quicksetup.util.Utils.*; import org.opends.quicksetup.util.BackgroundTask; import org.opends.quicksetup.util.ServerController; import org.opends.quicksetup.util.UIKeyStore; import org.opends.server.admin.AttributeTypePropertyDefinition; import org.opends.server.admin.ClassLoaderProvider; import org.opends.server.admin.ClassPropertyDefinition; @@ -150,7 +152,9 @@ * {@inheritDoc} */ public UserData createUserData() { return new UninstallUserData(); UninstallUserData data = new UninstallUserData(); data.setTrustManager(super.getTrustManager()); return data; } /** @@ -1554,7 +1558,7 @@ new CertificateDialog(qs.getDialog().getFrame(), ce); dlg.pack(); dlg.setVisible(true); if (dlg.isAccepted()) if (dlg.getUserAnswer() != CertificateDialog.ReturnType.NOT_ACCEPTED) { X509Certificate[] chain = ce.getChain(); String authType = ce.getAuthType(); @@ -1617,6 +1621,22 @@ } } } if (dlg.getUserAnswer() == CertificateDialog.ReturnType.ACCEPTED_PERMANENTLY) { X509Certificate[] chain = ce.getChain(); if (chain != null) { try { UIKeyStore.acceptCertificate(chain); } catch (Throwable t) { LOG.log(Level.WARNING, "Error accepting certificate: "+t, t); } } } } /** opends/src/guitools/org/opends/guitools/uninstaller/ui/LoginDialog.java
@@ -65,6 +65,7 @@ import org.opends.quicksetup.ui.UIFactory; import org.opends.quicksetup.ui.Utilities; import org.opends.quicksetup.util.BackgroundTask; import org.opends.quicksetup.util.UIKeyStore; import org.opends.quicksetup.util.Utils; import org.opends.messages.Message; @@ -660,7 +661,7 @@ CertificateDialog dlg = new CertificateDialog(parent, ce); dlg.pack(); dlg.setVisible(true); if (dlg.isAccepted()) if (dlg.getUserAnswer() != CertificateDialog.ReturnType.NOT_ACCEPTED) { X509Certificate[] chain = ce.getChain(); String authType = ce.getAuthType(); @@ -698,6 +699,22 @@ } } } if (dlg.getUserAnswer() == CertificateDialog.ReturnType.ACCEPTED_PERMANENTLY) { X509Certificate[] chain = ce.getChain(); if (chain != null) { try { UIKeyStore.acceptCertificate(chain); } catch (Throwable t) { LOG.log(Level.WARNING, "Error accepting certificate: "+t, t); } } } } /** opends/src/messages/messages/quicksetup.properties
@@ -99,10 +99,15 @@ INFO_CERTIFICATE_CHAIN_COMBO_TOOLTIP=To view the details of a given \ certificate select it. INFO_CERTIFICATE_CHAIN_LABEL=Certificate Chain: INFO_CERTIFICATE_DIALOG_CANCEL_BUTTON_TOOLTIP=Close this dialog and do not \ accept the certificate. INFO_CERTIFICATE_DIALOG_OK_BUTTON_TOOLTIP=Close this dialog and accept the \ certificate. INFO_CERTIFICATE_DIALOG_DO_NOT_ACCEPT_BUTTON_LABEL=Do not Accept INFO_CERTIFICATE_DIALOG_ACCEPT_FOR_SESSION_BUTTON_LABEL=Accept for this Session INFO_CERTIFICATE_DIALOG_ACCEPT_PERMANENTLY_BUTTON_LABEL=Accept permanently INFO_CERTIFICATE_DIALOG_DO_NOT_ACCEPT_BUTTON_TOOLTIP=Close this dialog and do \ not accept the certificate. INFO_CERTIFICATE_DIALOG_ACCEPT_FOR_SESSION_BUTTON_TOOLTIP=Close this dialog \ and accept the certificate only for this session. INFO_CERTIFICATE_DIALOG_ACCEPT_PERMANENTLY_BUTTON_TOOLTIP=Close this dialog \ and accept the certificate permanently. INFO_CERTIFICATE_DIALOG_TITLE=Certificate Not Trusted INFO_CERTIFICATE_EXCEPTION=You must accept the certificate presented by \ %s:%s. opends/src/quicksetup/org/opends/quicksetup/Application.java
@@ -39,6 +39,7 @@ import org.opends.quicksetup.event.ProgressUpdateListener; import org.opends.quicksetup.util.ServerController; import org.opends.quicksetup.util.ProgressMessageFormatter; import org.opends.quicksetup.util.UIKeyStore; import org.opends.quicksetup.ui.GuiApplication; import org.opends.quicksetup.util.Utils; @@ -562,7 +563,22 @@ { if (trustManager == null) { trustManager = new ApplicationTrustManager(null); if (!Utils.isCli()) { try { trustManager = new ApplicationTrustManager(UIKeyStore.getInstance()); } catch (Throwable t) { LOG.log(Level.WARNING, "Error retrieving UI key store: "+t, t); trustManager = new ApplicationTrustManager(null); } } else { trustManager = new ApplicationTrustManager(null); } } return trustManager; } opends/src/quicksetup/org/opends/quicksetup/ui/CertificateDialog.java
@@ -76,11 +76,31 @@ */ public class CertificateDialog extends JDialog implements HyperlinkListener { /** * The enumeration that defines the different answers that the user can * provide for this dialog. */ public enum ReturnType { /** * The user did not accept the certificate. */ NOT_ACCEPTED, /** * The user accepted the certificate only for this session. */ ACCEPTED_FOR_SESSION, /** * The user accepted the certificate permanently. */ ACCEPTED_PERMANENTLY }; private static final long serialVersionUID = -8989965057591475064L; private boolean isAccepted; private ReturnType returnValue = ReturnType.NOT_ACCEPTED; private UserDataCertificateException ce; private JButton cancelButton; private JButton okButton; private JButton doNotAcceptButton; private JButton acceptSessionButton; private JButton acceptPermanentlyButton; private JComponent certificateDetails; private JEditorPane explanationPane; private boolean detailsAlreadyClicked; @@ -107,7 +127,7 @@ pack(); if (getPreferredSize().width > parent.getWidth()) { setPreferredSize(new Dimension(Math.max(parent.getWidth() - 20, 400), setPreferredSize(new Dimension(Math.max(parent.getWidth() - 20, 600), getPreferredSize().height)); } pack(); @@ -115,13 +135,13 @@ int minHeight = (int) getPreferredSize().getHeight(); addComponentListener(new MinimumSizeComponentListener(this, minWidth, minHeight)); getRootPane().setDefaultButton(cancelButton); getRootPane().setDefaultButton(doNotAcceptButton); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { cancelClicked(); doNotAccept(); } }); setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); @@ -131,12 +151,12 @@ /** * Wheter the user accepted the certificate or not. * @return <CODE>true</CODE> ir the user accepted the certificate and * <CODE>false</CODE> otherwise. * @return the ReturnType object defining what the user chose to do with the * certificate. */ public boolean isAccepted() public ReturnType getUserAnswer() { return isAccepted; return returnValue; } /** @@ -313,8 +333,10 @@ } /** * Creates and returns the buttons OK/CANCEL sub panel. * @return the buttons OK/CANCEL sub panel. * Creates and returns the buttons DO NOT ACCEPT/ACCEPT FOR THIS SESSION/ * ACCEPT PERMANENTLY sub panel. * @return the buttons DO NOT ACCEPT/ACCEPT FOR THIS SESSION/ACCEPT * PERMANENTLY sub panel. */ private Component createButtonsPanel() { @@ -331,32 +353,48 @@ gbc.gridwidth--; gbc.insets.left = 0; buttonsPanel.add(Box.createHorizontalGlue(), gbc); gbc.gridwidth = GridBagConstraints.RELATIVE; gbc.gridwidth = 3; gbc.fill = GridBagConstraints.NONE; gbc.weightx = 0.0; okButton = UIFactory.makeJButton(INFO_OK_BUTTON_LABEL.get(), INFO_CERTIFICATE_DIALOG_OK_BUTTON_TOOLTIP.get()); buttonsPanel.add(okButton, gbc); okButton.addActionListener(new ActionListener() acceptSessionButton = UIFactory.makeJButton( INFO_CERTIFICATE_DIALOG_ACCEPT_FOR_SESSION_BUTTON_LABEL.get(), INFO_CERTIFICATE_DIALOG_ACCEPT_FOR_SESSION_BUTTON_TOOLTIP.get()); buttonsPanel.add(acceptSessionButton, gbc); acceptSessionButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ev) { okClicked(); acceptForSession(); } }); gbc.gridwidth = GridBagConstraints.RELATIVE; gbc.insets.left = UIFactory.HORIZONTAL_INSET_BETWEEN_BUTTONS; acceptPermanentlyButton = UIFactory.makeJButton( INFO_CERTIFICATE_DIALOG_ACCEPT_PERMANENTLY_BUTTON_LABEL.get(), INFO_CERTIFICATE_DIALOG_ACCEPT_PERMANENTLY_BUTTON_TOOLTIP.get()); buttonsPanel.add(acceptPermanentlyButton, gbc); acceptPermanentlyButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ev) { acceptPermanently(); } }); gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.insets.left = UIFactory.HORIZONTAL_INSET_BETWEEN_BUTTONS; cancelButton = UIFactory.makeJButton(INFO_CANCEL_BUTTON_LABEL.get(), INFO_CERTIFICATE_DIALOG_CANCEL_BUTTON_TOOLTIP.get()); buttonsPanel.add(cancelButton, gbc); cancelButton.addActionListener(new ActionListener() doNotAcceptButton = UIFactory.makeJButton( INFO_CERTIFICATE_DIALOG_DO_NOT_ACCEPT_BUTTON_LABEL.get(), INFO_CERTIFICATE_DIALOG_DO_NOT_ACCEPT_BUTTON_TOOLTIP.get()); buttonsPanel.add(doNotAcceptButton, gbc); doNotAcceptButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ev) { cancelClicked(); doNotAccept(); } }); @@ -739,9 +777,9 @@ * Method called when user clicks on ok. * */ private void okClicked() private void acceptForSession() { isAccepted = true; returnValue = ReturnType.ACCEPTED_FOR_SESSION; dispose(); } @@ -749,9 +787,19 @@ * Method called when user clicks on cancel. * */ private void cancelClicked() private void doNotAccept() { isAccepted = false; returnValue = ReturnType.NOT_ACCEPTED; dispose(); } /** * Method called when user clicks on ok. * */ private void acceptPermanently() { returnValue = ReturnType.ACCEPTED_PERMANENTLY; dispose(); } opends/src/quicksetup/org/opends/quicksetup/ui/GuiApplication.java
@@ -30,6 +30,7 @@ import org.opends.quicksetup.*; import org.opends.quicksetup.util.ServerController; import org.opends.quicksetup.util.InProcessServerController; import org.opends.quicksetup.util.UIKeyStore; import org.opends.quicksetup.util.Utils; import org.opends.quicksetup.UserInteraction; import org.opends.quicksetup.webstart.WebStartDownloader; @@ -435,8 +436,11 @@ * when trying to connect in secure mode. * @param ce the UserDataCertificateException that contains the information to * be used. * @param acceptPermanently whether the certificate must be accepted * permanently or not. */ protected void acceptCertificateForException(UserDataCertificateException ce) protected void acceptCertificateForException(UserDataCertificateException ce, boolean acceptPermanently) { X509Certificate[] chain = ce.getChain(); String authType = ce.getAuthType(); @@ -465,6 +469,20 @@ "The host is null for the UserDataCertificateException"); } } if (acceptPermanently) { if (chain != null) { try { UIKeyStore.acceptCertificate(chain); } catch (Throwable t) { LOG.log(Level.WARNING, "Error accepting certificate: "+t, t); } } } } /** opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetup.java
@@ -595,27 +595,6 @@ } /** * Displays a dialog asking the user to accept a certificate. * * @param ce * the certificate exception that occurred. * @return <CODE>true</CODE> if the user confirms the message, or * <CODE>false</CODE> if not. */ private boolean askToAcceptCertificate(UserDataCertificateException ce) { boolean accept = false; CertificateDialog dlg = new CertificateDialog(getDialog().getFrame(), ce); dlg.pack(); dlg.setVisible(true); if (dlg.isAccepted()) { accept = true; } return accept; } /** * Gets the string value for a given field name. * * @param fieldName @@ -756,12 +735,18 @@ { final UserDataCertificateException ce = (UserDataCertificateException)ude; if (askToAcceptCertificate(ce)) CertificateDialog dlg = new CertificateDialog(getDialog().getFrame(), ce); dlg.pack(); dlg.setVisible(true); CertificateDialog.ReturnType answer = dlg.getUserAnswer(); if (answer != CertificateDialog.ReturnType.NOT_ACCEPTED) { /* * Retry the click but now with the certificate accepted. */ application.acceptCertificateForException(ce); application.acceptCertificateForException(ce, answer == CertificateDialog.ReturnType.ACCEPTED_PERMANENTLY); application.nextClicked(cStep, QuickSetup.this); BackgroundTask worker = new NextClickedBackgroundTask(cStep); getDialog().workerStarted(); opends/src/quicksetup/org/opends/quicksetup/util/UIKeyStore.java
New file @@ -0,0 +1,172 @@ /* * 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 * trunk/opends/resource/legal-notices/OpenDS.LICENSE * or https://OpenDS.dev.java.net/OpenDS.LICENSE. * 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 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. 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 * * * Portions Copyright 2007 Sun Microsystems, Inc. */ package org.opends.quicksetup.util; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; 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.logging.Level; import java.util.logging.Logger; /** * Class used to get the KeyStore that the graphical utilities use. * */ public class UIKeyStore extends KeyStore { private static KeyStore keyStore = null; private static final Logger LOG = Logger.getLogger( UIKeyStore.class.getName()); /** * This should never be called. */ private UIKeyStore() { super(null, null, null); } /** * Returns the KeyStore to be used by graphical applications. * @return the KeyStore to be used by graphical applications. * @throws FileNotFoundException if the key store could not be found. * @throws IOException if there was a file system access error. * @throws KeyStoreException if there was a problem while reading the key * store. * @throws CertificateException if an error with a certificate occurred. * @throws NoSuchAlgorithmException if the used algorithm is not supported * by the system. */ public static KeyStore getInstance() throws FileNotFoundException, IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException { if (keyStore == null) { keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); String keyStorePath = getKeyStorePath(); File f = new File(keyStorePath); if (!f.exists()) { LOG.log(Level.INFO, "Path "+keyStorePath+ " does not exist"); keyStorePath = null; } else if (f.isDirectory()) { LOG.log(Level.SEVERE, "Path "+keyStorePath+ " is a directory"); keyStorePath = null; } else if (!f.canRead()) { LOG.log(Level.SEVERE, "Path "+keyStorePath+ " is not readable"); keyStorePath = null; } else if (!f.canWrite()) { LOG.log(Level.SEVERE, "Path "+keyStorePath+ " is not writable"); keyStorePath = null; } if (keyStorePath != null) { FileInputStream fos = new FileInputStream(keyStorePath); try { keyStore.load(fos, null); } catch (Throwable t) { LOG.log(Level.SEVERE, "Error reading key store on "+keyStorePath, t); keyStore.load(null, null); } fos.close(); } else { keyStore.load(null, null); } } return keyStore; } /** * Updates the Key Store with the provided certificate chain. * @param chain the certificate chain to be accepted. * @throws FileNotFoundException if the key store could not be found. * @throws IOException if there was a file system access error. * @throws KeyStoreException if there was a problem while reading or writing * to the key store. * @throws CertificateException if an error with a certificate occurred. * @throws NoSuchAlgorithmException if the used algorithm is not supported * by the system. */ public static void acceptCertificate(X509Certificate[] chain) throws FileNotFoundException, IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException { LOG.log(Level.INFO, "Accepting certificate chain."); KeyStore k = getInstance(); for (int i = 0; i < chain.length; i++) { String alias = chain[i].getSubjectDN().getName(); k.setCertificateEntry(alias, chain[i]); } String keyStorePath = getKeyStorePath(); File f = new File(keyStorePath); if (!f.exists()) { Utils.createFile(f); } FileOutputStream fos = new FileOutputStream(getKeyStorePath()); k.store(fos, new char[]{}); if (fos != null) { fos.close(); } } /** * Returns the path where we store the keystore for the graphical * applications. * @return the path where we store the keystore for the graphical * applications. */ private static String getKeyStorePath() { return System.getProperty("user.home") + File.separator + ".opends" + File.separator + "gui-keystore"; } } opends/src/server/org/opends/server/util/cli/LDAPConnectionConsoleInteraction.java
@@ -877,7 +877,7 @@ } } } // We'we got all the information to get the truststore manager // We've got all the information to get the truststore manager try { truststore = KeyStore.getInstance(KeyStore.getDefaultType());