⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serverdialback.java

📁 openfire 服务器源码下载
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
                    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;
                }
            }
        }
    }

    private boolean isHostUnknown(String recipient) {
        boolean host_unknown = !serverName.equals(recipient);
        // If the recipient does not match the serverName then check if it matches a subdomain. This
        // trick is useful when subdomains of this server are registered in the DNS so remote
        // servers may establish connections directly to a subdomain of this server
        if (host_unknown && recipient.contains(serverName)) {
            host_unknown = !routingTable.hasComponentRoute(new JID(recipient));
        }
        return host_unknown;
    }

    /**
     * Verifies the key with the Authoritative Server.
     */
    private boolean verifyKey(String key, String streamID, String recipient, String hostname,
            String host, int port) throws IOException, XmlPullParserException,
            RemoteConnectionFailedException {
        XMPPPacketReader reader;
        Writer writer = null;
        // Establish a TCP connection back to the domain name asserted by the Originating Server
        Log.debug("ServerDialback: RS - Trying to connect to Authoritative Server: " + hostname + ":" + port +
                        "(DNS lookup: " + host + ":" + port + ")");
        // Connect to the Authoritative server
        Socket socket = new Socket();
        socket.connect(new InetSocketAddress(host, port), RemoteServerManager.getSocketTimeout());
        // Set a read timeout
        socket.setSoTimeout(RemoteServerManager.getSocketTimeout());
        Log.debug("ServerDialback: RS - Connection to AS: " + hostname + ":" + port + " successful");
        try {
            reader = new XMPPPacketReader();
            reader.setXPPFactory(FACTORY);

            reader.getXPPParser().setInput(new InputStreamReader(socket.getInputStream(),
                    CHARSET));
            // Get a writer for sending the open stream tag
            writer =
                    new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(),
                            CHARSET));
            // Send the Authoritative Server a stream header
            StringBuilder stream = new StringBuilder();
            stream.append("<stream:stream");
            stream.append(" xmlns:stream=\"http://etherx.jabber.org/streams\"");
            stream.append(" xmlns=\"jabber:server\"");
            stream.append(" xmlns:db=\"jabber:server:dialback\">");
            writer.write(stream.toString());
            writer.flush();

            // Get the answer from the Authoritative Server
            XmlPullParser xpp = reader.getXPPParser();
            for (int eventType = xpp.getEventType(); eventType != XmlPullParser.START_TAG;) {
                eventType = xpp.next();
            }
            if ("jabber:server:dialback".equals(xpp.getNamespace("db"))) {
                Log.debug("ServerDialback: RS - Asking AS to verify dialback key for id" + streamID);
                // Request for verification of the key
                StringBuilder sb = new StringBuilder();
                sb.append("<db:verify");
                sb.append(" from=\"").append(recipient).append("\"");
                sb.append(" to=\"").append(hostname).append("\"");
                sb.append(" id=\"").append(streamID).append("\">");
                sb.append(key);
                sb.append("</db:verify>");
                writer.write(sb.toString());
                writer.flush();

                try {
                    Element doc = reader.parseDocument().getRootElement();
                    if ("db".equals(doc.getNamespacePrefix()) && "verify".equals(doc.getName())) {
                        if (!streamID.equals(doc.attributeValue("id"))) {
                            // Include the invalid-id stream error condition in the response
                            writer.write(new StreamError(StreamError.Condition.invalid_id).toXML());
                            writer.flush();
                            // Thrown an error so <remote-connection-failed/> stream error
                            // condition is sent to the Originating Server
                            throw new RemoteConnectionFailedException("Invalid ID");
                        }
                        else if (isHostUnknown(doc.attributeValue("to"))) {
                            // Include the host-unknown stream error condition in the response
                            writer.write(
                                    new StreamError(StreamError.Condition.host_unknown).toXML());
                            writer.flush();
                            // Thrown an error so <remote-connection-failed/> stream error
                            // condition is sent to the Originating Server
                            throw new RemoteConnectionFailedException("Host unknown");
                        }
                        else if (!hostname.equals(doc.attributeValue("from"))) {
                            // Include the invalid-from stream error condition in the response
                            writer.write(
                                    new StreamError(StreamError.Condition.invalid_from).toXML());
                            writer.flush();
                            // Thrown an error so <remote-connection-failed/> stream error
                            // condition is sent to the Originating Server
                            throw new RemoteConnectionFailedException("Invalid From");
                        }
                        else {
                            boolean valid = "valid".equals(doc.attributeValue("type"));
                            Log.debug("ServerDialback: RS - Key was " + (valid ? "" : "NOT ") +
                                    "VERIFIED by the Authoritative Server for: " +
                                    hostname);
                            return valid;
                        }
                    }
                    else {
                        Log.debug("ServerDialback: db:verify answer was: " + doc.asXML());
                    }
                }
                catch (DocumentException e) {
                    Log.error("An error occured connecting to the Authoritative Server", e);
                    // Thrown an error so <remote-connection-failed/> stream error condition is
                    // sent to the Originating Server
                    throw new RemoteConnectionFailedException("Error connecting to the Authoritative Server");
                }

            }
            else {
                // Include the invalid-namespace stream error condition in the response
                writer.write(new StreamError(StreamError.Condition.invalid_namespace).toXML());
                writer.flush();
                // Thrown an error so <remote-connection-failed/> stream error condition is
                // sent to the Originating Server
                throw new RemoteConnectionFailedException("Invalid namespace");
            }
        }
        finally {
            try {
                Log.debug("ServerDialback: RS - Closing connection to Authoritative Server: " + hostname);
                // Close the stream
                StringBuilder sb = new StringBuilder();
                sb.append("</stream:stream>");
                writer.write(sb.toString());
                writer.flush();
                // Close the TCP connection
                socket.close();
            }
            catch (IOException ioe) {
                // Do nothing
            }
        }
        return false;
    }

    /**
     * Verifies the key sent by a Receiving Server. This server will be acting as the
     * Authoritative Server when executing this method. The remote server may have established
     * a new connection to the Authoritative Server (i.e. this server) for verifying the key
     * or it may be reusing an existing incoming connection.
     *
     * @param doc the Element that contains the key to verify.
     * @param connection the connection to use for sending the verification result
     * @return true if the key was verified.
     */
    public static boolean verifyReceivedKey(Element doc, Connection connection) {
        String verifyFROM = doc.attributeValue("from");
        String verifyTO = doc.attributeValue("to");
        String key = doc.getTextTrim();
        String id = doc.attributeValue("id");
        Log.debug("ServerDialback: AS - Verifying key for host: " + verifyFROM + " id: " + id);

        // TODO If the value of the 'to' address does not match a recognized hostname,
        // then generate a <host-unknown/> stream error condition
        // TODO If the value of the 'from' address does not match the hostname
        // represented by the Receiving Server when opening the TCP connection, then
        // generate an <invalid-from/> stream error condition

        // Verify the received key
        // Created the expected key based on the received ID value and the shared secret
        String expectedKey = AuthFactory.createDigest(id, getSecretkey());
        boolean verified = expectedKey.equals(key);

        // Send the result of the key verification
        StringBuilder sb = new StringBuilder();
        sb.append("<db:verify");
        sb.append(" from=\"").append(verifyTO).append("\"");
        sb.append(" to=\"").append(verifyFROM).append("\"");
        sb.append(" type=\"");
        sb.append(verified ? "valid" : "invalid");
        sb.append("\" id=\"").append(id).append("\"/>");
        connection.deliverRawText(sb.toString());
        Log.debug("ServerDialback: AS - Key was: " + (verified ? "VALID" : "INVALID") + " for host: " +
                verifyFROM +
                " id: " +
                id);
        return verified;
    }

    /**
     * Returns the secret key that was randomly generated. When running inside of a cluster
     * the key will be unique to all cluster nodes.
     *
     * @return the secret key that was randomly generated.
     */
    private static String getSecretkey() {
        String key = "secretKey";
        Lock lock = CacheFactory.getLock(key, secretKeyCache);
        try {
            lock.lock();
            String secret = secretKeyCache.get(key);
            if (secret == null) {
                secret = StringUtils.randomString(10);
                secretKeyCache.put(key, secret);
            }
            return secret;
        }
        finally {
            lock.unlock();
        }
    }
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -