📄 serverdialback.java
字号:
/**
* Authenticates the Originating Server domain with the Receiving Server. Once the domain has
* been authenticated the Receiving Server will start accepting packets from the Originating
* Server.<p>
*
* The Receiving Server will connect to the Authoritative Server to verify the dialback key.
* Most probably the Originating Server machine will be the Authoritative Server too.
*
* @param socketReader the reader to use for reading the answer from the Receiving Server.
* @param domain the domain to authenticate.
* @param hostname the hostname of the remote server (i.e. Receiving Server).
* @param id the stream id to be used for creating the dialback key.
* @return true if the Receiving Server authenticated the domain with the Authoritative Server.
*/
public boolean authenticateDomain(OutgoingServerSocketReader socketReader, String domain,
String hostname, String id) {
String key = AuthFactory.createDigest(id, getSecretkey());
Log.debug("ServerDialback: OS - Sent dialback key to host: " + hostname + " id: " + id + " from domain: " +
domain);
synchronized (socketReader) {
// Send a dialback key to the Receiving Server
StringBuilder sb = new StringBuilder();
sb.append("<db:result");
sb.append(" from=\"").append(domain).append("\"");
sb.append(" to=\"").append(hostname).append("\">");
sb.append(key);
sb.append("</db:result>");
connection.deliverRawText(sb.toString());
// Process the answer from the Receiving Server
try {
Element doc = socketReader.getElement(RemoteServerManager.getSocketTimeout(),
TimeUnit.MILLISECONDS);
if (doc == null) {
Log.debug("ServerDialback: OS - Time out waiting for answer in validation from: " + hostname +
" id: " +
id +
" for domain: " +
domain);
return false;
}
else if ("db".equals(doc.getNamespacePrefix()) && "result".equals(doc.getName())) {
boolean success = "valid".equals(doc.attributeValue("type"));
Log.debug("ServerDialback: OS - Validation " + (success ? "GRANTED" : "FAILED") + " from: " +
hostname +
" id: " +
id +
" for domain: " +
domain);
return success;
}
else {
Log.debug("ServerDialback: OS - Unexpected answer in validation from: " + hostname + " id: " +
id +
" for domain: " +
domain +
" answer:" +
doc.asXML());
return false;
}
}
catch (InterruptedException e) {
Log.debug("ServerDialback: OS - Validation FAILED from: " + hostname +
" id: " +
id +
" for domain: " +
domain, e);
return false;
}
}
}
/**
* Returns a new {@link IncomingServerSession} with a domain validated by the Authoritative
* Server. New domains may be added to the returned IncomingServerSession after they have
* been validated. See
* {@link LocalIncomingServerSession#validateSubsequentDomain(org.dom4j.Element)}. The remote
* server will be able to send packets through this session whose domains were previously
* validated.<p>
*
* When acting as an Authoritative Server this method will verify the requested key
* and will return null since the underlying TCP connection will be closed after sending the
* response to the Receiving Server.<p>
*
* @param reader reader of DOM documents on the connection to the remote server.
* @return an IncomingServerSession that was previously validated against the remote server.
* @throws IOException if an I/O error occurs while communicating with the remote server.
* @throws XmlPullParserException if an error occurs while parsing XML packets.
*/
public LocalIncomingServerSession createIncomingSession(XMPPPacketReader reader) throws IOException,
XmlPullParserException {
XmlPullParser xpp = reader.getXPPParser();
StringBuilder sb;
if ("jabber:server:dialback".equals(xpp.getNamespace("db"))) {
StreamID streamID = sessionManager.nextStreamID();
sb = new StringBuilder();
sb.append("<stream:stream");
sb.append(" xmlns:stream=\"http://etherx.jabber.org/streams\"");
sb.append(" xmlns=\"jabber:server\" xmlns:db=\"jabber:server:dialback\"");
sb.append(" id=\"");
sb.append(streamID.toString());
sb.append("\">");
connection.deliverRawText(sb.toString());
try {
Element doc = reader.parseDocument().getRootElement();
if ("db".equals(doc.getNamespacePrefix()) && "result".equals(doc.getName())) {
if (validateRemoteDomain(doc, streamID)) {
String hostname = doc.attributeValue("from");
String recipient = doc.attributeValue("to");
// Create a server Session for the remote server
LocalIncomingServerSession session = sessionManager.
createIncomingServerSession(connection, streamID);
// Set the first validated domain as the address of the session
session.setAddress(new JID(null, hostname, null));
// Add the validated domain as a valid domain
session.addValidatedDomain(hostname);
// Set the domain or subdomain of the local server used when
// validating the session
session.setLocalDomain(recipient);
return session;
}
}
else if ("db".equals(doc.getNamespacePrefix()) && "verify".equals(doc.getName())) {
// When acting as an Authoritative Server the Receiving Server will send a
// db:verify packet for verifying a key that was previously sent by this
// server when acting as the Originating Server
verifyReceivedKey(doc, connection);
// Close the underlying connection
connection.close();
String verifyFROM = doc.attributeValue("from");
String id = doc.attributeValue("id");
Log.debug("ServerDialback: AS - Connection closed for host: " + verifyFROM + " id: " + id);
return null;
}
else {
// The remote server sent an invalid/unknown packet
connection.deliverRawText(
new StreamError(StreamError.Condition.invalid_xml).toXML());
// Close the underlying connection
connection.close();
return null;
}
}
catch (Exception e) {
Log.error("An error occured while creating a server session", e);
// Close the underlying connection
connection.close();
return null;
}
}
else {
// Include the invalid-namespace stream error condition in the response
connection.deliverRawText(
new StreamError(StreamError.Condition.invalid_namespace).toXML());
// Close the underlying connection
connection.close();
return null;
}
return null;
}
/**
* Returns true if the domain requested by the remote server was validated by the Authoritative
* Server. To validate the domain a new TCP connection will be established to the
* Authoritative Server. The Authoritative Server may be the same Originating Server or
* some other machine in the Originating Server's network.<p>
*
* If the domain was not valid or some error occured while validating the domain then the
* underlying TCP connection will be closed.
*
* @param doc the request for validating the new domain.
* @param streamID the stream id generated by this server for the Originating Server.
* @return true if the requested domain is valid.
*/
public boolean validateRemoteDomain(Element doc, StreamID streamID) {
StringBuilder sb;
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();
DNSUtil.HostAddress address = DNSUtil.resolveXMPPServerDomain(hostname,
RemoteServerManager.getPortForServer(hostname));
try {
boolean valid = verifyKey(key, streamID.toString(), recipient, hostname,
address.getHost(), address.getPort());
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");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -