Commit 4c528c9d authored by Dave Cridland's avatar Dave Cridland

Support Dialback Without Dialback

When processing a <db:result/>, this checks for the certificate first. If
this matches, then we don't bother actually dialling back, speeding up the
session setup.

This factors out the certificate verification function.
parent 026c3f2f
...@@ -528,29 +528,14 @@ public class SASLAuthentication { ...@@ -528,29 +528,14 @@ public class SASLAuthentication {
if (!verify) { if (!verify) {
authenticationSuccessful(session, hostname, null); authenticationSuccessful(session, hostname, null);
return Status.authenticated; return Status.authenticated;
} } else if(verifyCertificates(session.getConnection().getPeerCertificates(), hostname)) {
// Check that hostname matches the one provided in a certificate authenticationSuccessful(session, hostname, null);
Connection connection = session.getConnection(); LocalIncomingServerSession s = (LocalIncomingServerSession)session;
try { if (s != null) {
X509Certificate trusted = CertificateManager.getEndEntityCertificate(connection.getPeerCertificates(), SSLConfig.getKeyStore(), SSLConfig.gets2sTrustStore()); s.tlsAuth();
if (trusted != null) {
for (String identity : CertificateManager.getPeerIdentities(trusted)) {
// Verify that either the identity is the same as the hostname, or for wildcarded
// identities that the hostname ends with .domainspecified or -is- domainspecified.
if ((identity.startsWith("*.")
&& (hostname.endsWith(identity.replace("*.", "."))
|| hostname.equals(identity.replace("*.", ""))))
|| hostname.equals(identity)) {
authenticationSuccessful(session, hostname, null);
return Status.authenticated;
}
}
} }
} catch(IOException e) { return Status.authenticated;
/// Keystore problem.
} }
} }
else if (session instanceof LocalClientSession) { else if (session instanceof LocalClientSession) {
// Client EXTERNALL login // Client EXTERNALL login
...@@ -618,6 +603,28 @@ public class SASLAuthentication { ...@@ -618,6 +603,28 @@ public class SASLAuthentication {
return Status.failed; return Status.failed;
} }
public static boolean verifyCertificates(Certificate[] chain, String hostname) {
try {
X509Certificate trusted = CertificateManager.getEndEntityCertificate(chain, SSLConfig.getKeyStore(), SSLConfig.gets2sTrustStore());
if (trusted != null) {
for (String identity : CertificateManager.getPeerIdentities(trusted)) {
// Verify that either the identity is the same as the hostname, or for wildcarded
// identities that the hostname ends with .domainspecified or -is- domainspecified.
if ((identity.startsWith("*.")
&& (hostname.endsWith(identity.replace("*.", "."))
|| hostname.equals(identity.replace("*.", ""))))
|| hostname.equals(identity)) {
return true;
}
}
}
} catch(IOException e) {
Log.warn("Keystore issue while verifying certificate chain: {}", e.getMessage());
}
return false;
}
private static Status doSharedSecretAuthentication(LocalSession session, Element doc) private static Status doSharedSecretAuthentication(LocalSession session, Element doc)
throws UnsupportedEncodingException throws UnsupportedEncodingException
{ {
...@@ -686,6 +693,7 @@ public class SASLAuthentication { ...@@ -686,6 +693,7 @@ public class SASLAuthentication {
// Add the validated domain as a valid domain. The remote server can // Add the validated domain as a valid domain. The remote server can
// now send packets from this address // now send packets from this address
((LocalIncomingServerSession) session).addValidatedDomain(hostname); ((LocalIncomingServerSession) session).addValidatedDomain(hostname);
Log.info("Inbound Server {} authenticated (via TLS)", username);
} }
} }
......
...@@ -44,6 +44,7 @@ import org.jivesoftware.openfire.XMPPServer; ...@@ -44,6 +44,7 @@ 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.DNSUtil;
import org.jivesoftware.openfire.net.MXParser; import org.jivesoftware.openfire.net.MXParser;
import org.jivesoftware.openfire.net.SASLAuthentication;
import org.jivesoftware.openfire.net.ServerTrafficCounter; import org.jivesoftware.openfire.net.ServerTrafficCounter;
import org.jivesoftware.openfire.net.SocketConnection; import org.jivesoftware.openfire.net.SocketConnection;
import org.jivesoftware.openfire.session.ConnectionSettings; import org.jivesoftware.openfire.session.ConnectionSettings;
...@@ -534,15 +535,23 @@ public class ServerDialback { ...@@ -534,15 +535,23 @@ public class ServerDialback {
} }
} }
if (alreadyExists && !sessionManager.isMultipleServerConnectionsAllowed()) { if (alreadyExists && !sessionManager.isMultipleServerConnectionsAllowed()) {
// Remote server already has a IncomingServerSession created dialbackError(recipient, hostname, new PacketError(PacketError.Condition.resource_constraint, PacketError.Type.cancel, "Incoming session already exists"));
connection.deliverRawText(
new StreamError(StreamError.Condition.not_authorized).toXML());
// Close the underlying connection
connection.close();
Log.debug("ServerDialback: RS - Error, incoming connection already exists from: " + hostname); Log.debug("ServerDialback: RS - Error, incoming connection already exists from: " + hostname);
return false; return false;
} }
else { else {
if (SASLAuthentication.verifyCertificates(connection.getPeerCertificates(), hostname)) {
// If the remote host passes strong auth, just skip the dialback.
Log.debug("ServerDialback: RS - Sending key verification result to OS: " + hostname);
sb = new StringBuilder();
sb.append("<db:result");
sb.append(" from=\"").append(recipient).append("\"");
sb.append(" to=\"").append(hostname).append("\"");
sb.append(" type=\"valid\"");
sb.append("/>");
connection.deliverRawText(sb.toString());
return true;
}
String key = doc.getTextTrim(); String key = doc.getTextTrim();
// Get a list of real hostnames and try to connect using DNS lookup of the specified domain // Get a list of real hostnames and try to connect using DNS lookup of the specified domain
......
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