Skip to content

Commit

Permalink
OF-2559 Refactor to remove unused code following Netty migration
Browse files Browse the repository at this point in the history
  • Loading branch information
viv committed Jul 18, 2023
1 parent 516ec0c commit 1dc18ec
Showing 1 changed file with 0 additions and 210 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,38 +18,24 @@

import com.google.common.collect.Interner;
import com.google.common.collect.Interners;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.XMPPPacketReader;
import org.jivesoftware.openfire.*;
import org.jivesoftware.openfire.auth.UnauthorizedException;
import org.jivesoftware.openfire.event.ServerSessionEventDispatcher;
import org.jivesoftware.openfire.net.MXParser;
import org.jivesoftware.openfire.net.SASLAuthentication;
import org.jivesoftware.openfire.net.SocketConnection;
import org.jivesoftware.openfire.net.SocketUtil;
import org.jivesoftware.openfire.nio.NettySessionInitializer;
import org.jivesoftware.openfire.server.OutgoingServerSocketReader;
import org.jivesoftware.openfire.server.RemoteServerManager;
import org.jivesoftware.openfire.server.ServerDialback;
import org.jivesoftware.openfire.spi.BasicStreamIDFactory;
import org.jivesoftware.util.StringUtils;
import org.jivesoftware.util.TaskEngine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmpp.packet.*;

import javax.annotation.Nonnull;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.SocketAddress;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -298,202 +284,6 @@ private static LocalOutgoingServerSession createOutgoingSession(@Nonnull final D
}
}

public static LocalOutgoingServerSession encryptAndAuthenticate(DomainPair domainPair, SocketConnection connection, XMPPPacketReader reader, StringBuilder openingStream) throws Exception {
final Logger log = LoggerFactory.getLogger(Log.getName() + "[Encrypt connection for: " + domainPair + "]" );
Element features;

log.debug( "Encrypting and authenticating connection ...");

log.debug( "Indicating we want TLS and wait for response." );
connection.deliverRawText( "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>" );

MXParser xpp = reader.getXPPParser();
// Wait for the <proceed> response
Element proceed = reader.parseDocument().getRootElement();
if (proceed != null && proceed.getName().equals("proceed")) {
log.debug( "Received 'proceed' from remote server. Negotiating TLS..." );
try {
// boolean needed = JiveGlobals.getBooleanProperty(ConnectionSettings.Server.TLS_CERTIFICATE_VERIFY, true) &&
// JiveGlobals.getBooleanProperty(ConnectionSettings.Server.TLS_CERTIFICATE_CHAIN_VERIFY, true) &&
// !JiveGlobals.getBooleanProperty(ConnectionSettings.Server.TLS_ACCEPT_SELFSIGNED_CERTS, false);
connection.startTLS(true, false);
} catch(Exception e) {
log.debug("TLS negotiation failed: " + e.getMessage());
throw e;
}
log.debug( "TLS negotiation was successful. Connection encrypted. Proceeding with authentication..." );
if (!SASLAuthentication.verifyCertificates(connection.getPeerCertificates(), domainPair.getRemote(), true)) {
if (ServerDialback.isEnabled() || ServerDialback.isEnabledForSelfSigned()) {
log.debug( "SASL authentication failed. Will continue with dialback." );
} else {
log.warn( "Unable to authenticate the connection: SASL authentication failed (and dialback is not available)." );
return null;
}
}

log.debug( "TLS negotiation was successful so initiate a new stream." );
connection.deliverRawText( openingStream.toString() );

// Reset the parser to use the new secured reader
xpp.setInput(new InputStreamReader(connection.getTLSStreamHandler().getInputStream(), StandardCharsets.UTF_8));
// Skip new stream element
for (int eventType = xpp.getEventType(); eventType != XmlPullParser.START_TAG;) {
eventType = xpp.next();
}
// Get the stream ID
String id = xpp.getAttributeValue("", "id");
// Get new stream features
features = reader.parseDocument().getRootElement();
if (features != null) {
return authenticate( domainPair, connection, reader, openingStream, features, id );
}
else {
log.debug( "Failed to encrypt and authenticate connection: neither SASL mechanisms nor SERVER DIALBACK were offered by the remote host." );
return null;
}
}
else {
log.debug( "Failed to encrypt and authenticate connection: <proceed> was not received!" );
return null;
}
}

private static LocalOutgoingServerSession authenticate( final DomainPair domainPair,
final SocketConnection connection,
final XMPPPacketReader reader,
final StringBuilder openingStream,
final Element features,
final String id ) throws DocumentException, IOException, XmlPullParserException
{
final Logger log = LoggerFactory.getLogger(Log.getName() + "[Authenticate connection for: " + domainPair + "]" );

MXParser xpp = reader.getXPPParser();

// Bookkeeping: determine what functionality the remote server offers.
boolean saslEXTERNALoffered = false;
if (features.element("mechanisms") != null) {
Iterator<Element> it = features.element( "mechanisms").elementIterator();
while (it.hasNext()) {
Element mechanism = it.next();
if ("EXTERNAL".equals(mechanism.getTextTrim())) {
saslEXTERNALoffered = true;
break;
}
}
}
final boolean dialbackOffered = features.element("dialback") != null;

log.debug("Remote server is offering dialback: {}, EXTERNAL SASL: {}", dialbackOffered, saslEXTERNALoffered );

LocalOutgoingServerSession result = null;

// first, try SASL
if (saslEXTERNALoffered) {
log.debug( "Trying to authenticate with EXTERNAL SASL." );
result = attemptSASLexternal(connection, xpp, reader, domainPair, id, openingStream);
if (result == null) {
log.debug( "Failed to authenticate with EXTERNAL SASL." );
} else {
log.debug( "Successfully authenticated with EXTERNAL SASL." );
}
}

// SASL unavailable or failed, try dialback.
if (result == null) {
log.debug( "Trying to authenticate with dialback." );
result = attemptDialbackOverTLS(connection, reader, domainPair, id);
if (result == null) {
log.debug( "Failed to authenticate with dialback." );
} else {
log.debug( "Successfully authenticated with dialback." );
}
}

if ( result != null ) {
log.debug( "Successfully encrypted and authenticated connection!" );
return result;
} else {
log.warn( "Unable to encrypt and authenticate connection: Exhausted all options." );
return null;
}
}

private static LocalOutgoingServerSession attemptDialbackOverTLS(Connection connection, XMPPPacketReader reader, DomainPair domainPair, String id) {
final Logger log = LoggerFactory.getLogger( Log.getName() + "[Dialback over TLS for: " + domainPair + " (Stream ID: " + id + ")]" );

if (ServerDialback.isEnabled() || ServerDialback.isEnabledForSelfSigned()) {
log.debug("Trying to connecting using dialback over TLS.");
ServerDialback method = new ServerDialback(connection, domainPair);
OutgoingServerSocketReader newSocketReader = new OutgoingServerSocketReader(reader);
if (method.authenticateDomain(newSocketReader, id)) {
log.debug("Dialback over TLS was successful.");
StreamID streamID = BasicStreamIDFactory.createStreamID(id);
LocalOutgoingServerSession session = new LocalOutgoingServerSession(domainPair.getLocal(), connection, newSocketReader, streamID);
connection.init(session);
// Set the remote domain name as the address of the session.
session.setAddress(new JID(null, domainPair.getRemote(), null));
session.setAuthenticationMethod(AuthenticationMethod.DIALBACK);
return session;
}
else {
log.debug("Dialback over TLS failed");
return null;
}
}
else {
log.debug("Skipping server dialback attempt as it has been disabled by local configuration.");
return null;
}
}

private static LocalOutgoingServerSession attemptSASLexternal(SocketConnection connection, MXParser xpp, XMPPPacketReader reader, DomainPair domainPair, String id, StringBuilder openingStream) throws DocumentException, IOException, XmlPullParserException {
final Logger log = LoggerFactory.getLogger( Log.getName() + "[EXTERNAL SASL for: " + domainPair + " (Stream ID: " + id + ")]" );

log.debug("Starting EXTERNAL SASL.");
if (doExternalAuthentication(domainPair.getLocal(), connection, reader)) {
log.debug("EXTERNAL SASL was successful.");
// SASL was successful so initiate a new stream
connection.deliverRawText(openingStream.toString());

// Reset the parser
//xpp.resetInput();
// // Reset the parser to use the new secured reader
xpp.setInput(new InputStreamReader(connection.getTLSStreamHandler().getInputStream(), StandardCharsets.UTF_8));
// Skip the opening stream sent by the server
for (int eventType = xpp.getEventType(); eventType != XmlPullParser.START_TAG;) {
eventType = xpp.next();
}

// SASL authentication was successful so create new OutgoingServerSession
id = xpp.getAttributeValue("", "id");
StreamID streamID = BasicStreamIDFactory.createStreamID(id);
LocalOutgoingServerSession session = new LocalOutgoingServerSession(domainPair.getLocal(), connection, new OutgoingServerSocketReader(reader), streamID);
connection.init(session);
// Set the remote domain name as the address of the session
session.setAddress(new JID(null, domainPair.getRemote(), null));
// Set that the session was created using TLS+SASL (no server dialback)
session.setAuthenticationMethod(AuthenticationMethod.SASL_EXTERNAL);
return session;
}
else {
log.debug("EXTERNAL SASL failed.");
return null;
}
}

private static boolean doExternalAuthentication(String localDomain, SocketConnection connection,
XMPPPacketReader reader) throws DocumentException, IOException, XmlPullParserException {

StringBuilder sb = new StringBuilder();
sb.append("<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" mechanism=\"EXTERNAL\">");
sb.append(StringUtils.encodeBase64(localDomain));
sb.append("</auth>");
connection.deliverRawText(sb.toString());

Element response = reader.parseDocument().getRootElement();
return response != null && "success".equals(response.getName());
}

public LocalOutgoingServerSession(String localDomain, Connection connection, OutgoingServerSocketReader socketReader, StreamID streamID) {
super(localDomain, connection, streamID);
this.socketReader = socketReader;
Expand Down

0 comments on commit 1dc18ec

Please sign in to comment.