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