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