001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2008-2010 Sun Microsystems, Inc. 015 * Portions Copyright 2013-2015 ForgeRock AS. 016 017 */ 018 019package org.opends.quicksetup.installer.ui; 020 021import java.awt.Component; 022import java.awt.GridBagConstraints; 023import java.awt.GridBagLayout; 024import java.awt.Insets; 025import java.awt.event.ActionEvent; 026import java.awt.event.ActionListener; 027import java.awt.event.WindowAdapter; 028import java.awt.event.WindowEvent; 029import java.io.File; 030import java.security.KeyStoreException; 031import java.util.ArrayList; 032import java.util.Arrays; 033 034import javax.swing.Box; 035import javax.swing.ButtonGroup; 036import javax.swing.JButton; 037import javax.swing.JCheckBox; 038import javax.swing.JComponent; 039import javax.swing.JDialog; 040import javax.swing.JFrame; 041import javax.swing.JLabel; 042import javax.swing.JPanel; 043import javax.swing.JPasswordField; 044import javax.swing.JRadioButton; 045import javax.swing.JTextField; 046import javax.swing.SwingUtilities; 047import javax.swing.text.JTextComponent; 048 049import org.opends.quicksetup.SecurityOptions; 050import org.opends.quicksetup.event.BrowseActionListener; 051import org.opends.quicksetup.event.MinimumSizeComponentListener; 052import org.opends.quicksetup.installer.Installer; 053import org.opends.quicksetup.ui.UIFactory; 054import org.opends.quicksetup.ui.Utilities; 055import org.opends.quicksetup.util.BackgroundTask; 056import org.opends.quicksetup.util.Utils; 057import org.opends.server.util.CertificateManager; 058import org.opends.server.util.StaticUtils; 059import org.forgerock.i18n.LocalizableMessage; 060 061import static org.opends.messages.QuickSetupMessages.*; 062import static com.forgerock.opendj.cli.Utils.getThrowableMsg; 063 064/** 065 * This class is a dialog that appears when the user wants to configure 066 * security parameters for the new OpenDS instance. 067 */ 068public class SecurityOptionsDialog extends JDialog 069{ 070 private static final long serialVersionUID = 4083707346899442215L; 071 072 private JCheckBox cbEnableSSL; 073 private JCheckBox cbEnableStartTLS; 074 private JTextField tfPort; 075 private JRadioButton rbUseSelfSignedCertificate; 076 private JRadioButton rbUseExistingCertificate; 077 private JLabel lKeystoreType; 078 private JRadioButton rbPKCS11; 079 private JRadioButton rbJKS; 080 private JRadioButton rbJCEKS; 081 private JRadioButton rbPKCS12; 082 private JLabel lKeystorePath; 083 private JTextField tfKeystorePath; 084 private JButton browseButton; 085 private JLabel lKeystorePwd; 086 private JPasswordField tfKeystorePwd; 087 088 private JButton cancelButton; 089 private JButton okButton; 090 091 private SelectAliasDialog aliasDlg; 092 093 private boolean isCanceled = true; 094 095 private SecurityOptions securityOptions; 096 097 private String[] aliases; 098 private boolean certificateHasAlias; 099 private String selectedAlias; 100 101 private final int DEFAULT_PORT = 636; 102 103 /** 104 * Constructor of the SecurityOptionsDialog. 105 * @param parent the parent frame for this dialog. 106 * @param options the SecurityOptions used to populate this dialog. 107 * @throws IllegalArgumentException if options is null. 108 */ 109 public SecurityOptionsDialog(JFrame parent, SecurityOptions options) 110 throws IllegalArgumentException 111 { 112 super(parent); 113 setTitle(INFO_SECURITY_OPTIONS_DIALOG_TITLE.get().toString()); 114 securityOptions = options; 115 getContentPane().add(createPanel()); 116 pack(); 117 118 updateContents(); 119 120 int minWidth = (int) getPreferredSize().getWidth(); 121 int minHeight = (int) getPreferredSize().getHeight(); 122 addComponentListener(new MinimumSizeComponentListener(this, minWidth, 123 minHeight)); 124 getRootPane().setDefaultButton(okButton); 125 126 addWindowListener(new WindowAdapter() 127 { 128 @Override 129 public void windowClosing(WindowEvent e) 130 { 131 cancelClicked(); 132 } 133 }); 134 setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); 135 136 Utilities.centerOnComponent(this, parent); 137 } 138 139 /** 140 * Returns <CODE>true</CODE> if the user clicked on cancel and 141 * <CODE>false</CODE> otherwise. 142 * @return <CODE>true</CODE> if the user clicked on cancel and 143 * <CODE>false</CODE> otherwise. 144 */ 145 public boolean isCanceled() 146 { 147 return isCanceled; 148 } 149 150 /** 151 * Displays this dialog and populates its contents with the provided 152 * SecurityOptions object. 153 * @param options the SecurityOptions used to populate this dialog. 154 * @throws IllegalArgumentException if options is null. 155 */ 156 public void display(SecurityOptions options) throws IllegalArgumentException 157 { 158 if (options == null) 159 { 160 throw new IllegalArgumentException("options parameter cannot be null."); 161 } 162 UIFactory.setTextStyle(cbEnableSSL, 163 UIFactory.TextStyle.SECONDARY_FIELD_VALID); 164 UIFactory.setTextStyle(lKeystorePath, 165 UIFactory.TextStyle.SECONDARY_FIELD_VALID); 166 UIFactory.setTextStyle(lKeystorePwd, 167 UIFactory.TextStyle.SECONDARY_FIELD_VALID); 168 169 securityOptions = options; 170 updateContents(); 171 172 isCanceled = true; 173 174 setVisible(true); 175 } 176 177 /** 178 * Returns the security options object representing the input of the user 179 * in this panel. 180 * @return the security options object representing the input of the user 181 * in this panel. 182 */ 183 public SecurityOptions getSecurityOptions() 184 { 185 SecurityOptions ops; 186 187 boolean enableSSL = cbEnableSSL.isSelected(); 188 boolean enableStartTLS = cbEnableStartTLS.isSelected(); 189 if (enableSSL || enableStartTLS) 190 { 191 int sslPort = -1; 192 try 193 { 194 sslPort = Integer.parseInt(tfPort.getText()); 195 } 196 catch (Throwable t) 197 { 198 } 199 if (rbUseSelfSignedCertificate.isSelected()) 200 { 201 ops = SecurityOptions.createSelfSignedCertificateOptions( 202 enableSSL, enableStartTLS, sslPort); 203 } 204 else if (rbJKS.isSelected()) 205 { 206 ops = SecurityOptions.createJKSCertificateOptions( 207 tfKeystorePath.getText(), 208 String.valueOf(tfKeystorePwd.getPassword()), enableSSL, 209 enableStartTLS, sslPort, Arrays.asList(selectedAlias)); 210 } 211 else if (rbJCEKS.isSelected()) 212 { 213 ops = SecurityOptions.createJCEKSCertificateOptions( 214 tfKeystorePath.getText(), 215 String.valueOf(tfKeystorePwd.getPassword()), enableSSL, 216 enableStartTLS, sslPort, Arrays.asList(selectedAlias)); 217 } 218 else if (rbPKCS11.isSelected()) 219 { 220 ops = SecurityOptions.createPKCS11CertificateOptions( 221 String.valueOf(tfKeystorePwd.getPassword()), enableSSL, 222 enableStartTLS, sslPort, Arrays.asList(selectedAlias)); 223 } 224 else if (rbPKCS12.isSelected()) 225 { 226 ops = SecurityOptions.createPKCS12CertificateOptions( 227 tfKeystorePath.getText(), 228 String.valueOf(tfKeystorePwd.getPassword()), enableSSL, 229 enableStartTLS, sslPort, Arrays.asList(selectedAlias)); 230 } 231 else 232 { 233 throw new IllegalStateException("No certificate options selected."); 234 } 235 } 236 else 237 { 238 ops = SecurityOptions.createNoCertificateOptions(); 239 } 240 return ops; 241 } 242 243 /** 244 * Creates and returns the panel of the dialog. 245 * @return the panel of the dialog. 246 */ 247 private JPanel createPanel() 248 { 249 GridBagConstraints gbc = new GridBagConstraints(); 250 251 JPanel contentPanel = new JPanel(new GridBagLayout()); 252 contentPanel.setBackground(UIFactory.DEFAULT_BACKGROUND); 253 gbc.fill = GridBagConstraints.BOTH; 254 gbc.gridwidth = GridBagConstraints.REMAINDER; 255 gbc.weightx = 1.0; 256 257 JPanel topPanel = new JPanel(new GridBagLayout()); 258 topPanel.setBorder(UIFactory.DIALOG_PANEL_BORDER); 259 topPanel.setBackground(UIFactory.CURRENT_STEP_PANEL_BACKGROUND); 260 Insets insets = UIFactory.getCurrentStepPanelInsets(); 261 262 gbc.weighty = 0.0; 263 insets.bottom = 0; 264 gbc.insets = insets; 265 topPanel.add(createTitlePanel(), gbc); 266 gbc.insets.top = UIFactory.TOP_INSET_INSTRUCTIONS_SUBPANEL; 267 topPanel.add(createInstructionsPane(), gbc); 268 gbc.insets.top = UIFactory.TOP_INSET_INPUT_SUBPANEL; 269 gbc.insets.bottom = UIFactory.TOP_INSET_INPUT_SUBPANEL; 270 topPanel.add(createInputPanel(), gbc); 271 gbc.weighty = 1.0; 272 gbc.insets = UIFactory.getEmptyInsets(); 273 topPanel.add(Box.createVerticalGlue(), gbc); 274 contentPanel.add(topPanel, gbc); 275 gbc.weighty = 0.0; 276 gbc.insets = UIFactory.getButtonsPanelInsets(); 277 contentPanel.add(createButtonsPanel(), gbc); 278 279 return contentPanel; 280 } 281 282 /** 283 * Creates and returns the title sub panel. 284 * @return the title sub panel. 285 */ 286 private Component createTitlePanel() 287 { 288 JPanel titlePanel = new JPanel(new GridBagLayout()); 289 GridBagConstraints gbc = new GridBagConstraints(); 290 titlePanel.setOpaque(false); 291 gbc.anchor = GridBagConstraints.NORTHWEST; 292 gbc.fill = GridBagConstraints.BOTH; 293 gbc.weightx = 0.0; 294 gbc.gridwidth = GridBagConstraints.RELATIVE; 295 296 LocalizableMessage title = INFO_SECURITY_OPTIONS_TITLE.get(); 297 JLabel l = 298 UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, title, 299 UIFactory.TextStyle.TITLE); 300 l.setOpaque(false); 301 titlePanel.add(l, gbc); 302 303 gbc.gridwidth = GridBagConstraints.RELATIVE; 304 gbc.anchor = GridBagConstraints.NORTHWEST; 305 gbc.weightx = 1.0; 306 gbc.gridwidth = GridBagConstraints.REMAINDER; 307 gbc.insets.left = 0; 308 gbc.weightx = 1.0; 309 gbc.gridwidth = GridBagConstraints.REMAINDER; 310 titlePanel.add(Box.createHorizontalGlue(), gbc); 311 312 return titlePanel; 313 } 314 315 /** 316 * Creates and returns the instructions sub panel. 317 * @return the instructions sub panel. 318 */ 319 private Component createInstructionsPane() 320 { 321 LocalizableMessage instructions = INFO_SECURITY_OPTIONS_INSTRUCTIONS.get(); 322 323 JTextComponent instructionsPane = 324 UIFactory.makeHtmlPane(instructions, UIFactory.INSTRUCTIONS_FONT); 325 instructionsPane.setOpaque(false); 326 instructionsPane.setEditable(false); 327 328 return instructionsPane; 329 } 330 331 /** 332 * Creates and returns the input sub panel: the panel with all the widgets 333 * that are used to define the security options. 334 * @return the input sub panel. 335 */ 336 private Component createInputPanel() 337 { 338 JPanel inputPanel = new JPanel(new GridBagLayout()); 339 inputPanel.setOpaque(false); 340 341 ActionListener l = new ActionListener() 342 { 343 public void actionPerformed(ActionEvent ev) 344 { 345 updateEnablingState(); 346 } 347 }; 348 349 cbEnableSSL = UIFactory.makeJCheckBox(INFO_ENABLE_SSL_LABEL.get(), 350 INFO_ENABLE_SSL_TOOLTIP.get(), UIFactory.TextStyle.PRIMARY_FIELD_VALID); 351 cbEnableSSL.addActionListener(l); 352 String sPort = ""; 353 int port = securityOptions.getSslPort(); 354 if (port > 0) 355 { 356 sPort = String.valueOf(port); 357 } 358 tfPort = UIFactory.makeJTextField(LocalizableMessage.raw(sPort), 359 INFO_SSL_PORT_TEXTFIELD_TOOLTIP.get(), UIFactory.PORT_FIELD_SIZE, 360 UIFactory.TextStyle.TEXTFIELD); 361 cbEnableStartTLS = UIFactory.makeJCheckBox(INFO_ENABLE_STARTTLS_LABEL.get(), 362 INFO_ENABLE_STARTTLS_TOOLTIP.get(), 363 UIFactory.TextStyle.SECONDARY_FIELD_VALID); 364 cbEnableStartTLS.addActionListener(l); 365 rbUseSelfSignedCertificate = UIFactory.makeJRadioButton( 366 INFO_USE_SELF_SIGNED_LABEL.get(), 367 INFO_USE_SELF_SIGNED_TOOLTIP.get(), 368 UIFactory.TextStyle.SECONDARY_FIELD_VALID); 369 rbUseSelfSignedCertificate.addActionListener(l); 370 rbUseExistingCertificate = UIFactory.makeJRadioButton( 371 INFO_USE_EXISTING_CERTIFICATE_LABEL.get(), 372 INFO_USE_EXISTING_CERTIFICATE_TOOLTIP.get(), 373 UIFactory.TextStyle.SECONDARY_FIELD_VALID); 374 rbUseExistingCertificate.addActionListener(l); 375 ButtonGroup group1 = new ButtonGroup(); 376 group1.add(rbUseSelfSignedCertificate); 377 group1.add(rbUseExistingCertificate); 378 379 lKeystoreType = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, 380 INFO_KEYSTORE_TYPE_LABEL.get(), 381 UIFactory.TextStyle.SECONDARY_FIELD_VALID); 382 lKeystoreType.setOpaque(false); 383 rbJKS = UIFactory.makeJRadioButton( 384 INFO_JKS_CERTIFICATE_LABEL.get(), 385 INFO_JKS_CERTIFICATE_TOOLTIP.get(), 386 UIFactory.TextStyle.SECONDARY_FIELD_VALID); 387 rbJKS.addActionListener(l); 388 rbJCEKS = UIFactory.makeJRadioButton( 389 INFO_JCEKS_CERTIFICATE_LABEL.get(), 390 INFO_JCEKS_CERTIFICATE_TOOLTIP.get(), 391 UIFactory.TextStyle.SECONDARY_FIELD_VALID); 392 rbJCEKS.addActionListener(l); 393 rbPKCS11 = UIFactory.makeJRadioButton( 394 INFO_PKCS11_CERTIFICATE_LABEL.get(), 395 INFO_PKCS11_CERTIFICATE_TOOLTIP.get(), 396 UIFactory.TextStyle.SECONDARY_FIELD_VALID); 397 rbPKCS11.addActionListener(l); 398 rbPKCS12 = UIFactory.makeJRadioButton( 399 INFO_PKCS12_CERTIFICATE_LABEL.get(), 400 INFO_PKCS12_CERTIFICATE_TOOLTIP.get(), 401 UIFactory.TextStyle.SECONDARY_FIELD_VALID); 402 rbPKCS12.addActionListener(l); 403 ButtonGroup group2 = new ButtonGroup(); 404 group2.add(rbJKS); 405 group2.add(rbJCEKS); 406 group2.add(rbPKCS11); 407 group2.add(rbPKCS12); 408 lKeystoreType.setLabelFor(rbJKS); 409 410 lKeystorePath = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, 411 INFO_KEYSTORE_PATH_LABEL.get(), 412 UIFactory.TextStyle.SECONDARY_FIELD_VALID); 413 lKeystorePath.setOpaque(false); 414 tfKeystorePath = UIFactory.makeJTextField(LocalizableMessage.EMPTY, 415 INFO_KEYSTORE_PATH_TOOLTIP.get(), 416 UIFactory.HOST_FIELD_SIZE, UIFactory.TextStyle.TEXTFIELD); 417 lKeystorePath.setLabelFor(tfKeystorePath); 418 browseButton = 419 UIFactory.makeJButton(INFO_BROWSE_BUTTON_LABEL.get(), 420 INFO_BROWSE_BUTTON_TOOLTIP.get()); 421 422 BrowseActionListener browseListener = 423 new BrowseActionListener(tfKeystorePath, 424 BrowseActionListener.BrowseType.GENERIC_FILE, 425 this); 426 browseButton.addActionListener(browseListener); 427 428 lKeystorePwd = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, 429 INFO_KEYSTORE_PWD_LABEL.get(), 430 UIFactory.TextStyle.SECONDARY_FIELD_VALID); 431 lKeystorePwd.setOpaque(false); 432 tfKeystorePwd = UIFactory.makeJPasswordField(LocalizableMessage.EMPTY, 433 INFO_KEYSTORE_PWD_TOOLTIP.get(), 434 UIFactory.PASSWORD_FIELD_SIZE, UIFactory.TextStyle.PASSWORD_FIELD); 435 lKeystorePwd.setLabelFor(tfKeystorePwd); 436 437 GridBagConstraints gbc = new GridBagConstraints(); 438 gbc.anchor = GridBagConstraints.WEST; 439 gbc.weightx = 0.0; 440 gbc.gridwidth = GridBagConstraints.RELATIVE; 441 gbc.insets = UIFactory.getEmptyInsets(); 442 gbc.fill = GridBagConstraints.HORIZONTAL; 443 inputPanel.add(UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, 444 INFO_SSL_ACCESS_LABEL.get(), UIFactory.TextStyle.PRIMARY_FIELD_VALID), 445 gbc); 446 447 JPanel auxPanel = new JPanel(new GridBagLayout()); 448 auxPanel.setOpaque(false); 449 gbc.gridwidth = 4; 450 gbc.fill = GridBagConstraints.NONE; 451 auxPanel.add(cbEnableSSL, gbc); 452 gbc.gridwidth--; 453 gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD; 454 auxPanel.add(tfPort, gbc); 455 gbc.gridwidth = GridBagConstraints.RELATIVE; 456 auxPanel.add(UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, 457 getPortHelpMessage(), UIFactory.TextStyle.SECONDARY_FIELD_VALID), gbc); 458 gbc.gridwidth = GridBagConstraints.REMAINDER; 459 gbc.fill = GridBagConstraints.HORIZONTAL; 460 gbc.weightx = 1.0; 461 auxPanel.add(Box.createHorizontalGlue(), gbc); 462 463 gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD; 464 gbc.weightx = 1.0; 465 inputPanel.add(auxPanel, gbc); 466 467 gbc.insets = UIFactory.getEmptyInsets(); 468 gbc.insets.top = UIFactory.TOP_INSET_SECONDARY_FIELD; 469 gbc.gridwidth = GridBagConstraints.RELATIVE; 470 gbc.weightx = 0.0; 471 inputPanel.add(UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, 472 INFO_STARTTLS_ACCESS_LABEL.get(), 473 UIFactory.TextStyle.PRIMARY_FIELD_VALID), 474 gbc); 475 auxPanel = new JPanel(new GridBagLayout()); 476 auxPanel.setOpaque(false); 477 gbc.gridwidth = GridBagConstraints.RELATIVE; 478 gbc.insets = UIFactory.getEmptyInsets(); 479 auxPanel.add(cbEnableStartTLS, gbc); 480 gbc.weightx = 1.0; 481 gbc.gridwidth = GridBagConstraints.REMAINDER; 482 auxPanel.add(Box.createHorizontalGlue(), gbc); 483 gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD; 484 gbc.insets.top = UIFactory.TOP_INSET_SECONDARY_FIELD; 485 inputPanel.add(auxPanel, gbc); 486 487 gbc.insets = UIFactory.getEmptyInsets(); 488 gbc.insets.top = UIFactory.TOP_INSET_SECONDARY_FIELD; 489 gbc.anchor = GridBagConstraints.NORTHWEST; 490 gbc.gridwidth = GridBagConstraints.RELATIVE; 491 gbc.weightx = 0.0; 492 JLabel lCertificate = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, 493 INFO_CERTIFICATE_LABEL.get(), UIFactory.TextStyle.PRIMARY_FIELD_VALID); 494 int additionalInset = Math.abs(lCertificate.getPreferredSize().height - 495 rbUseSelfSignedCertificate.getPreferredSize().height) / 2; 496 gbc.insets.top += additionalInset; 497 inputPanel.add(lCertificate, gbc); 498 auxPanel = new JPanel(new GridBagLayout()); 499 auxPanel.setOpaque(false); 500 gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD; 501 gbc.gridwidth = GridBagConstraints.REMAINDER; 502 gbc.weightx = 1.0; 503 gbc.insets.top = UIFactory.TOP_INSET_SECONDARY_FIELD; 504 inputPanel.add(auxPanel, gbc); 505 506 gbc.insets = UIFactory.getEmptyInsets(); 507 gbc.anchor = GridBagConstraints.WEST; 508 JPanel aux2Panel = new JPanel(new GridBagLayout()); 509 aux2Panel.setOpaque(false); 510 gbc.gridwidth = GridBagConstraints.RELATIVE; 511 aux2Panel.add(rbUseSelfSignedCertificate, gbc); 512 gbc.weightx = 1.0; 513 gbc.gridwidth = GridBagConstraints.REMAINDER; 514 aux2Panel.add(Box.createHorizontalGlue(), gbc); 515 auxPanel.add(aux2Panel, gbc); 516 517 aux2Panel = new JPanel(new GridBagLayout()); 518 aux2Panel.setOpaque(false); 519 gbc.gridwidth = GridBagConstraints.RELATIVE; 520 gbc.insets = UIFactory.getEmptyInsets(); 521 gbc.weightx = 0.0; 522 aux2Panel.add(rbUseExistingCertificate, gbc); 523 gbc.weightx = 1.0; 524 gbc.gridwidth = GridBagConstraints.REMAINDER; 525 aux2Panel.add(Box.createHorizontalGlue(), gbc); 526 gbc.insets.top = UIFactory.TOP_INSET_SECONDARY_FIELD; 527 auxPanel.add(aux2Panel, gbc); 528 529 additionalInset = Math.abs(lKeystoreType.getPreferredSize().height - 530 rbJKS.getPreferredSize().height) / 2; 531 aux2Panel = new JPanel(new GridBagLayout()); 532 aux2Panel.setOpaque(false); 533 gbc.insets.top -= additionalInset; 534 gbc.insets.left = UIFactory.LEFT_INSET_RADIO_SUBORDINATE; 535 auxPanel.add(aux2Panel, gbc); 536 537 gbc.gridwidth = GridBagConstraints.RELATIVE; 538 gbc.insets = UIFactory.getEmptyInsets(); 539 gbc.weightx = 0.0; 540 gbc.anchor = GridBagConstraints.NORTHWEST; 541 gbc.insets.top = additionalInset; 542 aux2Panel.add(lKeystoreType, gbc); 543 gbc.gridwidth = GridBagConstraints.REMAINDER; 544 gbc.insets.top = 0; 545 aux2Panel.add(rbJKS, gbc); 546 547 gbc.insets.top = UIFactory.TOP_INSET_RADIOBUTTON; 548 gbc.gridwidth = GridBagConstraints.RELATIVE; 549 aux2Panel.add(Box.createHorizontalGlue(), gbc); 550 gbc.gridwidth = GridBagConstraints.REMAINDER; 551 aux2Panel.add(rbJCEKS, gbc); 552 gbc.gridwidth = GridBagConstraints.RELATIVE; 553 aux2Panel.add(Box.createHorizontalGlue(), gbc); 554 gbc.gridwidth = GridBagConstraints.REMAINDER; 555 aux2Panel.add(rbPKCS12, gbc); 556 gbc.gridwidth = GridBagConstraints.RELATIVE; 557 aux2Panel.add(Box.createHorizontalGlue(), gbc); 558 gbc.gridwidth = GridBagConstraints.REMAINDER; 559 aux2Panel.add(rbPKCS11, gbc); 560 561 gbc.gridwidth = GridBagConstraints.RELATIVE; 562 gbc.insets.left = 0; 563 gbc.weightx = 0.0; 564 gbc.anchor = GridBagConstraints.WEST; 565 aux2Panel.add(lKeystorePath, gbc); 566 JPanel aux3Panel = new JPanel(new GridBagLayout()); 567 aux3Panel.setOpaque(false); 568 gbc.weightx = 1.0; 569 gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD; 570 gbc.gridwidth = GridBagConstraints.REMAINDER; 571 aux2Panel.add(aux3Panel, gbc); 572 gbc.insets = UIFactory.getEmptyInsets(); 573 gbc.gridwidth = GridBagConstraints.RELATIVE; 574 aux3Panel.add(tfKeystorePath, gbc); 575 gbc.insets.left = UIFactory.LEFT_INSET_BROWSE; 576 gbc.gridwidth = GridBagConstraints.REMAINDER; 577 gbc.weightx = 0.0; 578 aux3Panel.add(browseButton, gbc); 579 580 gbc.insets.left = 0; 581 gbc.insets.top = UIFactory.TOP_INSET_SECONDARY_FIELD; 582 gbc.gridwidth = GridBagConstraints.RELATIVE; 583 gbc.weightx = 0.0; 584 gbc.anchor = GridBagConstraints.WEST; 585 aux2Panel.add(lKeystorePwd, gbc); 586 gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD; 587 gbc.gridwidth = GridBagConstraints.REMAINDER; 588 gbc.fill = GridBagConstraints.NONE; 589 aux2Panel.add(tfKeystorePwd, gbc); 590 591 return inputPanel; 592 } 593 594 /** 595 * Creates and returns the buttons OK/CANCEL sub panel. 596 * @return the buttons OK/CANCEL sub panel. 597 */ 598 private Component createButtonsPanel() 599 { 600 JPanel buttonsPanel = new JPanel(new GridBagLayout()); 601 buttonsPanel.setOpaque(false); 602 GridBagConstraints gbc = new GridBagConstraints(); 603 gbc.fill = GridBagConstraints.HORIZONTAL; 604 gbc.gridwidth = 4; 605 gbc.insets = UIFactory.getEmptyInsets(); 606 gbc.insets.left = UIFactory.getCurrentStepPanelInsets().left; 607 buttonsPanel.add(UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, 608 null, UIFactory.TextStyle.NO_STYLE), gbc); 609 gbc.weightx = 1.0; 610 gbc.gridwidth--; 611 gbc.insets.left = 0; 612 buttonsPanel.add(Box.createHorizontalGlue(), gbc); 613 gbc.gridwidth = GridBagConstraints.RELATIVE; 614 gbc.fill = GridBagConstraints.NONE; 615 gbc.weightx = 0.0; 616 okButton = 617 UIFactory.makeJButton(INFO_OK_BUTTON_LABEL.get(), 618 INFO_SECURITY_OPTIONS_OK_BUTTON_TOOLTIP.get()); 619 buttonsPanel.add(okButton, gbc); 620 okButton.addActionListener(new ActionListener() 621 { 622 public void actionPerformed(ActionEvent ev) 623 { 624 okClicked(); 625 } 626 }); 627 628 gbc.gridwidth = GridBagConstraints.REMAINDER; 629 gbc.insets.left = UIFactory.HORIZONTAL_INSET_BETWEEN_BUTTONS; 630 cancelButton = 631 UIFactory.makeJButton(INFO_CANCEL_BUTTON_LABEL.get(), 632 INFO_SECURITY_OPTIONS_CANCEL_BUTTON_TOOLTIP.get()); 633 buttonsPanel.add(cancelButton, gbc); 634 cancelButton.addActionListener(new ActionListener() 635 { 636 public void actionPerformed(ActionEvent ev) 637 { 638 cancelClicked(); 639 } 640 }); 641 642 return buttonsPanel; 643 } 644 645 /** 646 * Method called when user clicks on cancel. 647 * 648 */ 649 private void cancelClicked() 650 { 651 isCanceled = true; 652 dispose(); 653 } 654 655 /** 656 * Method called when user clicks on OK. 657 * 658 */ 659 private void okClicked() 660 { 661 BackgroundTask<ArrayList<LocalizableMessage>> worker = 662 new BackgroundTask<ArrayList<LocalizableMessage>>() 663 { 664 @Override 665 public ArrayList<LocalizableMessage> processBackgroundTask() 666 { 667 ArrayList<LocalizableMessage> errorMsgs = new ArrayList<>(); 668 errorMsgs.addAll(checkPort()); 669 errorMsgs.addAll(checkKeystore()); 670 return errorMsgs; 671 } 672 673 @Override 674 public void backgroundTaskCompleted(ArrayList<LocalizableMessage> returnValue, 675 Throwable throwable) 676 { 677 if (throwable != null) 678 { 679 // Bug 680 throwable.printStackTrace(); 681 displayError( 682 getThrowableMsg(INFO_BUG_MSG.get(), throwable), 683 INFO_ERROR_TITLE.get()); 684 cancelButton.setEnabled(true); 685 okButton.setEnabled(true); 686 } 687 else 688 { 689 cancelButton.setEnabled(true); 690 okButton.setEnabled(true); 691 692 if (!returnValue.isEmpty()) 693 { 694 displayError(Utils.getMessageFromCollection(returnValue, "\n"), 695 INFO_ERROR_TITLE.get()); 696 } 697 else if (rbUseExistingCertificate.isSelected() 698 && (cbEnableSSL.isSelected() || cbEnableStartTLS.isSelected())) 699 { 700 if (!certificateHasAlias) 701 { 702 selectedAlias = null; 703 isCanceled = false; 704 dispose(); 705 } 706 else if (aliases.length > 1) 707 { 708 if (aliasDlg == null) 709 { 710 aliasDlg = new SelectAliasDialog(SecurityOptionsDialog.this); 711 } 712 aliasDlg.display(aliases); 713 714 if (!aliasDlg.isCanceled()) 715 { 716 selectedAlias = aliasDlg.getSelectedAlias(); 717 isCanceled = false; 718 dispose(); 719 } 720 } 721 else 722 { 723 selectedAlias = aliases[0]; 724 isCanceled = false; 725 dispose(); 726 } 727 } 728 else 729 { 730 isCanceled = false; 731 dispose(); 732 } 733 } 734 } 735 }; 736 cancelButton.setEnabled(false); 737 okButton.setEnabled(false); 738 worker.startBackgroundTask(); 739 } 740 741 /** 742 * Displays an error message dialog. 743 * 744 * @param msg 745 * the error message. 746 * @param title 747 * the title for the dialog. 748 */ 749 private void displayError(LocalizableMessage msg, LocalizableMessage title) 750 { 751 Utilities.displayError(this, msg, title); 752 toFront(); 753 } 754 755 /** 756 * Updates the widgets on the dialog with the contents of the securityOptions 757 * object. 758 * 759 */ 760 private void updateContents() 761 { 762 cbEnableSSL.setSelected(securityOptions.getEnableSSL()); 763 cbEnableStartTLS.setSelected(securityOptions.getEnableStartTLS()); 764 if (securityOptions.getEnableSSL()) 765 { 766 int port = securityOptions.getSslPort(); 767 if (port > 0) 768 { 769 tfPort.setText(String.valueOf(port)); 770 } 771 } 772 773 switch (securityOptions.getCertificateType()) 774 { 775 case NO_CERTIFICATE: 776 // Nothing else to do 777 break; 778 779 case SELF_SIGNED_CERTIFICATE: 780 rbUseSelfSignedCertificate.setSelected(true); 781 break; 782 783 case JKS: 784 rbUseExistingCertificate.setSelected(true); 785 rbJKS.setSelected(true); 786 tfKeystorePath.setText(securityOptions.getKeystorePath()); 787 tfKeystorePwd.setText(securityOptions.getKeystorePassword()); 788 break; 789 790 case JCEKS: 791 rbUseExistingCertificate.setSelected(true); 792 rbJCEKS.setSelected(true); 793 tfKeystorePath.setText(securityOptions.getKeystorePath()); 794 tfKeystorePwd.setText(securityOptions.getKeystorePassword()); 795 break; 796 797 case PKCS11: 798 rbUseExistingCertificate.setSelected(true); 799 rbPKCS11.setSelected(true); 800 tfKeystorePwd.setText(securityOptions.getKeystorePassword()); 801 break; 802 803 case PKCS12: 804 rbUseExistingCertificate.setSelected(true); 805 rbPKCS12.setSelected(true); 806 tfKeystorePath.setText(securityOptions.getKeystorePath()); 807 tfKeystorePwd.setText(securityOptions.getKeystorePassword()); 808 break; 809 810 default: 811 throw new IllegalStateException("Unknown certificate type."); 812 } 813 814 updateEnablingState(); 815 } 816 817 /** 818 * Enables/disables and makes visible/invisible the objects according to what 819 * the user selected. 820 */ 821 private void updateEnablingState() 822 { 823 boolean enableSSL = cbEnableSSL.isSelected(); 824 boolean enableStartTLS = cbEnableStartTLS.isSelected(); 825 826 boolean useSSL = enableSSL || enableStartTLS; 827 828 if (useSSL && !rbUseSelfSignedCertificate.isSelected() && 829 !rbUseExistingCertificate.isSelected()) 830 { 831 rbUseSelfSignedCertificate.setSelected(true); 832 } 833 834 if (useSSL && rbUseExistingCertificate.isSelected() && 835 !rbJKS.isSelected() && !rbJCEKS.isSelected() && 836 !rbPKCS11.isSelected() && !rbPKCS12.isSelected()) 837 { 838 rbJKS.setSelected(true); 839 } 840 tfPort.setEnabled(enableSSL); 841 842 rbUseSelfSignedCertificate.setEnabled(useSSL); 843 844 rbUseExistingCertificate.setEnabled(useSSL); 845 lKeystoreType.setEnabled( 846 rbUseExistingCertificate.isSelected() && useSSL); 847 rbJKS.setEnabled(rbUseExistingCertificate.isSelected() && useSSL); 848 rbJCEKS.setEnabled(rbUseExistingCertificate.isSelected() && useSSL); 849 rbPKCS11.setEnabled(rbUseExistingCertificate.isSelected() && useSSL); 850 rbPKCS12.setEnabled(rbUseExistingCertificate.isSelected() && useSSL); 851 852 lKeystorePath.setEnabled( 853 rbUseExistingCertificate.isSelected() && useSSL); 854 tfKeystorePath.setEnabled( 855 rbUseExistingCertificate.isSelected() && useSSL); 856 browseButton.setEnabled(rbUseExistingCertificate.isSelected() && useSSL); 857 lKeystorePwd.setEnabled( 858 rbUseExistingCertificate.isSelected() && useSSL); 859 tfKeystorePwd.setEnabled( 860 rbUseExistingCertificate.isSelected() && useSSL); 861 862 lKeystorePath.setVisible(!rbPKCS11.isSelected()); 863 tfKeystorePath.setVisible(!rbPKCS11.isSelected()); 864 browseButton.setVisible(!rbPKCS11.isSelected()); 865 } 866 867 /** 868 * Returns the port help message that we display when we cannot use the 869 * default port (636). 870 * @return the port help message that we display when we cannot use the 871 * default port (636). 872 */ 873 private LocalizableMessage getPortHelpMessage() 874 { 875 LocalizableMessage s = LocalizableMessage.EMPTY; 876 if (securityOptions.getSslPort() != DEFAULT_PORT) 877 { 878 s = INFO_CANNOT_USE_DEFAULT_SECURE_PORT.get(); 879 } 880 return s; 881 } 882 883 /** 884 * Checks the port. 885 * @return the error messages found while checking the port. 886 */ 887 private ArrayList<LocalizableMessage> checkPort() 888 { 889 ArrayList<LocalizableMessage> errorMsgs = new ArrayList<>(); 890 891 if (cbEnableSSL.isSelected()) 892 { 893 /* Check the port. */ 894 String sPort = tfPort.getText(); 895 int port = -1; 896 try 897 { 898 port = Integer.parseInt(sPort); 899 if (port < Installer.MIN_PORT_VALUE 900 || port > Installer.MAX_PORT_VALUE) 901 { 902 errorMsgs.add(INFO_INVALID_SECURE_PORT_VALUE_RANGE.get( 903 Installer.MIN_PORT_VALUE, Installer.MAX_PORT_VALUE)); 904 } 905 else if (!Utils.canUseAsPort(port)) 906 { 907 if (Utils.isPrivilegedPort(port)) 908 { 909 errorMsgs.add(INFO_CANNOT_BIND_PRIVILEDGED_PORT.get(port)); 910 } 911 else 912 { 913 errorMsgs.add(INFO_CANNOT_BIND_PORT.get(port)); 914 } 915 } 916 } 917 catch (NumberFormatException nfe) 918 { 919 errorMsgs.add(INFO_INVALID_SECURE_PORT_VALUE_RANGE.get( 920 Installer.MIN_PORT_VALUE, Installer.MAX_PORT_VALUE)); 921 } 922 } 923 setValidLater(cbEnableSSL, errorMsgs.isEmpty()); 924 return errorMsgs; 925 } 926 927 /** 928 * Checks the existing keystore parameters. 929 * @return the error messages found while checking existing keystore 930 * parameters. 931 */ 932 private ArrayList<LocalizableMessage> checkKeystore() 933 { 934 ArrayList<LocalizableMessage> errorMsgs = new ArrayList<>(); 935 936 boolean pathValid = true; 937 boolean pwdValid = true; 938 939 if (rbUseExistingCertificate.isSelected() && 940 (cbEnableSSL.isSelected() || cbEnableStartTLS.isSelected())) 941 { 942 String path = tfKeystorePath.getText(); 943 if (rbJKS.isSelected() || rbJCEKS.isSelected() || rbPKCS12.isSelected()) 944 { 945 /* Check the path */ 946 if (path == null || path.length() == 0) 947 { 948 errorMsgs.add(INFO_KEYSTORE_PATH_NOT_PROVIDED.get()); 949 } 950 else 951 { 952 File f = new File(path); 953 if (!f.exists()) 954 { 955 errorMsgs.add(INFO_KEYSTORE_PATH_DOES_NOT_EXIST.get()); 956 } 957 else if (!f.isFile()) 958 { 959 errorMsgs.add(INFO_KEYSTORE_PATH_NOT_A_FILE.get()); 960 } 961 } 962 963 pathValid = errorMsgs.isEmpty(); 964 } 965 966 String pwd = String.valueOf(tfKeystorePwd.getPassword()); 967 if (pathValid) 968 { 969 try 970 { 971 CertificateManager certManager; 972 if (rbJKS.isSelected()) 973 { 974 certManager = new CertificateManager( 975 path, 976 CertificateManager.KEY_STORE_TYPE_JKS, 977 pwd); 978 } 979 else if (rbJCEKS.isSelected()) 980 { 981 certManager = new CertificateManager( 982 path, 983 CertificateManager.KEY_STORE_TYPE_JCEKS, 984 pwd); 985 } 986 else if (rbPKCS12.isSelected()) 987 { 988 certManager = new CertificateManager( 989 path, 990 CertificateManager.KEY_STORE_TYPE_PKCS12, 991 pwd); 992 } 993 else if (rbPKCS11.isSelected()) 994 { 995 certManager = new CertificateManager( 996 CertificateManager.KEY_STORE_PATH_PKCS11, 997 CertificateManager.KEY_STORE_TYPE_PKCS11, 998 pwd); 999 } 1000 else 1001 { 1002 throw new IllegalStateException("No keystore type selected."); 1003 } 1004 aliases = certManager.getCertificateAliases(); 1005 if (aliases == null || aliases.length == 0) 1006 { 1007 // Could not retrieve any certificate 1008 if (rbPKCS11.isSelected()) 1009 { 1010 errorMsgs.add(INFO_PKCS11_KEYSTORE_DOES_NOT_EXIST.get()); 1011 } 1012 else 1013 { 1014 if (rbJKS.isSelected()) 1015 { 1016 errorMsgs.add(INFO_JKS_KEYSTORE_DOES_NOT_EXIST.get()); 1017 } 1018 else if (rbJCEKS.isSelected()) 1019 { 1020 errorMsgs.add(INFO_JCEKS_KEYSTORE_DOES_NOT_EXIST.get()); 1021 } 1022 else 1023 { 1024 errorMsgs.add(INFO_PKCS12_KEYSTORE_DOES_NOT_EXIST.get()); 1025 } 1026 pathValid = false; 1027 } 1028 } 1029 else 1030 { 1031 certificateHasAlias = certManager.hasRealAliases(); 1032 } 1033 } 1034 catch (KeyStoreException ke) 1035 { 1036 // issue OPENDJ-18, related to JDK bug 1037 if (StaticUtils 1038 .stackTraceContainsCause(ke, ArithmeticException.class)) 1039 { 1040 errorMsgs.add(INFO_ERROR_ACCESSING_KEYSTORE_JDK_BUG.get()); 1041 } 1042 else 1043 { 1044 pwdValid = false; 1045 if (!rbPKCS11.isSelected()) 1046 { 1047 pathValid = false; 1048 } 1049 // Could not access to the keystore: because the password is 1050 // no good, because the provided file is not a valid keystore, etc. 1051 if (rbPKCS11.isSelected()) 1052 { 1053 errorMsgs.add(INFO_ERROR_ACCESSING_PKCS11_KEYSTORE.get()); 1054 } 1055 else 1056 { 1057 if (rbJKS.isSelected()) 1058 { 1059 errorMsgs.add(INFO_ERROR_ACCESSING_JKS_KEYSTORE.get()); 1060 } 1061 else if (rbJCEKS.isSelected()) 1062 { 1063 errorMsgs.add(INFO_ERROR_ACCESSING_JCEKS_KEYSTORE.get()); 1064 } 1065 else 1066 { 1067 errorMsgs.add(INFO_ERROR_ACCESSING_PKCS12_KEYSTORE.get()); 1068 } 1069 pathValid = false; 1070 } 1071 } 1072 } 1073 } 1074 } 1075 1076 setValidLater(lKeystorePath, pathValid); 1077 setValidLater(lKeystorePwd, pwdValid); 1078 1079 return errorMsgs; 1080 } 1081 1082 /** 1083 * Method that updates the text style of a provided component by calling 1084 * SwingUtilities.invokeLater. This method is aimed to be called outside 1085 * the event thread (calling it from the event thread will also work though). 1086 * @param comp the component to be updated. 1087 * @param valid whether to use a TextStyle to mark the component as valid 1088 * or as invalid. 1089 */ 1090 private void setValidLater(final JComponent comp, final boolean valid) 1091 { 1092 SwingUtilities.invokeLater(new Runnable() 1093 { 1094 public void run() 1095 { 1096 UIFactory.setTextStyle(comp, 1097 valid ? UIFactory.TextStyle.SECONDARY_FIELD_VALID : 1098 UIFactory.TextStyle.SECONDARY_FIELD_INVALID); 1099 } 1100 }); 1101 } 1102 1103 /** 1104 * Method written for testing purposes. 1105 * @param args the arguments to be passed to the test program. 1106 */ 1107 public static void main(String[] args) 1108 { 1109 try 1110 { 1111 // UIFactory.initialize(); 1112 SecurityOptionsDialog dlg = new SecurityOptionsDialog(new JFrame(), 1113 SecurityOptions.createNoCertificateOptions()); 1114 dlg.pack(); 1115 dlg.setVisible(true); 1116 } catch (Exception ex) 1117 { 1118 ex.printStackTrace(); 1119 } 1120 } 1121}