Merge pull request #20 from netmackan/tls-3

Show TLS connection info in call info window and logging on connecting
fix-message-formatting
Ingo Bauersachs 12 years ago
commit c3fd4136e5

@ -648,6 +648,12 @@ service.gui.callinfo.IS_CONFERENCE_FOCUS=Conference focus
service.gui.callinfo.IS_DEFAULT_ENCRYPTED=Encryption enabled
service.gui.callinfo.CALL_TRANSPORT=Signalling call transport
service.gui.callinfo.CALL_DURATION=Call duration
service.gui.callinfo.TLS_PROTOCOL=TLS protocol
service.gui.callinfo.TLS_CIPHER_SUITE=TLS cipher suite
service.gui.callinfo.TLS_SERVER_CERTIFICATE_CHAIN=TLS server certificate chain
service.gui.callinfo.TLS_CERTIFICATE_CONTENT=The content of the TLS server \
certificate is displayed below.
service.gui.callinfo.VIEW_CERTIFICATE=View certificate
service.gui.callinfo.CODEC=Codec / Frequency
service.gui.callinfo.NA=N.A.
service.gui.callinfo.VIDEO_SIZE=Video size

@ -27,6 +27,8 @@
import org.jitsi.util.*;
import com.explodingpixels.macwidgets.*;
import java.security.cert.*;
import javax.swing.event.*;
/**
* The frame displaying the statistical information for a telephony conference.
@ -36,7 +38,8 @@
*/
public class CallInfoFrame
implements CallTitleListener,
PropertyChangeListener
PropertyChangeListener,
HyperlinkListener
{
/**
* The telephony conference to compute and display the statistics of.
@ -69,6 +72,11 @@ public class CallInfoFrame
*/
private boolean hasCallInfo;
/**
* Dummy URL to indicate that the certificate should be displayed.
*/
private final String CERTIFICATE_URL = "jitsi://viewCertificate";
/**
* Creates a new frame containing the statistical information for a specific
* telephony conference.
@ -156,6 +164,7 @@ private JEditorPane createGeneralInfoPane()
infoTextPane.setOpaque(false);
infoTextPane.setEditable(false);
infoTextPane.setContentType("text/html");
infoTextPane.addHyperlinkListener(this);
return infoTextPane;
}
@ -235,6 +244,27 @@ private boolean constructCallInfo()
resources.getI18NString("service.gui.callinfo.CALL_TRANSPORT"),
preferredTransport.toString()));
final OperationSetTLS opSetTls = aCall.getProtocolProvider()
.getOperationSet(OperationSetTLS.class);
if (opSetTls != null)
{
stringBuffer.append(getLineString(
resources.getI18NString(
"service.gui.callinfo.TLS_PROTOCOL"),
opSetTls.getProtocol()));
stringBuffer.append(getLineString(
resources.getI18NString(
"service.gui.callinfo.TLS_CIPHER_SUITE"),
opSetTls.getCipherSuite()));
stringBuffer.append("<b><a href=\"")
.append(CERTIFICATE_URL)
.append("\">")
.append(resources.getI18NString(
"service.gui.callinfo.VIEW_CERTIFICATE"))
.append("</a></b><br/>");
}
constructCallPeersInfo(stringBuffer);
stringBuffer.append("</font></p></body></html>");
@ -805,4 +835,31 @@ private String videoSizeToString(Dimension videoSize)
}
return ((int) videoSize.getWidth()) + " x " + ((int) videoSize.getHeight());
}
/**
* Invoked when user clicks a link in the editor pane.
* @param e the event
*/
public void hyperlinkUpdate(HyperlinkEvent e)
{
// Handle "View certificate" link
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED
&& CERTIFICATE_URL.equals(e.getDescription()))
{
List<Call> calls = callConference.getCalls();
if (!calls.isEmpty())
{
Call aCall = calls.get(0);
Certificate[] chain = aCall.getProtocolProvider()
.getOperationSet(OperationSetTLS.class)
.getServerCertificates();
ViewCertificateFrame certFrame =
new ViewCertificateFrame(chain, null,
resources.getI18NString(
"service.gui.callinfo.TLS_CERTIFICATE_CONTENT"));
certFrame.setVisible(true);
}
}
}
}

@ -0,0 +1,157 @@
/*
* Jitsi, 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.gui.main.call;
import java.awt.*;
import java.security.cert.*;
import javax.swing.*;
import net.java.sip.communicator.plugin.desktoputil.*;
import org.jitsi.service.resources.*;
/**
* Frame for showing information about a certificate.
*/
public class ViewCertificateFrame
extends SIPCommFrame
{
/**
* Serial version UID.
*/
private static final long serialVersionUID = 0L;
/**
* The resource service.
*/
private final ResourceManagementService R = DesktopUtilActivator.getResources();
/**
* 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;
/**
* Creates the dialog.
*
* @param certs the certificates list
* @param title The title of the dialog; when null the resource
* <tt>service.gui.CERT_DIALOG_TITLE</tt> is loaded.
* @param message A text that describes why the verification failed.
*/
public ViewCertificateFrame(Certificate[] certs,
String title, String message)
{
super(false);
setTitle(title != null ? title :
R.getI18NString("service.gui.CERT_DIALOG_TITLE"));
// 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(
R.getImage("service.gui.icons.CERTIFICATE_WARNING"));
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(new BorderLayout());
contentPane.add(certPanel, BorderLayout.CENTER);
this.getContentPane().add(contentPane, BorderLayout.CENTER);
Component certInfoPane;
if(cert instanceof X509Certificate)
{
certInfoPane = new X509CertificatePanel((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, 600));
certPanel.add(certScroll, BorderLayout.CENTER);
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
certScroll.getVerticalScrollBar().setValue(0);
}
});
setPreferredSize(null);
pack();
}
}

@ -0,0 +1,90 @@
/*
* Jitsi, 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.protocol.jabber;
import java.security.cert.*;
import javax.net.ssl.*;
import net.java.sip.communicator.service.protocol.*;
/**
* An implementation of the OperationSetTLS for the Jabber protocol.
*
* @author Markus Kilås
*/
public class OperationSetTLSJabberImpl
implements OperationSetTLS
{
private final ProtocolProviderServiceJabberImpl jabberService;
public OperationSetTLSJabberImpl(
ProtocolProviderServiceJabberImpl jabberService)
{
this.jabberService = jabberService;
}
/**
* @see OperationSetTLS#getCipherSuite()
*/
@Override
public String getCipherSuite()
{
final String result;
final SSLSocket socket = jabberService.getSSLSocket();
if (socket == null)
{
result = null;
}
else
{
result = socket.getSession().getCipherSuite();
}
return result;
}
/**
* @see OperationSetTLS#getProtocol()
*/
@Override
public String getProtocol()
{
final String result;
final SSLSocket socket = jabberService.getSSLSocket();
if (socket == null)
{
result = null;
}
else
{
result = socket.getSession().getProtocol();
}
return result;
}
/**
* @see OperationSetTLS#getServerCertificates()
*/
@Override
public Certificate[] getServerCertificates()
{
Certificate[] result = null;
final SSLSocket socket = jabberService.getSSLSocket();
if (socket != null)
{
try
{
result = socket.getSession().getPeerCertificates();
}
catch (SSLPeerUnverifiedException ignored) // NOPMD
{
// result will be null
}
}
return result;
}
}

@ -1154,6 +1154,32 @@ private ConnectState connectAndLogin(
{
SSLContext sslContext = loginStrategy.createSslContext(cvs,
getTrustManager(cvs, serviceName));
// log SSL/TLS algorithms and protocols
if (logger.isDebugEnabled())
{
final StringBuilder buff = new StringBuilder();
buff.append("Available TLS protocols and algorithms:\n");
buff.append("Default protocols: ");
buff.append(Arrays.toString(
sslContext.getDefaultSSLParameters().getProtocols()));
buff.append("\n");
buff.append("Supported protocols: ");
buff.append(Arrays.toString(
sslContext.getSupportedSSLParameters().getProtocols()));
buff.append("\n");
buff.append("Default cipher suites: ");
buff.append(Arrays.toString(
sslContext.getDefaultSSLParameters()
.getCipherSuites()));
buff.append("\n");
buff.append("Supported cipher suites: ");
buff.append(Arrays.toString(
sslContext.getSupportedSSLParameters()
.getCipherSuites()));
logger.debug(buff.toString());
}
connection.setCustomSslContext(sslContext);
}
else if (tlsRequired)
@ -1220,6 +1246,35 @@ else if (tlsRequired)
}
else
{
if (connection.getSocket() instanceof SSLSocket)
{
final SSLSocket sslSocket = (SSLSocket) connection.getSocket();
StringBuilder buff = new StringBuilder();
buff.append("Chosen TLS protocol and algorithm:\n")
.append("Protocol: ").append(sslSocket.getSession()
.getProtocol()).append("\n")
.append("Cipher suite: ").append(sslSocket.getSession()
.getCipherSuite());
logger.info(buff.toString());
if (logger.isDebugEnabled())
{
buff = new StringBuilder();
buff.append("Server TLS certificate chain:\n");
try
{
buff.append(Arrays.toString(
sslSocket.getSession().getPeerCertificates()));
}
catch (SSLPeerUnverifiedException ex)
{
buff.append("<unavailable: ")
.append(ex.getLocalizedMessage()).append(">");
}
logger.debug(buff.toString());
}
}
connection.addConnectionListener(connectionListener);
}
@ -1859,6 +1914,11 @@ protected void initialize(String screenname,
new OperationSetUserSearchJabberImpl(this));
}
OperationSetTLS opsetTLS
= new OperationSetTLSJabberImpl(this);
addSupportedOperationSet(OperationSetTLS.class,
opsetTLS);
isInitialized = true;
}
}
@ -2867,4 +2927,24 @@ private static void loadJabberServiceClasses()
logger.error("Error loading classes in smack", e);
}
}
/**
* Return the SSL socket (if TLS used).
* @return The SSL socket or null if not used
*/
public SSLSocket getSSLSocket()
{
final SSLSocket result;
final Socket socket = connection.getSocket();
if (socket instanceof SSLSocket)
{
result = (SSLSocket) socket;
}
else
{
result = null;
}
return result;
}
}

@ -0,0 +1,43 @@
/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.service.protocol;
import java.security.cert.*;
/**
* An <tt>OperationSet</tt> that allows access to information about TLS used by
* the protocol provider.
*
* @author Markus Kilås
*/
public interface OperationSetTLS
extends OperationSet
{
/**
* Returns the negotiated cipher suite
*
* @return The cipher suite name used for instance
* "TLS_RSA_WITH_AES_256_CBC_SHA" or null if TLS is not used.
*/
String getCipherSuite();
/**
* Returns the negotiated SSL/TLS protocol.
*
* @return The protocol name used for instance "TLSv1".
*/
String getProtocol();
/**
* Returns the TLS server certificate chain with the end entity certificate
* in the first position and the issuers following (if any returned by the
* server).
*
* @return The TLS server certificate chain.
*/
Certificate[] getServerCertificates();
}
Loading…
Cancel
Save