Commit c7c4d7c2 authored by Dave Cridland's avatar Dave Cridland

OF-986 Negotiate TLS in verify-only connections

parent 775be8e4
...@@ -172,7 +172,7 @@ public class TLSStreamHandler { ...@@ -172,7 +172,7 @@ public class TLSStreamHandler {
return writer.getOutputStream(); return writer.getOutputStream();
} }
void start() throws IOException { public void start() throws IOException {
while (!initialHSComplete) { while (!initialHSComplete) {
initialHSComplete = doHandshake(null); initialHSComplete = doHandshake(null);
} }
......
...@@ -27,6 +27,7 @@ import java.io.OutputStreamWriter; ...@@ -27,6 +27,7 @@ import java.io.OutputStreamWriter;
import java.io.Writer; import java.io.Writer;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.Socket; import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
...@@ -43,16 +44,14 @@ import org.jivesoftware.openfire.SessionManager; ...@@ -43,16 +44,14 @@ import org.jivesoftware.openfire.SessionManager;
import org.jivesoftware.openfire.StreamID; import org.jivesoftware.openfire.StreamID;
import org.jivesoftware.openfire.XMPPServer; import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.auth.AuthFactory; import org.jivesoftware.openfire.auth.AuthFactory;
import org.jivesoftware.openfire.net.DNSUtil; import org.jivesoftware.openfire.net.*;
import org.jivesoftware.openfire.net.MXParser;
import org.jivesoftware.openfire.net.SASLAuthentication;
import org.jivesoftware.openfire.net.ServerTrafficCounter;
import org.jivesoftware.openfire.net.SocketConnection;
import org.jivesoftware.openfire.session.ConnectionSettings; import org.jivesoftware.openfire.session.ConnectionSettings;
import org.jivesoftware.openfire.session.IncomingServerSession; import org.jivesoftware.openfire.session.IncomingServerSession;
import org.jivesoftware.openfire.session.LocalIncomingServerSession; import org.jivesoftware.openfire.session.LocalIncomingServerSession;
import org.jivesoftware.openfire.session.LocalOutgoingServerSession; import org.jivesoftware.openfire.session.LocalOutgoingServerSession;
import org.jivesoftware.openfire.spi.BasicStreamIDFactory; import org.jivesoftware.openfire.spi.BasicStreamIDFactory;
import org.jivesoftware.openfire.spi.ConnectionManagerImpl;
import org.jivesoftware.openfire.spi.ConnectionType;
import org.jivesoftware.util.JiveGlobals; import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.StringUtils; import org.jivesoftware.util.StringUtils;
import org.jivesoftware.util.cache.Cache; import org.jivesoftware.util.cache.Cache;
...@@ -638,27 +637,9 @@ public class ServerDialback { ...@@ -638,27 +637,9 @@ public class ServerDialback {
return host_unknown; return host_unknown;
} }
/** private VerifyResult sendVerifyKey(String key, String streamID, String recipient, String hostname, Writer writer, XMPPPacketReader reader, Socket socket) throws IOException, XmlPullParserException, RemoteConnectionFailedException {
* Verifies the key with the Authoritative Server.
*/
private VerifyResult verifyKey(String key, String streamID, String recipient, String hostname,
Socket socket) throws IOException, XmlPullParserException,
RemoteConnectionFailedException {
XMPPPacketReader reader;
Writer writer = null;
// Set a read timeout
socket.setSoTimeout(RemoteServerManager.getSocketTimeout());
VerifyResult result = VerifyResult.error; VerifyResult result = VerifyResult.error;
try { TLSStreamHandler tlsStreamHandler;
reader = new XMPPPacketReader();
reader.setXPPFactory(FACTORY);
reader.getXPPParser().setInput(new InputStreamReader(socket.getInputStream(),
CHARSET));
// Get a writer for sending the open stream tag
writer =
new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(),
CHARSET));
// Send the Authoritative Server a stream header // Send the Authoritative Server a stream header
StringBuilder stream = new StringBuilder(); StringBuilder stream = new StringBuilder();
stream.append("<stream:stream"); stream.append("<stream:stream");
...@@ -686,16 +667,36 @@ public class ServerDialback { ...@@ -686,16 +667,36 @@ public class ServerDialback {
try { try {
doc = reader.parseDocument(); doc = reader.parseDocument();
} catch (DocumentException e) { } catch (DocumentException e) {
// TODO Auto-generated catch block
Log.warn("XML Error!", e); Log.warn("XML Error!", e);
return VerifyResult.error; return VerifyResult.error;
} }
Element features = doc.getRootElement(); Element features = doc.getRootElement();
Element starttls = features.element("starttls"); Element starttls = features.element("starttls");
if (starttls != null) { if (starttls != null) {
if (starttls.element("required") != null) { writer.write("<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>");
Log.error("TLS required for db:verify but cannot yet do this."); writer.flush();
try {
doc = reader.parseDocument();
} catch (DocumentException e) {
Log.warn("XML Error!", e);
return VerifyResult.error;
} }
if (!doc.getRootElement().getName().equals("proceed")) {
Log.warn("Got {} instead of proceed for starttls", doc.getRootElement().getName());
Log.debug("Like this: {}", doc.asXML());
return VerifyResult.error;
}
// Ugly hacks, apparently, copied from SocketConnection.
final ConnectionManagerImpl connectionManager = ((ConnectionManagerImpl) XMPPServer.getInstance().getConnectionManager());
tlsStreamHandler = new TLSStreamHandler(socket, connectionManager.getListener( ConnectionType.SOCKET_S2S, false ).generateConnectionConfiguration(), true);
// Start handshake
tlsStreamHandler.start();
// Use new wrapped writers
writer = new BufferedWriter(new OutputStreamWriter(tlsStreamHandler.getOutputStream(), StandardCharsets.UTF_8));
reader.getXPPParser().setInput(new InputStreamReader(tlsStreamHandler.getInputStream(),
StandardCharsets.UTF_8));
/// Recurses!
return sendVerifyKey(key, streamID, recipient, hostname, writer, reader, socket);
} }
} }
if ("jabber:server:dialback".equals(xpp.getNamespace("db"))) { if ("jabber:server:dialback".equals(xpp.getNamespace("db"))) {
...@@ -773,6 +774,31 @@ public class ServerDialback { ...@@ -773,6 +774,31 @@ public class ServerDialback {
// sent to the Originating Server // sent to the Originating Server
throw new RemoteConnectionFailedException("Invalid namespace"); throw new RemoteConnectionFailedException("Invalid namespace");
} }
return result;
}
/**
* Verifies the key with the Authoritative Server.
*/
private VerifyResult verifyKey(String key, String streamID, String recipient, String hostname,
Socket socket) throws IOException, XmlPullParserException,
RemoteConnectionFailedException {
XMPPPacketReader reader;
Writer writer = null;
// Set a read timeout
socket.setSoTimeout(RemoteServerManager.getSocketTimeout());
VerifyResult result = VerifyResult.error;
try {
reader = new XMPPPacketReader();
reader.setXPPFactory(FACTORY);
reader.getXPPParser().setInput(new InputStreamReader(socket.getInputStream(),
CHARSET));
// Get a writer for sending the open stream tag
writer =
new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(),
CHARSET));
result = sendVerifyKey(key, streamID, recipient, hostname, writer, reader, socket);
} }
finally { finally {
try { try {
......
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