String recipient = doc.attributeValue("to");
String hostname = doc.attributeValue("from");
Log.debug("ServerDialback: RS - Received dialback key from host: " + hostname + " to: " + recipient);
if (!RemoteServerManager.canAccess(hostname)) {
// Remote server is not allowed to establish a connection to this server
connection.deliverRawText(new StreamError(StreamError.Condition.host_unknown).toXML());
// Close the underlying connection
connection.close();
Log.debug("ServerDialback: RS - Error, hostname is not allowed to establish a connection to " +
"this server: " +
recipient);
return false;
}
else if (isHostUnknown(recipient)) {
// address does not match a recognized hostname
connection.deliverRawText(new StreamError(StreamError.Condition.host_unknown).toXML());
// Close the underlying connection
connection.close();
Log.debug("ServerDialback: RS - Error, hostname not recognized: " + recipient);
return false;
}
else {
// Check if the remote server already has a connection to the target domain/subdomain
boolean alreadyExists = false;
for (IncomingServerSession session : sessionManager.getIncomingServerSessions(hostname)) {
if (recipient.equals(session.getLocalDomain())) {
alreadyExists = true;
}
}
if (alreadyExists && !sessionManager.isMultipleServerConnectionsAllowed()) {
// Remote server already has a IncomingServerSession created
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);
return false;
}
else {
String key = doc.getTextTrim();
// Get a list of real hostnames and try to connect using DNS lookup of the specified domain
List<DNSUtil.HostAddress> hosts = DNSUtil.resolveXMPPDomain(hostname,
RemoteServerManager.getPortForServer(hostname));
Socket socket = new Socket();
String realHostname = null;
int realPort;
for (Iterator<DNSUtil.HostAddress> it = hosts.iterator(); it.hasNext();) {
try {
DNSUtil.HostAddress address = it.next();
realHostname = address.getHost();
realPort = address.getPort();
Log.debug("ServerDialback: RS - Trying to connect to Authoritative Server: " + hostname +
"(DNS lookup: " + realHostname + ":" + realPort + ")");
// Establish a TCP connection to the Receiving Server
socket.connect(new InetSocketAddress(realHostname, realPort),
RemoteServerManager.getSocketTimeout());
Log.debug("ServerDialback: RS - Connection to AS: " + hostname + " successful");
break;
}
catch (Exception e) {
Log.warn("Error trying to connect to remote server: " + hostname +
"(DNS lookup: " + realHostname + ")", e);
}
}
if (!socket.isConnected()) {
Log.warn("No server available for verifying key of remote server: " + hostname);
return false;
}
try {
boolean valid = verifyKey(key, streamID.toString(), recipient, hostname, socket);
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=\"");
sb.append(valid ? "valid" : "invalid");
sb.append("\"/>");
connection.deliverRawText(sb.toString());
if (!valid) {
// Close the underlying connection
connection.close();
}
return valid;
}
catch (Exception e) {
Log.warn("Error verifying key of remote server: " + hostname, e);
// Send a <remote-connection-failed/> stream error condition
// and terminate both the XML stream and the underlying
// TCP connection
connection.deliverRawText(new StreamError(
StreamError.Condition.remote_connection_failed).toXML());
// Close the underlying connection
connection.close();
return false;
}