📄 localoutgoingserversession.java
字号:
}
// A session already exists so authenticate the domain using that session
return session.authenticateSubdomain(domain, hostname);
}
catch (Exception e) {
Log.error("Error authenticating domain with remote server: " + hostname, e);
}
return false;
}
/**
* Establishes a new outgoing session to a remote server. If the remote server supports TLS
* and SASL then the new outgoing connection will be secured with TLS and authenticated
* using SASL. However, if TLS or SASL is not supported by the remote server or if an
* error occured while securing or authenticating the connection using SASL then server
* dialback method will be used.
*
* @param domain the local domain to authenticate with the remote server.
* @param hostname the hostname of the remote server.
* @param port default port to use to establish the connection.
* @return new outgoing session to a remote server.
*/
private static LocalOutgoingServerSession createOutgoingSession(String domain, String hostname,
int port) {
boolean useTLS = JiveGlobals.getBooleanProperty("xmpp.server.tls.enabled", true);
RemoteServerConfiguration configuration = RemoteServerManager.getConfiguration(hostname);
if (configuration != null) {
// TODO Use the specific TLS configuration for this remote server
//useTLS = configuration.isTLSEnabled();
}
if (useTLS) {
// Connect to remote server using TLS + SASL
SocketConnection connection = null;
String realHostname = null;
int realPort = port;
Socket socket = new Socket();
try {
// Get the real hostname to connect to using DNS lookup of the specified hostname
DNSUtil.HostAddress address = DNSUtil.resolveXMPPServerDomain(hostname, port);
realHostname = address.getHost();
realPort = address.getPort();
Log.debug("LocalOutgoingServerSession: OS - Trying to connect to " + hostname + ":" + port +
"(DNS lookup: " + realHostname + ":" + realPort + ")");
// Establish a TCP connection to the Receiving Server
socket.connect(new InetSocketAddress(realHostname, realPort),
RemoteServerManager.getSocketTimeout());
Log.debug("LocalOutgoingServerSession: OS - Plain connection to " + hostname + ":" + port + " successful");
}
catch (Exception e) {
Log.error("Error trying to connect to remote server: " + hostname +
"(DNS lookup: " + realHostname + ":" + realPort + ")", e);
return null;
}
try {
connection =
new SocketConnection(XMPPServer.getInstance().getPacketDeliverer(), socket,
false);
// Send the stream header
StringBuilder openingStream = new StringBuilder();
openingStream.append("<stream:stream");
openingStream.append(" xmlns:stream=\"http://etherx.jabber.org/streams\"");
openingStream.append(" xmlns=\"jabber:server\"");
openingStream.append(" to=\"").append(hostname).append("\"");
openingStream.append(" version=\"1.0\">");
connection.deliverRawText(openingStream.toString());
// Set a read timeout (of 5 seconds) so we don't keep waiting forever
int soTimeout = socket.getSoTimeout();
socket.setSoTimeout(5000);
XMPPPacketReader reader = new XMPPPacketReader();
reader.getXPPParser().setInput(new InputStreamReader(socket.getInputStream(),
CHARSET));
// Get the answer from the Receiving Server
XmlPullParser xpp = reader.getXPPParser();
for (int eventType = xpp.getEventType(); eventType != XmlPullParser.START_TAG;) {
eventType = xpp.next();
}
String serverVersion = xpp.getAttributeValue("", "version");
// Check if the remote server is XMPP 1.0 compliant
if (serverVersion != null && decodeVersion(serverVersion)[0] >= 1) {
// Restore default timeout
socket.setSoTimeout(soTimeout);
// Get the stream features
Element features = reader.parseDocument().getRootElement();
// Check if TLS is enabled
if (features != null && features.element("starttls") != null) {
// Secure the connection with TLS and authenticate using SASL
LocalOutgoingServerSession answer;
answer = secureAndAuthenticate(hostname, connection, reader, openingStream,
domain);
if (answer != null) {
// Everything went fine so return the secured and
// authenticated connection
return answer;
}
}
else {
Log.debug("LocalOutgoingServerSession: OS - Error, <starttls> was not received");
}
}
// Something went wrong so close the connection and try server dialback over
// a plain connection
if (connection != null) {
connection.close();
}
}
catch (SSLHandshakeException e) {
Log.debug("LocalOutgoingServerSession: Handshake error while creating secured outgoing session to remote " +
"server: " + hostname + "(DNS lookup: " + realHostname + ":" + realPort +
")", e);
// Close the connection
if (connection != null) {
connection.close();
}
}
catch (XmlPullParserException e) {
Log.warn("Error creating secured outgoing session to remote server: " + hostname +
"(DNS lookup: " + realHostname + ":" + realPort + ")", e);
// Close the connection
if (connection != null) {
connection.close();
}
}
catch (Exception e) {
Log.error("Error creating secured outgoing session to remote server: " + hostname +
"(DNS lookup: " + realHostname + ":" + realPort + ")", e);
// Close the connection
if (connection != null) {
connection.close();
}
}
}
if (ServerDialback.isEnabled()) {
Log.debug("LocalOutgoingServerSession: OS - Going to try connecting using server dialback with: " + hostname);
// Use server dialback over a plain connection
return new ServerDialback().createOutgoingSession(domain, hostname, port);
}
return null;
}
private static LocalOutgoingServerSession secureAndAuthenticate(String hostname,
SocketConnection connection, XMPPPacketReader reader, StringBuilder openingStream,
String domain) throws Exception {
Element features;
Log.debug("LocalOutgoingServerSession: OS - Indicating we want TLS to " + hostname);
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("LocalOutgoingServerSession: OS - Negotiating TLS with " + 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("LocalOutgoingServerSession: OS - TLS negotiation with " + hostname + " was successful");
// 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(),
CHARSET));
// Skip new stream element
for (int eventType = xpp.getEventType(); eventType != XmlPullParser.START_TAG;) {
eventType = xpp.next();
}
// Get new stream features
features = reader.parseDocument().getRootElement();
if (features != null && features.element("mechanisms") != null) {
// Check if we can use stream compression
String policyName = JiveGlobals.getProperty("xmpp.server.compression.policy",
Connection.CompressionPolicy.disabled.toString());
Connection.CompressionPolicy compressionPolicy =
Connection.CompressionPolicy.valueOf(policyName);
if (Connection.CompressionPolicy.optional == compressionPolicy) {
// Verify if the remote server supports stream compression
Element compression = features.element("compression");
if (compression != null) {
boolean zlibSupported = false;
Iterator it = compression.elementIterator("method");
while (it.hasNext()) {
Element method = (Element) it.next();
if ("zlib".equals(method.getTextTrim())) {
zlibSupported = true;
}
}
if (zlibSupported) {
// Request Stream Compression
connection.deliverRawText("<compress xmlns='http://jabber.org/protocol/compress'><method>zlib</method></compress>");
// Check if we are good to start compression
Element answer = reader.parseDocument().getRootElement();
if ("compressed".equals(answer.getName())) {
// Server confirmed that we can use zlib compression
connection.addCompression();
connection.startCompression();
Log.debug("LocalOutgoingServerSession: OS - Stream compression was successful with " + hostname);
// Stream compression was successful so initiate a new stream
connection.deliverRawText(openingStream.toString());
// Reset the parser to use stream compression over TLS
ZInputStream in = new ZInputStream(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -