Commit 01eafc87 authored by Gaston Dombiak's avatar Gaston Dombiak Committed by gato

Finished TLS for s2s. JM-395

git-svn-id: http://svn.igniterealtime.org/svn/repos/wildfire/trunk@3253 b35dd754-fafc-0310-a699-88a17e54d16e
parent 75bbf141
......@@ -12,6 +12,7 @@
package org.jivesoftware.wildfire.net;
import org.jivesoftware.wildfire.*;
import org.jivesoftware.wildfire.server.IncomingServerSession;
import org.jivesoftware.wildfire.auth.UnauthorizedException;
import org.jivesoftware.wildfire.interceptor.InterceptorManager;
import org.jivesoftware.wildfire.interceptor.PacketRejectedException;
......@@ -20,6 +21,7 @@ import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.util.Log;
import org.xmpp.packet.Packet;
import javax.net.ssl.SSLSession;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
......@@ -131,15 +133,20 @@ public class SocketConnection implements Connection {
}
/**
* Secures the plain connection by negotiating TLS with the client.
* Secures the plain connection by negotiating TLS with the client. When connecting
* to a remote server then <tt>clientMode</tt> will be <code>true</code> and
* <tt>remoteServer</tt> is the server name of the remote server. Otherwise <tt>clientMode</tt>
* will be <code>false</code> and <tt>remoteServer</tt> null.
*
* @param clientMode boolean indicating if this entity is a client or a server.
* @param remoteServer server name of the remote server we are connecting to or <tt>null</tt>
* when not in client mode.
* @throws IOException if an error occured while securing the connection.
*/
public void startTLS(boolean clientMode) throws IOException {
public void startTLS(boolean clientMode, String remoteServer) throws IOException {
if (!secure) {
secure = true;
tlsStreamHandler = new TLSStreamHandler(socket, clientMode);
tlsStreamHandler = new TLSStreamHandler(socket, clientMode, remoteServer, session instanceof IncomingServerSession);
writer = new BufferedWriter(new OutputStreamWriter(tlsStreamHandler.getOutputStream(), CHARSET));
xmlSerializer = new XMLSocketWriter(writer, this);
}
......@@ -304,6 +311,13 @@ public class SocketConnection implements Connection {
this.flashClient = flashClient;
}
public SSLSession getSSLSession() {
if (tlsStreamHandler != null) {
return tlsStreamHandler.getSSLSession();
}
return null;
}
public void close() {
boolean wasClosed = false;
synchronized (this) {
......
......@@ -670,9 +670,10 @@ public abstract class SocketReader implements Runnable {
connection.deliverRawText("<proceed xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>");
// Negotiate TLS.
try {
connection.startTLS(false);
connection.startTLS(false, null);
}
catch (IOException e) {
Log.error("Error while negotiating TLS", e);
connection.deliverRawText("<failure xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\">");
connection.close();
return false;
......
......@@ -14,6 +14,7 @@ package org.jivesoftware.wildfire.net;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLEngineResult;
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
import javax.net.ssl.SSLSession;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
......@@ -74,14 +75,23 @@ public class TLSStreamHandler {
private static ByteBuffer hsBB = ByteBuffer.allocate(0);
/**
* Creates a new TLSStreamHandler and secures the plain socket connection.
* Creates a new TLSStreamHandler and secures the plain socket connection. When connecting
* to a remote server then <tt>clientMode</tt> will be <code>true</code> and
* <tt>remoteServer</tt> is the server name of the remote server. Otherwise <tt>clientMode</tt>
* will be <code>false</code> and <tt>remoteServer</tt> null.
*
* @param clientMode boolean indicating if this entity is a client or a server.
* @param socket the plain socket connection to secure
* @throws IOException
* @param clientMode boolean indicating if this entity is a client or a server.
* @param remoteServer server name of the remote server we are connecting to or <tt>null</tt>
* when not in client mode.
* @param needClientAuth boolean that indicates if client should authenticate during the TLS
* negotiation. This option is only required when the client is a server since
* EXTERNAL SASL is going to be used.
* @throws java.io.IOException
*/
public TLSStreamHandler(Socket socket, boolean clientMode) throws IOException {
wrapper = new TLSWrapper(clientMode);
public TLSStreamHandler(Socket socket, boolean clientMode, String remoteServer,
boolean needClientAuth) throws IOException {
wrapper = new TLSWrapper(clientMode, needClientAuth, remoteServer);
tlsEngine = wrapper.getTlsEngine();
reader = new TLSStreamReader(wrapper, socket);
writer = new TLSStreamWriter(wrapper, socket);
......@@ -107,6 +117,9 @@ public class TLSStreamHandler {
initialHSStatus = HandshakeStatus.NEED_WRAP;
tlsEngine.beginHandshake();
}
else if (needClientAuth) {
tlsEngine.setNeedClientAuth(true);
}
while (!initialHSComplete) {
initialHSComplete = doHandshake(null);
......@@ -290,4 +303,15 @@ public class TLSStreamHandler {
wbc.close();
rbc.close();
}
/**
* Returns the SSLSession in use. The session specifies a particular cipher suite which
* is being actively used by all connections in that session, as well as the identities
* of the session's client and server.
*
* @return the SSLSession in use.
*/
public SSLSession getSSLSession() {
return tlsEngine.getSession();
}
}
......@@ -11,7 +11,6 @@
package org.jivesoftware.wildfire.net;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Log;
import javax.net.ssl.*;
......@@ -22,7 +21,6 @@ import java.nio.ByteBuffer;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
/**
* Creates and initializes the SSLContext instance to use to secure the plain connection. This
......@@ -57,7 +55,7 @@ public class TLSWrapper {
private int netBuffSize;
private int appBuffSize;
public TLSWrapper(boolean clientMode) {
public TLSWrapper(boolean clientMode, boolean needClientAuth, String remoteServer) {
if (debug) {
System.setProperty("javax.net.debug", "all");
......@@ -77,27 +75,11 @@ public class TLSWrapper {
// TrustManager's decide whether to allow connections.
TrustManager[] tm = SSLJiveTrustManagerFactory.getTrustManagers(ksTrust, trustpass);
boolean verify = JiveGlobals.getBooleanProperty("xmpp.server.certificate.verify", true);
if (clientMode && !verify) {
// Trust any certificate presented by the server. Disabling certificate validation
// is not recommended for production environments.
tm = new TrustManager[]{new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] x509Certificates,
String string) {
if (clientMode || needClientAuth) {
// Check if we can trust certificates presented by the server
tm = new TrustManager[]{new ServerTrustManager(remoteServer, ksTrust)};
}
public void checkServerTrusted(X509Certificate[] x509Certificates,
String string) {
}
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
};
}
SSLContext tlsContext = SSLContext.getInstance(PROTOCOL);
tlsContext.init(km, tm, null);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment