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