Commit 19a5b349 authored by Gaston Dombiak's avatar Gaston Dombiak Committed by gato

Refactoring work. Exposed SSLSession in Connection and rewrote startTLS to...

Refactoring work. Exposed SSLSession in Connection and rewrote startTLS to accept client authentication mode as a param.

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/trunk@9107 b35dd754-fafc-0310-a699-88a17e54d16e
parent 89cd9f86
......@@ -15,6 +15,7 @@ import org.jivesoftware.openfire.auth.UnauthorizedException;
import org.jivesoftware.openfire.session.LocalSession;
import org.xmpp.packet.Packet;
import javax.net.ssl.SSLSession;
import java.net.UnknownHostException;
/**
......@@ -87,6 +88,13 @@ public interface Connection {
*/
public String getHostName() throws UnknownHostException;
/**
* Returns the underlying {@link SSLSession} for the connection.
*
* @return <tt>null</tt> if no {@link SSLSession} is initialized yet.
*/
public SSLSession getSSLSession();
/**
* Close this session including associated socket connection. The order of
* events for closing the session is:
......@@ -290,9 +298,10 @@ public interface Connection {
* @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 authentication policy to use for authenticating the remote peer.
* @throws Exception if an error occured while securing the connection.
*/
void startTLS(boolean clientMode, String remoteServer) throws Exception;
void startTLS(boolean clientMode, String remoteServer, ClientAuth authentication) throws Exception;
/**
* Adds the compression filter to the connection but only filter incoming traffic. Do not filter
......@@ -349,4 +358,32 @@ public interface Connection {
*/
disabled
}
/**
* Enumeration that specifies if clients should be authenticated (and how) while
* negotiating TLS.
*/
enum ClientAuth {
/**
* No authentication will be performed on the client. Client credentials will not
* be verified while negotiating TLS.
*/
disabled,
/**
* Clients will try to be authenticated. Unlike {@link #needed}, if the client
* chooses not to provide authentication information about itself, the TLS negotiations
* will stop and the connection will be dropped. This option is only useful for
* engines in the server mode.
*/
wanted,
/**
* Clients need to be authenticated. Unlike {@link #wanted}, if the client
* chooses not to provide authentication information about itself, the TLS negotiations
* will continue. This option is only useful for engines in the server mode.
*/
needed
}
}
......@@ -90,4 +90,8 @@ public class ClientStanzaHandler extends StanzaHandler {
packet.setFrom(session.getAddress());
super.processMessage(packet);
}
void startTLS() throws Exception {
connection.startTLS(false, null, Connection.ClientAuth.disabled);
}
}
......@@ -131,4 +131,8 @@ public class MultiplexerStanzaHandler extends StanzaHandler {
}
return false;
}
void startTLS() throws Exception {
connection.startTLS(false, null, Connection.ClientAuth.disabled);
}
}
......@@ -152,7 +152,7 @@ public class SocketConnection implements Connection {
return tlsStreamHandler;
}
public void startTLS(boolean clientMode, String remoteServer) throws IOException {
public void startTLS(boolean clientMode, String remoteServer, ClientAuth authentication) throws IOException {
if (!secure) {
secure = true;
// Prepare for TLS
......
......@@ -69,7 +69,7 @@ abstract class SocketReadingMode {
}
// Client requested to secure the connection using TLS. Negotiate TLS.
try {
socketReader.connection.startTLS(false, null);
socketReader.connection.startTLS(false, null, Connection.ClientAuth.disabled);
}
catch (IOException e) {
Log.error("Error while negotiating TLS: " + socketReader.connection, e);
......
......@@ -43,7 +43,7 @@ public abstract class StanzaHandler {
* The utf-8 charset for decoding and encoding Jabber packet streams.
*/
protected static String CHARSET = "UTF-8";
private Connection connection;
protected Connection connection;
// DANIELE: Indicate if a session is already created
private boolean sessionCreated = false;
......@@ -347,8 +347,9 @@ public abstract class StanzaHandler {
*
* @param doc the DOM element of an unkown type.
* @return true if a received packet has been processed.
* @throws UnauthorizedException if stanza failed to be processed. Connection will be closed.
*/
abstract boolean processUnknowPacket(Element doc);
abstract boolean processUnknowPacket(Element doc) throws UnauthorizedException;
/**
* Tries to secure the connection using TLS. If the connection is secured then reset
......@@ -372,7 +373,7 @@ public abstract class StanzaHandler {
}
// Client requested to secure the connection using TLS. Negotiate TLS.
try {
connection.startTLS(false, null);
startTLS();
}
catch (Exception e) {
Log.error("Error while negotiating TLS", e);
......@@ -383,6 +384,8 @@ public abstract class StanzaHandler {
return true;
}
abstract void startTLS() throws Exception;
/**
* TLS negotiation was successful so open a new stream and offer the new stream features.
* The new stream features will include available SASL mechanisms and specific features
......
......@@ -19,6 +19,7 @@ import org.jivesoftware.openfire.session.Session;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.util.Log;
import javax.net.ssl.SSLSession;
import java.util.HashMap;
import java.util.Map;
......@@ -56,6 +57,11 @@ public abstract class VirtualConnection implements Connection {
return 0;
}
public SSLSession getSSLSession() {
// Ignore
return null;
}
public boolean isClosed() {
if (session == null) {
return closed;
......@@ -108,7 +114,7 @@ public abstract class VirtualConnection implements Connection {
return null;
}
public void startTLS(boolean clientMode, String remoteServer) throws Exception {
public void startTLS(boolean clientMode, String remoteServer, ClientAuth authentication) throws Exception {
//Ignore
}
......
......@@ -34,6 +34,7 @@ import org.xmpp.packet.Packet;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.SSLSession;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
......@@ -134,6 +135,10 @@ public class NIOConnection implements Connection {
return ((InetSocketAddress) ioSession.getRemoteAddress()).getAddress().getHostName();
}
public SSLSession getSSLSession() {
return (SSLSession) ioSession.getAttribute(SSLFilter.SSL_SESSION);
}
public PacketDeliverer getPacketDeliverer() {
return backupDeliverer;
}
......@@ -272,7 +277,7 @@ public class NIOConnection implements Connection {
}
}
public void startTLS(boolean clientMode, String remoteServer) throws Exception {
public void startTLS(boolean clientMode, String remoteServer, ClientAuth authentication) throws Exception {
KeyStore ksKeys = SSLConfig.getKeyStore();
String keypass = SSLConfig.getKeyPassword();
......@@ -284,9 +289,7 @@ public class NIOConnection implements Connection {
// TrustManager's decide whether to allow connections.
TrustManager[] tm = SSLJiveTrustManagerFactory.getTrustManagers(ksTrust, trustpass);
// TODO Set proper value when s2s is supported
boolean needClientAuth = false;
if (clientMode || needClientAuth) {
if (clientMode || authentication == ClientAuth.needed || authentication == ClientAuth.wanted) {
// Check if we can trust certificates presented by the server
tm = new TrustManager[]{new ServerTrustManager(remoteServer, ksTrust)};
}
......@@ -297,21 +300,14 @@ public class NIOConnection implements Connection {
SSLFilter filter = new SSLFilter(tlsContext);
filter.setUseClientMode(clientMode);
if (needClientAuth) {
// Only REQUIRE client authentication if we are fully verifying certificates
if (JiveGlobals.getBooleanProperty("xmpp.server.certificate.verify", true) &&
JiveGlobals.getBooleanProperty("xmpp.server.certificate.verify.chain", true) &&
!JiveGlobals
.getBooleanProperty("xmpp.server.certificate.accept-selfsigned", false))
{
filter.setNeedClientAuth(true);
}
else {
// Just indicate that we would like to authenticate the client but if client
// certificates are self-signed or have no certificate chain then we are still
// good
filter.setWantClientAuth(true);
}
if (authentication == ClientAuth.needed) {
filter.setNeedClientAuth(true);
}
else if (authentication == ClientAuth.wanted) {
// Just indicate that we would like to authenticate the client but if client
// certificates are self-signed or have no certificate chain then we are still
// good
filter.setWantClientAuth(true);
}
// TODO Temporary workaround (placing SSLFilter before ExecutorFilter) to avoid deadlock. Waiting for
// MINA devs feedback
......
......@@ -363,7 +363,10 @@ public class LocalOutgoingServerSession extends LocalSession implements Outgoing
Element proceed = reader.parseDocument().getRootElement();
if (proceed != null && proceed.getName().equals("proceed")) {
Log.debug("OS - Negotiating TLS with " + hostname);
connection.startTLS(true, hostname);
boolean needed = JiveGlobals.getBooleanProperty("xmpp.server.certificate.verify", true) &&
JiveGlobals.getBooleanProperty("xmpp.server.certificate.verify.chain", true) &&
!JiveGlobals.getBooleanProperty("xmpp.server.certificate.accept-selfsigned", false);
connection.startTLS(true, hostname, needed ? Connection.ClientAuth.needed : Connection.ClientAuth.wanted);
Log.debug("OS - TLS negotiation with " + hostname + " was successful");
// TLS negotiation was successful so initiate a new stream
......
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