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-2009 Sun Microsystems, Inc. 015 * Portions Copyright 2013-2016 ForgeRock AS. 016 */ 017package org.opends.quicksetup.ui; 018 019import static org.opends.messages.QuickSetupMessages.*; 020 021import java.awt.CardLayout; 022import java.awt.Component; 023import java.awt.Dimension; 024import java.awt.GridBagConstraints; 025import java.awt.GridBagLayout; 026import java.awt.event.ActionEvent; 027import java.awt.event.ActionListener; 028import java.awt.event.WindowAdapter; 029import java.awt.event.WindowEvent; 030import java.security.MessageDigest; 031import java.security.NoSuchAlgorithmException; 032import java.security.cert.CertificateEncodingException; 033import java.security.cert.X509Certificate; 034import java.text.DateFormat; 035import java.util.Date; 036import java.util.HashMap; 037import java.util.Map; 038 039import javax.naming.ldap.LdapName; 040import javax.naming.ldap.Rdn; 041import javax.swing.Box; 042import javax.swing.JButton; 043import javax.swing.JComboBox; 044import javax.swing.JComponent; 045import javax.swing.JDialog; 046import javax.swing.JEditorPane; 047import javax.swing.JFrame; 048import javax.swing.JLabel; 049import javax.swing.JPanel; 050import javax.swing.JScrollPane; 051import javax.swing.border.EmptyBorder; 052import javax.swing.event.HyperlinkEvent; 053import javax.swing.event.HyperlinkListener; 054 055import org.forgerock.i18n.LocalizableMessage; 056import org.forgerock.i18n.LocalizableMessageBuilder; 057import org.forgerock.i18n.slf4j.LocalizedLogger; 058import org.opends.quicksetup.UserDataCertificateException; 059import org.opends.quicksetup.event.MinimumSizeComponentListener; 060 061/** 062 * This class is used to present the user a certificate to the user in order 063 * it to be accepted. 064 */ 065public class CertificateDialog extends JDialog implements HyperlinkListener 066{ 067 /** 068 * The enumeration that defines the different answers that the user can 069 * provide for this dialog. 070 */ 071 public enum ReturnType 072 { 073 /** The user did not accept the certificate. */ 074 NOT_ACCEPTED, 075 /** The user accepted the certificate only for this session. */ 076 ACCEPTED_FOR_SESSION, 077 /** The user accepted the certificate permanently. */ 078 ACCEPTED_PERMANENTLY 079 } 080 private static final long serialVersionUID = -8989965057591475064L; 081 private ReturnType returnValue = ReturnType.NOT_ACCEPTED; 082 private final UserDataCertificateException ce; 083 private JButton doNotAcceptButton; 084 private JComponent certificateDetails; 085 private JEditorPane explanationPane; 086 private boolean detailsAlreadyClicked; 087 private String explanationWithHideDetails; 088 private String explanationWithShowDetails; 089 090 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 091 092 /** 093 * Constructor of the certificate dialog. 094 * @param parent the parent frame for this dialog. 095 * @param ce the UserDataCertificateException we use to get the information 096 * about the certificate that was presented and the reason why it was 097 * rejected. 098 */ 099 public CertificateDialog(JFrame parent, UserDataCertificateException ce) 100 { 101 super(parent); 102 this.ce = ce; 103 setTitle(INFO_CERTIFICATE_DIALOG_TITLE.get().toString()); 104 getContentPane().add(createPanel()); 105 setModal(true); 106 pack(); 107 if (parent != null 108 && getPreferredSize().width > parent.getWidth()) 109 { 110 setPreferredSize(new Dimension(Math.max(parent.getWidth() - 20, 600), 111 getPreferredSize().height)); 112 } 113 pack(); 114 int minWidth = (int) getPreferredSize().getWidth(); 115 int minHeight = (int) getPreferredSize().getHeight(); 116 addComponentListener(new MinimumSizeComponentListener(this, minWidth, 117 minHeight)); 118 getRootPane().setDefaultButton(doNotAcceptButton); 119 120 addWindowListener(new WindowAdapter() 121 { 122 @Override 123 public void windowClosing(WindowEvent e) 124 { 125 doNotAccept(); 126 } 127 }); 128 setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); 129 130 Utilities.centerOnComponent(this, parent); 131 } 132 133 /** 134 * Wheter the user accepted the certificate or not. 135 * @return the ReturnType object defining what the user chose to do with the 136 * certificate. 137 */ 138 public ReturnType getUserAnswer() 139 { 140 return returnValue; 141 } 142 143 /** 144 * Implements HyperlinkListener. When the user clicks on a link we assume 145 * that is the show details/hide details and we update the visible components 146 * accordingly. 147 * 148 * @param e the HyperlinkEvent. 149 */ 150 @Override 151 public void hyperlinkUpdate(HyperlinkEvent e) 152 { 153 if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) 154 { 155 boolean detailsVisible = !certificateDetails.isVisible(); 156 explanationPane.setText(detailsVisible? 157 explanationWithHideDetails:explanationWithShowDetails); 158 certificateDetails.setVisible(detailsVisible); 159 if (detailsVisible && !detailsAlreadyClicked) 160 { 161 detailsAlreadyClicked = true; 162 pack(); 163 } 164 } 165 } 166 167 /** 168 * Creates and returns the panel of the dialog. 169 * @return the panel of the dialog. 170 */ 171 private JPanel createPanel() 172 { 173 GridBagConstraints gbc = new GridBagConstraints(); 174 175 JPanel contentPanel = new JPanel(new GridBagLayout()); 176 contentPanel.setBackground(UIFactory.DEFAULT_BACKGROUND); 177 gbc.anchor = GridBagConstraints.NORTHWEST; 178 gbc.insets = UIFactory.getEmptyInsets(); 179 gbc.fill = GridBagConstraints.BOTH; 180 gbc.gridwidth = GridBagConstraints.REMAINDER; 181 gbc.weightx = 1.0; 182 183 JPanel topPanel = new JPanel(new GridBagLayout()); 184 topPanel.setBorder(UIFactory.DIALOG_PANEL_BORDER); 185 topPanel.setBackground(UIFactory.CURRENT_STEP_PANEL_BACKGROUND); 186 187 gbc.weighty = 0.0; 188 gbc.insets = UIFactory.getCurrentStepPanelInsets(); 189 topPanel.add(createTitlePanel(), gbc); 190 gbc.insets.top = UIFactory.TOP_INSET_INSTRUCTIONS_SUBPANEL; 191 topPanel.add(createTextPane(), gbc); 192 certificateDetails = createCertificateDetailsPane(); 193 gbc.insets.top = 0; 194 gbc.insets.bottom = 0; 195 topPanel.add(Box.createHorizontalStrut( 196 certificateDetails.getPreferredSize().width), gbc); 197 gbc.insets.top = 0; 198 gbc.weighty = 1.0; 199 JPanel auxPanel = UIFactory.makeJPanel(); 200 auxPanel.setLayout(new GridBagLayout()); 201 gbc.weightx = 0.0; 202 gbc.insets = UIFactory.getEmptyInsets(); 203 gbc.gridwidth = GridBagConstraints.RELATIVE; 204 auxPanel.add(Box.createVerticalStrut(100), gbc); 205 gbc.weightx = 1.0; 206 gbc.gridwidth = GridBagConstraints.REMAINDER; 207 auxPanel.add(certificateDetails, gbc); 208 gbc.insets = UIFactory.getCurrentStepPanelInsets(); 209 gbc.insets.bottom = UIFactory.TOP_INSET_INPUT_SUBPANEL; 210 topPanel.add(auxPanel, gbc); 211 certificateDetails.setVisible(false); 212 gbc.weighty = 0.2; 213 gbc.insets = UIFactory.getEmptyInsets(); 214 topPanel.add(Box.createVerticalGlue(), gbc); 215 contentPanel.add(topPanel, gbc); 216 gbc.weighty = 0.0; 217 gbc.insets = UIFactory.getButtonsPanelInsets(); 218 gbc.fill = GridBagConstraints.HORIZONTAL; 219 contentPanel.add(createButtonsPanel(), gbc); 220 221 return contentPanel; 222 } 223 224 /** 225 * Creates and returns the title sub panel. 226 * @return the title sub panel. 227 */ 228 private Component createTitlePanel() 229 { 230 JPanel titlePanel = UIFactory.makeJPanel(); 231 titlePanel.setLayout(new GridBagLayout()); 232 GridBagConstraints gbc = new GridBagConstraints(); 233 gbc.anchor = GridBagConstraints.NORTHWEST; 234 gbc.fill = GridBagConstraints.BOTH; 235 gbc.weightx = 0.0; 236 gbc.gridwidth = GridBagConstraints.RELATIVE; 237 238 LocalizableMessage title = INFO_CERTIFICATE_TITLE.get(); 239 JLabel l = 240 UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, title, 241 UIFactory.TextStyle.TITLE); 242 l.setOpaque(false); 243 titlePanel.add(l, gbc); 244 245 gbc.gridwidth = GridBagConstraints.RELATIVE; 246 gbc.anchor = GridBagConstraints.NORTHWEST; 247 gbc.weightx = 1.0; 248 gbc.gridwidth = GridBagConstraints.REMAINDER; 249 gbc.insets.left = 0; 250 gbc.weightx = 1.0; 251 gbc.gridwidth = GridBagConstraints.REMAINDER; 252 titlePanel.add(Box.createHorizontalGlue(), gbc); 253 254 return titlePanel; 255 } 256 257 /** 258 * Creates and returns the text sub panel. 259 * @return the text sub panel. 260 */ 261 private Component createTextPane() 262 { 263 LocalizableMessage text; 264 if (ce.getType() == UserDataCertificateException.Type.NOT_TRUSTED) 265 { 266 text = INFO_CERTIFICATE_NOT_TRUSTED_TEXT.get( 267 ce.getHost(), ce.getPort(), 268 ce.getHost(), ce.getPort()); 269 } 270 else 271 { 272 text = INFO_CERTIFICATE_NAME_MISMATCH_TEXT.get( 273 ce.getHost(), ce.getPort(), 274 ce.getHost(), 275 ce.getHost(), ce.getPort(), 276 ce.getHost(), ce.getPort()); 277 } 278 JPanel p = UIFactory.makeJPanel(); 279 p.setLayout(new GridBagLayout()); 280 GridBagConstraints gbc = new GridBagConstraints(); 281 gbc.gridwidth = GridBagConstraints.RELATIVE; 282 gbc.anchor = GridBagConstraints.NORTHWEST; 283 p.add(UIFactory.makeJLabel(UIFactory.IconType.WARNING_LARGE, null, 284 UIFactory.TextStyle.NO_STYLE), gbc); 285 gbc.weightx = 1.0; 286 gbc.gridwidth = GridBagConstraints.REMAINDER; 287 gbc.fill = GridBagConstraints.BOTH; 288 gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD; 289 gbc.insets.bottom = 0; 290 explanationPane = UIFactory.makeHtmlPane(null, UIFactory.INSTRUCTIONS_FONT); 291 explanationPane.setOpaque(false); 292 explanationPane.setEditable(false); 293 explanationPane.addHyperlinkListener(this); 294 p.add(explanationPane, gbc); 295 if (ce.getChain() != null && ce.getChain().length > 0) 296 { 297 LocalizableMessageBuilder mb = new LocalizableMessageBuilder(); 298 mb.append(text); 299 mb.append(INFO_CERTIFICATE_SHOW_DETAILS_TEXT.get()); 300 explanationWithShowDetails = UIFactory.applyFontToHtml( 301 mb.toString(), UIFactory.INSTRUCTIONS_FONT); 302 LocalizableMessageBuilder mb2 = new LocalizableMessageBuilder(); 303 mb2.append(text); 304 mb2.append(INFO_CERTIFICATE_HIDE_DETAILS_TEXT.get()); 305 explanationWithHideDetails = UIFactory.applyFontToHtml( 306 mb2.toString(), UIFactory.INSTRUCTIONS_FONT); 307 308 explanationPane.setText(explanationWithShowDetails); 309 } 310 else 311 { 312 explanationPane.setText(text.toString()); 313 } 314 return p; 315 } 316 317 /** 318 * Creates and returns the buttons DO NOT ACCEPT/ACCEPT FOR THIS SESSION/ 319 * ACCEPT PERMANENTLY sub panel. 320 * @return the buttons DO NOT ACCEPT/ACCEPT FOR THIS SESSION/ACCEPT 321 * PERMANENTLY sub panel. 322 */ 323 private Component createButtonsPanel() 324 { 325 JPanel buttonsPanel = UIFactory.makeJPanel(); 326 buttonsPanel.setLayout(new GridBagLayout()); 327 GridBagConstraints gbc = new GridBagConstraints(); 328 gbc.fill = GridBagConstraints.HORIZONTAL; 329 gbc.gridwidth = 4; 330 gbc.insets = UIFactory.getEmptyInsets(); 331 gbc.insets.left = UIFactory.getCurrentStepPanelInsets().left; 332 buttonsPanel.add(UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, 333 null, UIFactory.TextStyle.NO_STYLE), gbc); 334 gbc.weightx = 1.0; 335 gbc.gridwidth--; 336 gbc.insets.left = 0; 337 buttonsPanel.add(Box.createHorizontalGlue(), gbc); 338 gbc.gridwidth = 3; 339 gbc.fill = GridBagConstraints.NONE; 340 gbc.weightx = 0.0; 341 JButton acceptSessionButton = UIFactory.makeJButton( 342 INFO_CERTIFICATE_DIALOG_ACCEPT_FOR_SESSION_BUTTON_LABEL.get(), 343 INFO_CERTIFICATE_DIALOG_ACCEPT_FOR_SESSION_BUTTON_TOOLTIP.get()); 344 buttonsPanel.add(acceptSessionButton, gbc); 345 acceptSessionButton.addActionListener(new ActionListener() { 346 @Override 347 public void actionPerformed(ActionEvent ev) { 348 acceptForSession(); 349 } 350 }); 351 352 gbc.gridwidth = GridBagConstraints.RELATIVE; 353 gbc.insets.left = UIFactory.HORIZONTAL_INSET_BETWEEN_BUTTONS; 354 JButton acceptPermanentlyButton = UIFactory.makeJButton( 355 INFO_CERTIFICATE_DIALOG_ACCEPT_PERMANENTLY_BUTTON_LABEL.get(), 356 INFO_CERTIFICATE_DIALOG_ACCEPT_PERMANENTLY_BUTTON_TOOLTIP.get()); 357 buttonsPanel.add(acceptPermanentlyButton, gbc); 358 acceptPermanentlyButton.addActionListener(new ActionListener() { 359 @Override 360 public void actionPerformed(ActionEvent ev) { 361 acceptPermanently(); 362 } 363 }); 364 365 gbc.gridwidth = GridBagConstraints.REMAINDER; 366 doNotAcceptButton = 367 UIFactory.makeJButton( 368 INFO_CERTIFICATE_DIALOG_DO_NOT_ACCEPT_BUTTON_LABEL.get(), 369 INFO_CERTIFICATE_DIALOG_DO_NOT_ACCEPT_BUTTON_TOOLTIP.get()); 370 buttonsPanel.add(doNotAcceptButton, gbc); 371 doNotAcceptButton.addActionListener(new ActionListener() 372 { 373 @Override 374 public void actionPerformed(ActionEvent ev) 375 { 376 doNotAccept(); 377 } 378 }); 379 380 return buttonsPanel; 381 } 382 383 /** 384 * Creates the panel containing a representation of the certificate chain. 385 * @return the panel containing a representation of the certificate chain. 386 */ 387 private JComponent createCertificateDetailsPane() 388 { 389 JPanel p = UIFactory.makeJPanel(); 390 p.setLayout(new GridBagLayout()); 391 if (ce.getChain() != null && ce.getChain().length > 0) 392 { 393 final JComboBox<String> combo = new JComboBox<String>(); 394 combo.setToolTipText( 395 INFO_CERTIFICATE_CHAIN_COMBO_TOOLTIP.get().toString()); 396 final CardLayout cl = new CardLayout(); 397 final JPanel cardPanel = new JPanel(cl); 398 final Map<String, JPanel> hmPanels = new HashMap<>(); 399 400 LocalizableMessage[] labels = 401 { 402 INFO_CERTIFICATE_SUBJECT_LABEL.get(), 403 INFO_CERTIFICATE_ISSUED_BY_LABEL.get(), 404 INFO_CERTIFICATE_VALID_FROM_LABEL.get(), 405 INFO_CERTIFICATE_EXPIRES_ON_LABEL.get(), 406 INFO_CERTIFICATE_TYPE_LABEL.get(), 407 INFO_CERTIFICATE_SERIAL_NUMBER_LABEL.get(), 408 INFO_CERTIFICATE_MD5_FINGERPRINT_LABEL.get(), 409 INFO_CERTIFICATE_SHA1_FINGERPRINT_LABEL.get() 410 }; 411 412 for (int i=0; i<ce.getChain().length; i++) 413 { 414 X509Certificate cert = ce.getChain()[i]; 415 JComponent[] components = 416 { 417 createSubjectComponent(cert), 418 createIssuedByComponent(cert), 419 createValidFromComponent(cert), 420 createExpiresOnComponent(cert), 421 createTypeComponent(cert), 422 createSerialNumberComponent(cert), 423 createMD5FingerprintComponent(cert), 424 createSHA1FingerprintComponent(cert) 425 }; 426 JPanel certPanel = UIFactory.makeJPanel(); 427 certPanel.setLayout(new GridBagLayout()); 428 GridBagConstraints gbc = new GridBagConstraints(); 429 gbc.anchor = GridBagConstraints.NORTHWEST; 430 gbc.fill = GridBagConstraints.HORIZONTAL; 431 432 for (int j=0; j<labels.length; j++) 433 { 434 JLabel l = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, 435 labels[j], UIFactory.TextStyle.PRIMARY_FIELD_VALID); 436 437 l.setLabelFor(components[j]); 438 if (j > 0) 439 { 440 gbc.insets.top = UIFactory.TOP_INSET_SECONDARY_FIELD; 441 } 442 gbc.gridwidth = GridBagConstraints.RELATIVE; 443 gbc.weightx = 0.0; 444 gbc.insets.left = 0; 445 certPanel.add(l, gbc); 446 gbc.gridwidth = GridBagConstraints.REMAINDER; 447 gbc.weightx = 1.0; 448 gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD; 449 certPanel.add(components[j], gbc); 450 } 451 String name = getName(cert); 452 hmPanels.put(name, certPanel); 453 cardPanel.add(name, certPanel); 454 combo.addItem(name); 455 } 456 GridBagConstraints gbc = new GridBagConstraints(); 457 if (ce.getChain().length == 1) 458 { 459 gbc.gridwidth = GridBagConstraints.REMAINDER; 460 gbc.weightx = 1.0; 461 gbc.fill = GridBagConstraints.BOTH; 462 p.add(cardPanel, gbc); 463 464 gbc.weighty = 1.0; 465 p.add(Box.createVerticalGlue(), gbc); 466 } 467 else 468 { 469 gbc.anchor = GridBagConstraints.WEST; 470 gbc.gridwidth = 3; 471 gbc.fill = GridBagConstraints.HORIZONTAL; 472 JPanel auxPanel = UIFactory.makeJPanel(); 473 auxPanel.setLayout(new GridBagLayout()); 474 JLabel l = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, 475 INFO_CERTIFICATE_CHAIN_LABEL.get(), 476 UIFactory.TextStyle.PRIMARY_FIELD_VALID); 477 auxPanel.add(l, gbc); 478 gbc.gridwidth = GridBagConstraints.RELATIVE; 479 gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD; 480 auxPanel.add(combo, gbc); 481 l.setLabelFor(combo); 482 gbc.gridwidth = GridBagConstraints.REMAINDER; 483 gbc.insets.left = 0; 484 gbc.weightx = 1.0; 485 auxPanel.add(Box.createHorizontalGlue(), gbc); 486 487 p.add(auxPanel, gbc); 488 489 gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD; 490 gbc.fill = GridBagConstraints.BOTH; 491 p.add(cardPanel, gbc); 492 493 gbc.weighty = 1.0; 494 p.add(Box.createVerticalGlue(), gbc); 495 } 496 497 combo.addActionListener(new ActionListener() 498 { 499 @Override 500 public void actionPerformed(ActionEvent ev) 501 { 502 String selectedItem = (String)combo.getSelectedItem(); 503 cl.show(hmPanels.get(selectedItem), selectedItem); 504 } 505 }); 506 } 507 JScrollPane scroll = new JScrollPane(p); 508 scroll.setViewportBorder(new EmptyBorder(0, 0, 0, 0)); 509 scroll.setOpaque(false); 510 scroll.getViewport().setOpaque(false); 511 scroll.setPreferredSize(new Dimension(scroll.getPreferredSize().width, 512 175)); 513 return scroll; 514 } 515 516 private JComponent createSubjectComponent(X509Certificate cert) 517 { 518 LocalizableMessage dn = LocalizableMessage.raw(cert.getSubjectX500Principal().getName()); 519 return makeValueLabel(dn); 520 } 521 522 private JComponent createIssuedByComponent(X509Certificate cert) 523 { 524 LocalizableMessage dn = LocalizableMessage.raw(cert.getIssuerX500Principal().getName()); 525 return makeValueLabel(dn); 526 } 527 528 private JComponent createValidFromComponent(X509Certificate cert) 529 { 530 JComponent c; 531 532 Date date = cert.getNotBefore(); 533 DateFormat df = DateFormat.getDateTimeInstance(DateFormat.SHORT, 534 DateFormat.SHORT); 535 LocalizableMessage value = LocalizableMessage.raw(df.format(date)); 536 long t1 = System.currentTimeMillis(); 537 long t2 = date.getTime(); 538 boolean isNotValidYet = t1 < t2; 539 540 if (isNotValidYet) 541 { 542 c = UIFactory.makeJLabel(UIFactory.IconType.ERROR, 543 INFO_CERTIFICATE_NOT_VALID_YET.get(value), 544 UIFactory.TextStyle.SECONDARY_FIELD_INVALID); 545 } 546 else 547 { 548 c = makeValueLabel(value); 549 } 550 return c; 551 } 552 553 554 private JComponent createExpiresOnComponent(X509Certificate cert) 555 { 556 JComponent c; 557 558 Date date = cert.getNotAfter(); 559 DateFormat df = DateFormat.getDateTimeInstance(DateFormat.SHORT, 560 DateFormat.SHORT); 561 LocalizableMessage value = LocalizableMessage.raw(df.format(date)); 562 long t1 = System.currentTimeMillis(); 563 long t2 = date.getTime(); 564 boolean isExpired = t1 > t2; 565 566 if (isExpired) 567 { 568 c = UIFactory.makeJLabel(UIFactory.IconType.ERROR, 569 INFO_CERTIFICATE_EXPIRED.get(value), 570 UIFactory.TextStyle.SECONDARY_FIELD_INVALID); 571 } 572 else 573 { 574 c = makeValueLabel(value); 575 } 576 return c; 577 } 578 579 580 private JComponent createTypeComponent(X509Certificate cert) 581 { 582 LocalizableMessage type = LocalizableMessage.raw(cert.getType()); 583 return makeValueLabel(type); 584 } 585 586 private JComponent createSerialNumberComponent(X509Certificate cert) 587 { 588 LocalizableMessage serialNumber = LocalizableMessage.raw(String.valueOf(cert.getSerialNumber())); 589 return makeValueLabel(serialNumber); 590 } 591 592 593 /** 594 * Returns the LocalizableMessage representation of the SHA1 fingerprint. 595 * @param cert the certificate object. 596 * @return the LocalizableMessage representation of the SHA1 fingerprint. 597 */ 598 private static LocalizableMessage getSHA1FingerPrint(X509Certificate cert) 599 { 600 return getFingerPrint(cert, "SHA1"); 601 } 602 603 /** 604 * Returns the LocalizableMessage representation of the MD5 fingerprint. 605 * @param cert the certificate object. 606 * @return the LocalizableMessage representation of the MD5 fingerprint. 607 */ 608 private static LocalizableMessage getMD5FingerPrint(X509Certificate cert) 609 { 610 return getFingerPrint(cert, "MD5"); 611 } 612 613 private static LocalizableMessage getFingerPrint(X509Certificate cert, String algorithm) 614 { 615 try { 616 MessageDigest md = MessageDigest.getInstance(algorithm); 617 byte[] b = md.digest(cert.getEncoded()); 618 StringBuilder sb = new StringBuilder(); 619 for (int i = 0; i < b.length; i++) 620 { 621 if (i > 0) 622 { 623 sb.append(":"); 624 } 625 sb.append(Integer.toHexString(b[i] & 0xFF)); 626 } 627 return LocalizableMessage.raw(sb); 628 } 629 catch (NoSuchAlgorithmException nsae) { 630 logger.warn(LocalizableMessage.raw(algorithm + " algorithm not supported: " + nsae, nsae)); 631 return null; 632 } 633 catch (CertificateEncodingException cee) { 634 logger.warn(LocalizableMessage.raw("Certificate encoding exception: "+cee, cee)); 635 return null; 636 } 637 } 638 639 private JComponent createSHA1FingerprintComponent(X509Certificate cert) 640 { 641 return UIFactory.makeTextPane(getSHA1FingerPrint(cert), 642 UIFactory.TextStyle.SECONDARY_FIELD_VALID); 643 } 644 645 private JComponent createMD5FingerprintComponent(X509Certificate cert) 646 { 647 return UIFactory.makeTextPane(getMD5FingerPrint(cert), 648 UIFactory.TextStyle.SECONDARY_FIELD_VALID); 649 } 650 651 private JLabel makeValueLabel(LocalizableMessage value) 652 { 653 if (value == null) 654 { 655 value = INFO_NOT_AVAILABLE_LABEL.get(); 656 } 657 return UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, value, 658 UIFactory.TextStyle.SECONDARY_FIELD_VALID); 659 } 660 661 private String getName(X509Certificate cert) 662 { 663 String name = cert.getSubjectX500Principal().getName(); 664 try 665 { 666 LdapName dn = new LdapName(name); 667 Rdn rdn = dn.getRdn(0); 668 return rdn.getValue().toString(); 669 } 670 catch (Throwable t) 671 { 672 logger.warn(LocalizableMessage.raw("Error parsing subject dn: "+ 673 cert.getSubjectX500Principal(), t)); 674 return name; 675 } 676 } 677 678 /** Method called when user clicks on ok. */ 679 private void acceptForSession() 680 { 681 returnValue = ReturnType.ACCEPTED_FOR_SESSION; 682 dispose(); 683 } 684 685 /** Method called when user clicks on cancel. */ 686 private void doNotAccept() 687 { 688 returnValue = ReturnType.NOT_ACCEPTED; 689 dispose(); 690 } 691 692 /** Method called when user clicks on ok. */ 693 private void acceptPermanently() 694 { 695 returnValue = ReturnType.ACCEPTED_PERMANENTLY; 696 dispose(); 697 } 698}