Package net.java.sip.communicator.impl.certificate

Source Code of net.java.sip.communicator.impl.certificate.CertificateVerificationServiceImpl$HostTrustManager

/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.certificate;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.security.cert.*;
import java.security.interfaces.*;
import java.text.*;
import java.util.*;

import javax.naming.*;
import javax.swing.*;
import javax.naming.ldap.*;
import javax.net.ssl.*;
import javax.security.auth.x500.*;

import net.java.sip.communicator.service.certificate.*;
import net.java.sip.communicator.service.resources.*;
import net.java.sip.communicator.util.*;
import net.java.sip.communicator.util.swing.*;

/**
* Asks the user for permission for the
* certificates which are for some reason not valid and not globally trusted.
*
* @author Damian Minkov
* @author Yana Stamcheva
*/
public class CertificateVerificationServiceImpl
    implements CertificateVerificationService
{
    /**
     * The property for the configuration value to store the
     * KeyStore file location.
     */
    private static final String KEYSTORE_FILE_PROP =
        "net.java.sip.communicator.impl.protocol.sip.net.KEYSTORE";

    /**
     * The default name of the keystore file.
     */
    private static final String KEY_STORE_FILE_NAME = "jssecacerts";

    /**
     * The key store holding stored certificate during previous sessions.
     */
    private KeyStore keyStore;

    /**
     * This are the certificates which are temporally allowed
     * only for this session.
     */
    private ArrayList<X509Certificate> temporalyAllowed =
            new ArrayList<X509Certificate>();

    /**
     * The default password used for the keystore.
     */
    private char[] defaultPassword = new char[0];

    /**
     * The logger.
     */
    private static final Logger logger =
        Logger.getLogger(CertificateVerificationServiceImpl.class);

    /**
     * Return the File object for the keystore we will use. It can be
     * a full path existing keystore set from user. If it is set from user
     * but not existing we ignore it and return the default one.
     * If it is not set return just the default one.
     *
     * @return the file which will be used by KeyStore.
     * @throws Exception exception on creating file.
     */
    private File getKeyStoreLocation()
        throws Exception
    {
        String keyStoreFile = CertificateVerificationActivator.
            getConfigurationService().getString(KEYSTORE_FILE_PROP);

        if(keyStoreFile == null || keyStoreFile.length() == 0)
            return CertificateVerificationActivator.getFileAccessService()
                    .getPrivatePersistentFile(KEY_STORE_FILE_NAME);

        File f = new File(keyStoreFile);

        if(f.exists())
            return f;
        else
        {
            // Hum a keystore file is set but is not existing
            // lets remove the wrong config and return the default file.
            // An old version used to store the whole path to the file
            // and if the user changes location of its home dir
            // it breaks things.
            CertificateVerificationActivator.getConfigurationService()
                .removeProperty(KEYSTORE_FILE_PROP);

            return CertificateVerificationActivator.getFileAccessService()
                    .getPrivatePersistentFile(KEY_STORE_FILE_NAME);
        }
    }

    /**
     * Add a certificate to the local trust store.
     *
     * @param cert The certificate to add to the trust store.
     * @param trustMode Whether to trust the certificate permanently
     *  or only for the current session.
     * @throws GeneralSecurityException
     */
    public void addCertificateToTrust(X509Certificate cert, int trustMode)
        throws GeneralSecurityException
    {
        switch (trustMode)
        {
            case TRUST_ALWAYS:
                try
                {
                    KeyStore kStore = getKeyStore();
                    synchronized (kStore)
                    {
                        kStore.setCertificateEntry(
                            String.valueOf(System.currentTimeMillis()), cert);

                        kStore.store(new FileOutputStream(getKeyStoreLocation()),
                            defaultPassword);
                    }
                }
                catch (Exception e)
                {
                    logger.error("cannot add certificate to truststore", e);
                }
                break;
            case TRUST_THIS_SESSION_ONLY:
                temporalyAllowed.add(cert);
                break;
            default:
                throw new GeneralSecurityException(
                    "Cannot add a certificate to truststore "
                        + "when no trust is requested.");
        }
    }

    /**
     * Checks does the user trust the supplied chain of certificates, when
     * connecting to the server and port.
     *
     * @param   chain the chain of the certificates to check with user.
     * @param   message A text that describes why the verification failed.
     * @return  the result of user interaction on of DO_NOT_TRUST, TRUST_ALWAYS,
     *          TRUST_THIS_SESSION_ONLY.
     */
    protected int verify(
        final X509Certificate[] chain, final String message)
    {
        final VerifyCertificateDialog dialog = new VerifyCertificateDialog(
                        chain, message);
        try
        {
            // show the dialog in the swing thread and wait for the user
            // choice
            SwingUtilities.invokeAndWait(new Runnable() {
                public void run()
                {
                    dialog.setVisible(true);
                }
            });
        }
        catch (Exception e)
        {
            logger.error("Cannot show certificate verification dialog", e);
            return DO_NOT_TRUST;
        }

        if(!dialog.isTrusted)
            return DO_NOT_TRUST;
        else if(dialog.alwaysTrustCheckBox.isSelected())
        {
            try
            {
                KeyStore kStore = getKeyStore();

                synchronized(kStore)
                {
                    // TODO this is potentially dangerous and not what the user
                    // wanted (e.g. trusting a complete fraud CA instead of only
                    // trusting one single certificate
                    for (X509Certificate c : chain)
                        kStore.setCertificateEntry(
                            String.valueOf(System.currentTimeMillis()), c);

                    kStore.store(
                        new FileOutputStream(getKeyStoreLocation()),
                        defaultPassword);
                }
            } catch (Throwable e)
            {
                logger.error("Error saving keystore.", e);
            }

            return TRUST_ALWAYS;
        }
        else
        {
            for (X509Certificate c : chain)
                temporalyAllowed.add(c);

            return TRUST_THIS_SESSION_ONLY;
        }
    }

    /**
     * Obtain custom trust manager, which will try verify the certificate and
     * if verification fails will query the user for acceptance.
     *
     * @param   message A text that describes why the verification failed.
     * @return the custom trust manager.
     * @throws GeneralSecurityException when there is problem creating
     *         the trust manager
     */
    public X509TrustManager getTrustManager(String message)
        throws GeneralSecurityException
    {
        TrustManagerFactory tmFactory =
            TrustManagerFactory.getInstance(
                KeyManagerFactory.getDefaultAlgorithm());
        tmFactory.init((KeyStore)null);

        return new HostTrustManager(
            (X509TrustManager)tmFactory.getTrustManagers()[0], message);
    }

    /**
     * Returns SSLContext instance initialized with the custom trust manager,
     * which will try verify the certificate and if verification fails
     * will query the user for acceptance.
     *
     * @param   toHost the host we are connecting.
     * @param   toPort the port used when connecting.
     * @return  the SSLContext
     * @throws IOException throws exception when unable to initialize the
     *  ssl context.
     */
    public SSLContext getSSLContext(String toHost, int toPort)
        throws IOException
    {
        return getSSLContext(
            CertificateVerificationActivator.getResources().
                getI18NString(
                    "service.gui.CERT_DIALOG_DESCRIPTION_TXT",
                    new String[]{
                        CertificateVerificationActivator.getResources()
                            .getSettingsString("service.gui.APPLICATION_NAME"),
                        toHost,
                        Integer.toString(toPort)
                    }
                )
            );
    }

    /**
     * Returns SSLContext instance initialized with the custom trust manager,
     * which will try verify the certificate and if verification fails
     * will query the user for acceptance.
     *
     * @param message The message to show on the verification GUI if necessary
     * @return  the SSLContext
     * @throws IOException throws exception when unable to initialize the
     *  ssl context.
     */
    public SSLContext getSSLContext(String message)
        throws IOException
    {
        try
        {
            KeyStore ks = KeyStore.getInstance(
                    System.getProperty(
                            "javax.net.ssl.keyStoreType",
                            KeyStore.getDefaultType()
                        )
                );
            KeyManagerFactory kmFactory = KeyManagerFactory.getInstance(
                    KeyManagerFactory.getDefaultAlgorithm()
            );

            String keyStorePassword = System.getProperty("javax.net.ssl.keyStorePassword");
            if(System.getProperty("javax.net.ssl.keyStore") != null)
            {
                ks.load(
                        new FileInputStream(System.getProperty("javax.net.ssl.keyStore")),
                        null
                    );
            }
            else
            {
                ks.load(null, null);
            }

            kmFactory.init(
                    ks,
                    keyStorePassword == null ? null : keyStorePassword.toCharArray()
                );

            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(
                    kmFactory.getKeyManagers(),
                    new TrustManager[]{getTrustManager(message)},
                    null
                );

            return sslContext;
        } catch (Exception e)
        {
            throw new IOException("Cannot init SSLContext: " + e.getMessage());
        }
    }

    /**
     * Obtain and if null initialize the keystore.
     * @return the key store with certificates saved in previous sessions.
     */
    private KeyStore getKeyStore()
    {
        if(keyStore == null)
        {
            try
            {
                keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
                synchronized(keyStore)
                {
                    keyStore.load(null, defaultPassword);

                    File keyStoreFile = getKeyStoreLocation();

                    if(!keyStoreFile.exists())
                    {
                        // just store an empty keystore
                        // so the file to be created
                        keyStore.store(
                            new FileOutputStream(keyStoreFile),
                            defaultPassword);
                    }
                    else
                    {
                        keyStore.load(new FileInputStream(keyStoreFile), null);
                    }
                }

            } catch (Exception e)
            {
                logger.error("Cannot init keystore file.", e);
            }
        }

        return keyStore;
    }

    /**
     * The dialog that is shown to user.
     */
    private static class VerifyCertificateDialog
        extends SIPCommDialog
    {
        /**
         * Serial version UID.
         */
        private static final long serialVersionUID = 0L;

        /**
         * Date formatter.
         */
        private static SimpleDateFormat dateFormatter =
            new SimpleDateFormat("MM/dd/yyyy");

        /**
         * Used for converting bytes to HEX.
         */
        private static final String HEXES = "0123456789ABCDEF";

        /**
         * The maximum width that we allow message dialogs to have.
         */
        private static final int MAX_MSG_PANE_WIDTH = 600;

        /**
         * The maximum height that we allow message dialogs to have.
         */
        private static final int MAX_MSG_PANE_HEIGHT = 800;

        /**
         * The certificate to show.
         */
        Certificate cert;

        /**
         * A text that describes why the verification failed.
         */
        String message;

        /**
         * The certificate panel.
         */
        TransparentPanel certPanel;

        /**
         * This dialog content pane.
         */
        TransparentPanel contentPane;

        /**
         * Whether certificate description is shown.
         */
        boolean certOpened = false;

        /**
         * The button to show certificate description.
         */
        JButton certButton;

        /**
         * The check box if checked permanently stored the certificate
         * which will be always trusted.
         */
        SIPCommCheckBox alwaysTrustCheckBox = new SIPCommCheckBox(
            CertificateVerificationActivator.getResources()
                .getI18NString("service.gui.ALWAYS_TRUST"),
            false);

        /**
         * Whether the user trusts this certificate.
         */
        boolean isTrusted = false;

        /**
         * Creates the dialog.
         *
         * @param certs the certificates list
         * @param message A text that describes why the verification failed.
         */
        public VerifyCertificateDialog( Certificate[] certs,
                                        String message)
        {
            super(false);

            setTitle(CertificateVerificationActivator.getResources()
                .getI18NString("service.gui.CERT_DIALOG_TITLE"));
            setModal(true);

            // for now shows only the first certificate from the chain
            this.cert = certs[0];
            this.message = message;

            setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);

            init();

            setLocationRelativeTo(getParent());
        }

        /**
         * Inits the dialog initial display.
         */
        private void init()
        {
            this.getContentPane().setLayout(new BorderLayout());

            contentPane =
                new TransparentPanel(new BorderLayout(5, 5));

            TransparentPanel northPanel =
                new TransparentPanel(new BorderLayout(5, 5));
            northPanel.setBorder(BorderFactory.createEmptyBorder(10, 5, 5, 5));

            JLabel imgLabel = new JLabel(
                CertificateVerificationActivator.getResources().getImage(
                    "impl.media.security.zrtp.CONF_ICON"));
            imgLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
            northPanel.add(imgLabel, BorderLayout.WEST);

            StyledHTMLEditorPane descriptionPane = new StyledHTMLEditorPane();
            descriptionPane.setOpaque(false);
            descriptionPane.setEditable(false);
            descriptionPane.setContentType("text/html");
            descriptionPane.setText(message);
            descriptionPane.setSize(
                        new Dimension(MAX_MSG_PANE_WIDTH, MAX_MSG_PANE_HEIGHT));
            int height = descriptionPane.getPreferredSize().height;
            descriptionPane.setPreferredSize(
                        new Dimension(MAX_MSG_PANE_WIDTH, height));

            northPanel.add(descriptionPane, BorderLayout.CENTER);
            contentPane.add(northPanel, BorderLayout.NORTH);

            certPanel = new TransparentPanel();
            contentPane.add(certPanel, BorderLayout.CENTER);

            TransparentPanel southPanel =
                new TransparentPanel(new BorderLayout());
            contentPane.add(southPanel, BorderLayout.SOUTH);

            certButton = new JButton();
            certButton.setText(CertificateVerificationActivator
                .getResources().getI18NString("service.gui.SHOW_CERT"));
            certButton.addActionListener(new ActionListener() {

                public void actionPerformed(ActionEvent e)
                {
                    actionShowCertificate();
                }
            });
            TransparentPanel firstButonPanel =
                new TransparentPanel(new FlowLayout(FlowLayout.LEFT));
            firstButonPanel.add(certButton);
            southPanel.add(firstButonPanel, BorderLayout.WEST);

            TransparentPanel secondButonPanel =
                new TransparentPanel(new FlowLayout(FlowLayout.RIGHT));
            JButton cancelButton = new JButton(
                CertificateVerificationActivator.getResources()
                    .getI18NString("service.gui.CANCEL"));

            cancelButton.addActionListener(new ActionListener() {

                public void actionPerformed(ActionEvent e)
                {
                    actionCancel();
                }
            });
            JButton continueButton = new JButton(
                CertificateVerificationActivator.getResources()
                    .getI18NString("service.gui.CONTINUE"));

            continueButton.addActionListener(new ActionListener() {

                public void actionPerformed(ActionEvent e)
                {
                    actionContinue();
                }
            });
            secondButonPanel.add(continueButton);
            secondButonPanel.add(cancelButton);
            southPanel.add(secondButonPanel, BorderLayout.EAST);

            this.getContentPane().add(contentPane, BorderLayout.CENTER);

            pack();
        }

        /**
         * Action when shoe certificate button is clicked.
         */
        private void actionShowCertificate()
        {
            if(certOpened)
            {
                certPanel.removeAll();
                certButton.setText(
                    CertificateVerificationActivator.getResources()
                        .getI18NString("service.gui.SHOW_CERT"));

                certPanel.revalidate();
                certPanel.repaint();
                pack();
                certOpened = false;
                setLocationRelativeTo(getParent());
                return;
            }

            certPanel.setLayout(new BorderLayout());
            certPanel.add(alwaysTrustCheckBox, BorderLayout.NORTH);

            Component certInfoPane = null;
            if(cert instanceof X509Certificate)
            {
                certInfoPane = getX509DisplayComponent((X509Certificate)cert);
            }
            else
            {
                JTextArea textArea = new JTextArea();
                textArea.setOpaque(false);
                textArea.setEditable(false);
                textArea.setText(cert.toString());
                certInfoPane = textArea;
            }

            final JScrollPane certScroll = new JScrollPane(certInfoPane);
            certScroll.setPreferredSize(new Dimension(300, 300));
            certPanel.add(certScroll, BorderLayout.CENTER);

            SwingUtilities.invokeLater(new Runnable()
            {
                public void run()
                {
                    certScroll.getVerticalScrollBar().setValue(0);
                }
            });

                certButton.setText(
                    CertificateVerificationActivator.getResources()
                    .getI18NString("service.gui.HIDE_CERT"));

            certPanel.revalidate();
            certPanel.repaint();
            // restore default values for prefered size,
            // as we have resized its components let it calculate
            // that size
            setPreferredSize(null);
            pack();
            certOpened = true;
            setLocationRelativeTo(getParent());
        }

        /**
         * Action when cancel button is clicked.
         */
        private void actionCancel()
        {
            isTrusted = false;
            dispose();
        }

        /**
         * Action when continue is clicked.
         */
        private void actionContinue()
        {
            isTrusted = true;
            dispose();
        }

        /**
         * Called when dialog closed or escape pressed.
         * @param isEscaped is escape button pressed.
         */
        protected void close(boolean isEscaped)
        {
            actionCancel();
        }

        /**
         * Returns the display component for X509 certificate.
         *
         * @param certificate the certificate to show
         * @return the created component
         */
        private static Component getX509DisplayComponent(
            X509Certificate certificate)
        {
            Insets valueInsets = new Insets(2,10,0,0);
            Insets titleInsets = new Insets(10,5,0,0);

            ResourceManagementService resources
                = CertificateVerificationActivator.getResources();

            TransparentPanel certDisplayPanel
                = new TransparentPanel(new GridBagLayout());

            int currentRow = 0;

            GridBagConstraints constraints = new GridBagConstraints();
            constraints.anchor = GridBagConstraints.WEST;
            constraints.fill = GridBagConstraints.HORIZONTAL;
            constraints.insets = new Insets(2,5,0,0);
            constraints.gridx = 0;
            constraints.weightx = 0;
            constraints.weighty = 0;
            constraints.gridy = currentRow++;

            X500Principal issuer = certificate.getIssuerX500Principal();
            X500Principal subject = certificate.getSubjectX500Principal();

            certDisplayPanel.add(new JLabel(
                resources.getI18NString("service.gui.CERT_INFO_ISSUED_TO")),
                constraints);

            constraints.gridy = currentRow++;
            certDisplayPanel.add(new JLabel(
                resources.getI18NString("service.gui.CERT_INFO_CN")),
                constraints);
            constraints.gridx = 1;
            certDisplayPanel.add(
                new JLabel(getCertificateValue(subject.getName(), "CN")),
                constraints);

            constraints.gridy = currentRow++;
            constraints.gridx = 0;
            certDisplayPanel.add(new JLabel(
                resources.getI18NString("service.gui.CERT_INFO_O")),
                constraints);
            constraints.gridx = 1;
            certDisplayPanel.add(
                new JLabel(getCertificateValue(subject.getName(), "O")),
                constraints);

            constraints.gridy = currentRow++;
            constraints.gridx = 0;
            certDisplayPanel.add(new JLabel(
                resources.getI18NString("service.gui.CERT_INFO_C")),
                constraints);
            constraints.gridx = 1;
            certDisplayPanel.add(
                new JLabel(getCertificateValue(subject.getName(), "C")),
                constraints);

            constraints.gridy = currentRow++;
            constraints.gridx = 0;
            certDisplayPanel.add(new JLabel(
                resources.getI18NString("service.gui.CERT_INFO_ST")),
                constraints);
            constraints.gridx = 1;
            certDisplayPanel.add(
                new JLabel(getCertificateValue(subject.getName(), "ST")),
                constraints);

            constraints.gridy = currentRow++;
            constraints.gridx = 0;
            certDisplayPanel.add(new JLabel(
                resources.getI18NString("service.gui.CERT_INFO_L")),
                constraints);
            constraints.gridx = 1;
            certDisplayPanel.add(
                new JLabel(getCertificateValue(subject.getName(), "L")),
                constraints);

            constraints.gridy = currentRow++;
            constraints.gridx = 0;
            constraints.insets = titleInsets;
            certDisplayPanel.add(new JLabel(
                resources.getI18NString("service.gui.CERT_INFO_ISSUED_BY")),
                constraints);
            constraints.insets = valueInsets;

            constraints.gridy = currentRow++;
            constraints.gridx = 0;
            certDisplayPanel.add(new JLabel(
                resources.getI18NString("service.gui.CERT_INFO_C")),
                constraints);
            constraints.gridx = 1;
            certDisplayPanel.add(
                new JLabel(getCertificateValue(issuer.getName(), "C")),
                constraints);

            constraints.gridy = currentRow++;
            constraints.gridx = 0;
            certDisplayPanel.add(new JLabel(
                resources.getI18NString("service.gui.CERT_INFO_O")),
                constraints);
            constraints.gridx = 1;
            certDisplayPanel.add(
                new JLabel(getCertificateValue(issuer.getName(), "O")),
                constraints);

            constraints.gridy = currentRow++;
            constraints.gridx = 0;
            certDisplayPanel.add(new JLabel(
                resources.getI18NString("service.gui.CERT_INFO_OU")),
                constraints);
            constraints.gridx = 1;
            certDisplayPanel.add(
                new JLabel(getCertificateValue(issuer.getName(), "OU")),
                constraints);

            constraints.gridy = currentRow++;
            constraints.gridx = 0;
            constraints.insets = titleInsets;
            certDisplayPanel.add(new JLabel(
                resources.getI18NString("service.gui.CERT_INFO_VALIDITY")),
                constraints);
            constraints.insets = valueInsets;

            constraints.gridy = currentRow++;
            constraints.gridx = 0;
            certDisplayPanel.add(new JLabel(
                resources.getI18NString("service.gui.CERT_INFO_ISSUED_ON")),
                constraints);
            constraints.gridx = 1;
            certDisplayPanel.add(
                new JLabel(dateFormatter.format(certificate.getNotBefore())),
                constraints);

            constraints.gridy = currentRow++;
            constraints.gridx = 0;
            certDisplayPanel.add(new JLabel(
                resources.getI18NString("service.gui.CERT_INFO_EXPIRES_ON")),
                constraints);
            constraints.gridx = 1;
            certDisplayPanel.add(
                new JLabel(dateFormatter.format(certificate.getNotAfter())),
                constraints);

            constraints.gridy = currentRow++;
            constraints.gridx = 0;
            constraints.insets = titleInsets;
            certDisplayPanel.add(new JLabel(
                resources.getI18NString("service.gui.CERT_INFO_FINGERPRINTS")),
                constraints);
            constraints.insets = valueInsets;

            try
            {
                MessageDigest md = MessageDigest.getInstance("SHA1");
                md.update(certificate.getEncoded());
                String sha1String = getHex(md.digest());

                md = MessageDigest.getInstance("MD5");
                md.update(certificate.getEncoded());
                String md5String = getHex(md.digest());

                JTextArea sha1Area = new JTextArea(sha1String);
                sha1Area.setLineWrap(false);
                sha1Area.setOpaque(false);
                sha1Area.setWrapStyleWord(true);
                sha1Area.setEditable(false);

                constraints.gridy = currentRow++;
                constraints.gridx = 0;
                certDisplayPanel.add(new JLabel("SHA1:"),
                    constraints);

                constraints.gridx = 1;
                certDisplayPanel.add(
                    sha1Area,
                    constraints);

                constraints.gridy = currentRow++;
                constraints.gridx = 0;
                certDisplayPanel.add(new JLabel("MD5:"),
                    constraints);

                JTextArea md5Area = new JTextArea(md5String);
                md5Area.setLineWrap(false);
                md5Area.setOpaque(false);
                md5Area.setWrapStyleWord(true);
                md5Area.setEditable(false);

                constraints.gridx = 1;
                certDisplayPanel.add(
                    md5Area,
                    constraints);
            }
            catch (Exception e)
            {
                // do nothing as we cannot show this value
                logger.warn("Error in certificate, cannot show fingerprints", e);
            }

            constraints.gridy = currentRow++;
            constraints.gridx = 0;
            constraints.insets = titleInsets;
            certDisplayPanel.add(new JLabel(
                resources.getI18NString("service.gui.CERT_INFO_CERT_DETAILS")),
                constraints);
            constraints.insets = valueInsets;

            constraints.gridy = currentRow++;
            constraints.gridx = 0;
            certDisplayPanel.add(new JLabel(
                resources.getI18NString("service.gui.CERT_INFO_SER_NUM")),
                constraints);
            constraints.gridx = 1;
            certDisplayPanel.add(
                new JLabel(certificate.getSerialNumber().toString()),
                constraints);

            constraints.gridy = currentRow++;
            constraints.gridx = 0;
            certDisplayPanel.add(new JLabel(
                resources.getI18NString("service.gui.CERT_INFO_VER")),
                constraints);
            constraints.gridx = 1;
            certDisplayPanel.add(
                new JLabel(String.valueOf(certificate.getVersion())),
                constraints);

            constraints.gridy = currentRow++;
            constraints.gridx = 0;
            certDisplayPanel.add(new JLabel(
                resources.getI18NString("service.gui.CERT_INFO_SIGN_ALG")),
                constraints);
            constraints.gridx = 1;
            certDisplayPanel.add(
                new JLabel(String.valueOf(certificate.getSigAlgName())),
                constraints);

            constraints.gridy = currentRow++;
            constraints.gridx = 0;
            constraints.insets = titleInsets;
            certDisplayPanel.add(new JLabel(
                resources.getI18NString("service.gui.CERT_INFO_PUB_KEY_INFO")),
                constraints);
            constraints.insets = valueInsets;

            constraints.gridy = currentRow++;
            constraints.gridx = 0;
            certDisplayPanel.add(new JLabel(
                resources.getI18NString("service.gui.CERT_INFO_ALG")),
                constraints);
            constraints.gridx = 1;
            certDisplayPanel.add(
                new JLabel(certificate.getPublicKey().getAlgorithm()),
                constraints);

            if(certificate.getPublicKey().getAlgorithm().equals("RSA"))
            {
                RSAPublicKey key = (RSAPublicKey)certificate.getPublicKey();

                constraints.gridy = currentRow++;
                constraints.gridx = 0;
                certDisplayPanel.add(new JLabel(
                    resources.getI18NString("service.gui.CERT_INFO_PUB_KEY")),
                    constraints);

                JTextArea pubkeyArea = new JTextArea(
                    resources.getI18NString(
                        "service.gui.CERT_INFO_KEY_BYTES_PRINT",
                        new String[]{
                            String.valueOf(key.getModulus().toByteArray().length - 1),
                            key.getModulus().toString(16)
                        }));
                pubkeyArea.setLineWrap(false);
                pubkeyArea.setOpaque(false);
                pubkeyArea.setWrapStyleWord(true);
                pubkeyArea.setEditable(false);

                constraints.gridx = 1;
                certDisplayPanel.add(
                    pubkeyArea,
                    constraints);

                constraints.gridy = currentRow++;
                constraints.gridx = 0;
                certDisplayPanel.add(new JLabel(
                    resources.getI18NString("service.gui.CERT_INFO_EXP")),
                    constraints);
                constraints.gridx = 1;
                certDisplayPanel.add(
                    new JLabel(key.getPublicExponent().toString()),
                    constraints);

                constraints.gridy = currentRow++;
                constraints.gridx = 0;
                certDisplayPanel.add(new JLabel(
                    resources.getI18NString("service.gui.CERT_INFO_KEY_SIZE")),
                    constraints);
                constraints.gridx = 1;
                certDisplayPanel.add(
                    new JLabel(resources.getI18NString(
                        "service.gui.CERT_INFO_KEY_BITS_PRINT",
                        new String[]{
                            String.valueOf(key.getModulus().bitLength())})),
                    constraints);
            }
            else if(certificate.getPublicKey().getAlgorithm().equals("DSA"))
            {
                DSAPublicKey key =
                    (DSAPublicKey)certificate.getPublicKey();

                constraints.gridy = currentRow++;
                constraints.gridx = 0;
                certDisplayPanel.add(new JLabel("Y:"), constraints);

                JTextArea yArea = new JTextArea(key.getY().toString(16));
                yArea.setLineWrap(false);
                yArea.setOpaque(false);
                yArea.setWrapStyleWord(true);
                yArea.setEditable(false);

                constraints.gridx = 1;
                certDisplayPanel.add(
                    yArea,
                    constraints);
            }

            constraints.gridy = currentRow++;
            constraints.gridx = 0;
            certDisplayPanel.add(new JLabel(
                resources.getI18NString("service.gui.CERT_INFO_SIGN")),
                constraints);

            JTextArea signArea = new JTextArea(
                resources.getI18NString(
                        "service.gui.CERT_INFO_KEY_BYTES_PRINT",
                        new String[]{
                            String.valueOf(certificate.getSignature().length),
                            getHex(certificate.getSignature())
                        }));
            signArea.setLineWrap(false);
            signArea.setOpaque(false);
            signArea.setWrapStyleWord(true);
            signArea.setEditable(false);

            constraints.gridx = 1;
            certDisplayPanel.add(
                signArea,
                constraints);

            return certDisplayPanel;
        }

        /**
         * Extract values from certificate DNs(Distinguished Names).
         * @param rfc2253String the certificate string.
         * @param attributeName the DN attribute name to search for.
         * @return empty string or the found value.
         */
        private static String getCertificateValue(
            String rfc2253String, String attributeName)
        {
            try
            {
                LdapName issuerDN = new LdapName(rfc2253String);
                java.util.List<Rdn> l = issuerDN.getRdns();
                for (int i = 0; i < l.size(); i++)
                {
                    Rdn rdn = l.get(i);
                    if (rdn.getType().equals(attributeName))
                    {
                        return (String) rdn.getValue();
                    }
                }
            }
            catch (InvalidNameException ex)
            {
                // do nothing
                logger.warn("Wrong DN:" + rfc2253String, ex);
            }

            return "";
        }

        /**
         * Converts the byte array to hex string.
         * @param raw the data.
         * @return the hex string.
         */
        public static String getHex( byte [] raw )
        {
            if ( raw == null )
            {
                return null;
            }
            final StringBuilder hex = new StringBuilder( 2 * raw.length );
            for ( final byte b : raw )
            {
                hex.append(HEXES.charAt((b & 0xF0) >> 4))
                    .append(HEXES.charAt((b & 0x0F)));
            }
            return hex.toString();
        }
    }

    /**
     * The trust manager which asks the client whether to trust particular
     * certificate which is not globally trusted.
     */
    private class HostTrustManager
        implements X509TrustManager
    {
        /**
         * A text displayed on the gui that describes why the
         * verification failed.
         */
        String message;

        /**
         * The default trust manager.
         */
        private final X509TrustManager tm;

        /**
         * Creates the custom trust manager.
         * @param tm the default trust manager.
         */
        private HostTrustManager(X509TrustManager tm, String message)
        {
            this.tm = tm;
            this.message = message;
        }

        /**
         * Not used, returns an empty array.
         * @return UnsupportedOperationException
         */
        public X509Certificate[] getAcceptedIssuers()
        {
            return new X509Certificate[]{};
        }

        /**
         * Not used.
         * @param chain the cert chain.
         * @param authType authentication type like: RSA.
         * @throws CertificateException if something went wrong with
         * certificate verification
         */
        public void checkClientTrusted(X509Certificate[] chain, String authType)
            throws CertificateException
        {
            if(CertificateVerificationActivator.getConfigurationService()
                    .getBoolean(CertificateVerificationService
                        .ALWAYS_TRUST_MODE_ENABLED_PROP_NAME,
                        false))
            {
                return;
            }

            try
            {
                tm.checkClientTrusted(chain, authType);
                // everything is fine certificate is globally trusted
            } catch (CertificateException certificateException)
            {
                checkLocalTrust(chain, authType, certificateException);
            }
        }

        /**
         * Check whether a certificate is trusted, if not as user whether he
         * trust it.
         * @param chain the certificate chain.
         * @param authType authentication type like: RSA.
         * @throws CertificateException not trusted.
         */
        public void checkServerTrusted(X509Certificate[] chain, String authType)
            throws CertificateException
        {
            // check and default configurations for property
            // if missing default is null - false
            String defaultAlwaysTrustMode =
                CertificateVerificationActivator.getResources()
                    .getSettingsString(CertificateVerificationService
                        .ALWAYS_TRUST_MODE_ENABLED_PROP_NAME);

            if(CertificateVerificationActivator.getConfigurationService()
                .getBoolean(CertificateVerificationService
                    .ALWAYS_TRUST_MODE_ENABLED_PROP_NAME,
                    Boolean.parseBoolean(defaultAlwaysTrustMode)))
            {
                return;
            }

            try
            {
                tm.checkServerTrusted(chain, authType);
                // everything is fine certificate is globally trusted
            }
            catch (CertificateException certificateException)
            {
                checkLocalTrust(chain, authType, certificateException);
            }
        }
       
        private void checkLocalTrust(X509Certificate[] chain,
                                    String authType,
                                    CertificateException certificateException)
            throws CertificateException
        {
            KeyStore kStore = getKeyStore();

            if(kStore == null)
                throw certificateException;

            try
            {
                for (int i = 0; i < chain.length; i++)
                {
                    X509Certificate c = chain[i];

                    // check for temporaly allowed certs
                    if(temporalyAllowed.contains(c))
                    {
                        return;
                    }

                    // now check for permanent allow of certs
                    String alias = kStore.getCertificateAlias(c);
                    if(alias != null)
                    {
                        return;
                    }
                }

                if(verify(chain, message)
                    == CertificateVerificationService.DO_NOT_TRUST)
                {
                    throw certificateException;
                }
            } catch (Throwable e)
            {
                // something happend
                logger.error("Error trying to " +
                    "show certificate to user", e);

                throw certificateException;
            }
        }
    }
}
TOP

Related Classes of net.java.sip.communicator.impl.certificate.CertificateVerificationServiceImpl$HostTrustManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.