Search in sources :

Example 21 with StreamError

use of org.xmpp.packet.StreamError in project Openfire by igniterealtime.

the class ServerDialback method validateRemoteDomain.

/**
     * 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 occurred while validating the domain then the
     * underlying TCP connection may 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 remoteDomain = doc.attributeValue("from");
    final Logger log = LoggerFactory.getLogger(Log.getName() + "[Acting as Receiving Server: Validate domain:" + recipient + "(id " + streamID + ") for OS: " + remoteDomain + "]");
    log.debug("Validating domain...");
    if (connection.getTlsPolicy() == Connection.TLSPolicy.required && !connection.isSecure()) {
        connection.deliverRawText(new StreamError(StreamError.Condition.policy_violation).toXML());
        // Close the underlying connection
        connection.close();
        return false;
    }
    if (!RemoteServerManager.canAccess(remoteDomain)) {
        connection.deliverRawText(new StreamError(StreamError.Condition.policy_violation).toXML());
        // Close the underlying connection
        connection.close();
        log.debug("Unable to validate domain: Remote domain is not allowed to establish a connection to this server.");
        return false;
    } else if (isHostUnknown(recipient)) {
        dialbackError(recipient, remoteDomain, new PacketError(PacketError.Condition.item_not_found, PacketError.Type.cancel, "Service not hosted here"));
        log.debug("Unable to validate domain: recipient not recognized as a local domain.");
        return false;
    } else {
        log.debug("Check if the remote domain already has a connection to the target domain/subdomain");
        boolean alreadyExists = false;
        for (IncomingServerSession session : sessionManager.getIncomingServerSessions(remoteDomain)) {
            if (recipient.equals(session.getLocalDomain())) {
                alreadyExists = true;
            }
        }
        if (alreadyExists && !sessionManager.isMultipleServerConnectionsAllowed()) {
            dialbackError(recipient, remoteDomain, new PacketError(PacketError.Condition.resource_constraint, PacketError.Type.cancel, "Incoming session already exists"));
            log.debug("Unable to validate domain: An incoming connection already exists from this remote domain, and multiple connections are not allowed.");
            return false;
        } else {
            log.debug("Checking to see if the remote server provides stronger authentication based on SASL. If that's the case, dialback-based authentication can be skipped.");
            if (SASLAuthentication.verifyCertificates(connection.getPeerCertificates(), remoteDomain, true)) {
                log.debug("Host authenticated based on SASL. Weaker dialback-based authentication is skipped.");
                sb = new StringBuilder();
                sb.append("<db:result");
                sb.append(" from=\"").append(recipient).append("\"");
                sb.append(" to=\"").append(remoteDomain).append("\"");
                sb.append(" type=\"valid\"");
                sb.append("/>");
                connection.deliverRawText(sb.toString());
                log.debug("Domain validated successfully!");
                return true;
            }
            log.debug("Unable to authenticate host based on stronger SASL. Proceeding with dialback...");
            String key = doc.getTextTrim();
            Socket socket = SocketUtil.createSocketToXmppDomain(remoteDomain, RemoteServerManager.getPortForServer(remoteDomain));
            if (socket == null) {
                log.debug("Unable to validate domain: No server available for verifying key of remote server.");
                dialbackError(recipient, remoteDomain, new PacketError(PacketError.Condition.remote_server_not_found, PacketError.Type.cancel, "Unable to connect to authoritative server"));
                return false;
            }
            VerifyResult result;
            try {
                log.debug("Verifying dialback key...");
                try {
                    result = verifyKey(key, streamID, recipient, remoteDomain, socket, false);
                } catch (SSLHandshakeException e) {
                    log.debug("Verification of dialback key failed due to TLS failure. Retry without TLS...", e);
                    // The receiving entity is expected to close the socket *without* sending any more data (<failure/> nor </stream>).
                    // It is probably (see OF-794) best if we, as the initiating entity, therefor don't send any data either.
                    final SocketAddress oldAddress = socket.getRemoteSocketAddress();
                    socket.close();
                    log.debug("Re-opening socket (with the same remote peer)...");
                    // Retry, without TLS.
                    socket = new Socket();
                    socket.connect(oldAddress, RemoteServerManager.getSocketTimeout());
                    log.debug("Successfully re-opened socket! Try to validate dialback key again (without TLS this time)...");
                    result = verifyKey(key, streamID, recipient, remoteDomain, socket, true);
                }
                switch(result) {
                    case valid:
                    case invalid:
                        boolean valid = (result == VerifyResult.valid);
                        log.debug("Dialback key is" + (valid ? "valid" : "invalid") + ". Sending verification result to remote domain.");
                        sb = new StringBuilder();
                        sb.append("<db:result");
                        sb.append(" from=\"").append(recipient).append("\"");
                        sb.append(" to=\"").append(remoteDomain).append("\"");
                        sb.append(" type=\"");
                        sb.append(valid ? "valid" : "invalid");
                        sb.append("\"/>");
                        connection.deliverRawText(sb.toString());
                        if (!valid) {
                            log.debug("Close the underlying connection as key verification failed.");
                            connection.close();
                            log.debug("Unable to validate domain: dialback key is invalid.");
                            return false;
                        } else {
                            log.debug("Successfully validated domain!");
                            return true;
                        }
                    default:
                        break;
                }
                log.debug("Unable to validate domain: key verification did not complete (the AS likely returned an error or a time out occurred).");
                dialbackError(recipient, remoteDomain, new PacketError(PacketError.Condition.remote_server_timeout, PacketError.Type.cancel, "Authoritative server returned error"));
                return false;
            } catch (Exception e) {
                dialbackError(recipient, remoteDomain, new PacketError(PacketError.Condition.remote_server_timeout, PacketError.Type.cancel, "Authoritative server failed"));
                log.warn("Unable to validate domain: An exception occurred while verifying the dialback key.", e);
                return false;
            }
        }
    }
}
Also used : StreamError(org.xmpp.packet.StreamError) IncomingServerSession(org.jivesoftware.openfire.session.IncomingServerSession) LocalIncomingServerSession(org.jivesoftware.openfire.session.LocalIncomingServerSession) PacketError(org.xmpp.packet.PacketError) Logger(org.slf4j.Logger) SocketAddress(java.net.SocketAddress) InetSocketAddress(java.net.InetSocketAddress) Socket(java.net.Socket) SSLHandshakeException(javax.net.ssl.SSLHandshakeException) DocumentException(org.dom4j.DocumentException) SSLHandshakeException(javax.net.ssl.SSLHandshakeException) IOException(java.io.IOException) XmlPullParserException(org.xmlpull.v1.XmlPullParserException)

Example 22 with StreamError

use of org.xmpp.packet.StreamError in project Openfire by igniterealtime.

the class ServerDialback method sendVerifyKey.

private VerifyResult sendVerifyKey(String key, StreamID streamID, String recipient, String remoteDomain, Writer writer, XMPPPacketReader reader, Socket socket, boolean skipTLS) throws IOException, XmlPullParserException, RemoteConnectionFailedException {
    final Logger log = LoggerFactory.getLogger(Log.getName() + "[Acting as Receiving Server: Verify key with AS: " + remoteDomain + " for OS: " + recipient + " (id " + streamID + ")]");
    VerifyResult result = VerifyResult.error;
    TLSStreamHandler tlsStreamHandler;
    log.debug("Send the Authoritative Server a stream header and wait for answer.");
    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\"");
    stream.append(" to=\"");
    stream.append(remoteDomain);
    stream.append("\"");
    stream.append(" from=\"");
    stream.append(recipient);
    stream.append("\"");
    stream.append(" version=\"1.0\">");
    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();
    }
    // TODO there's code duplication here with LocalOutgoingServerSession.
    log.debug("Got a response.");
    if ((xpp.getAttributeValue("", "version") != null) && (xpp.getAttributeValue("", "version").equals("1.0"))) {
        log.debug("The remote server is XMPP 1.0 compliant (or at least reports to be).");
        Document doc;
        try {
            doc = reader.parseDocument();
        } catch (DocumentException e) {
            log.warn("Unable to verify key: XML Error!", e);
            return VerifyResult.error;
        }
        Element features = doc.getRootElement();
        Element starttls = features.element("starttls");
        if (!skipTLS && starttls != null) {
            writer.write("<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>");
            writer.flush();
            try {
                doc = reader.parseDocument();
            } catch (DocumentException e) {
                log.warn("Unable to verify key: XML Error!", e);
                return VerifyResult.error;
            }
            if (!doc.getRootElement().getName().equals("proceed")) {
                log.warn("Unable to verify key: Got {} instead of proceed for starttls", doc.getRootElement().getName());
                log.debug("Like this: {}", doc.asXML());
                return VerifyResult.error;
            }
            log.debug("Negotiating TLS with AS... ");
            // Ugly hacks, apparently, copied from SocketConnection.
            final ConnectionManagerImpl connectionManager = ((ConnectionManagerImpl) XMPPServer.getInstance().getConnectionManager());
            tlsStreamHandler = new TLSStreamHandler(socket, connectionManager.getListener(ConnectionType.SOCKET_S2S, false).generateConnectionConfiguration(), true);
            // Start handshake
            tlsStreamHandler.start();
            // Use new wrapped writers
            writer = new BufferedWriter(new OutputStreamWriter(tlsStreamHandler.getOutputStream(), StandardCharsets.UTF_8));
            reader.getXPPParser().setInput(new InputStreamReader(tlsStreamHandler.getInputStream(), StandardCharsets.UTF_8));
            log.debug("Successfully negotiated TLS with AS... ");
            /// Recurses!
            return sendVerifyKey(key, streamID, recipient, remoteDomain, writer, reader, socket, skipTLS);
        }
    }
    if ("jabber:server:dialback".equals(xpp.getNamespace("db"))) {
        log.debug("Request for verification of the key and wait for response");
        StringBuilder sb = new StringBuilder();
        sb.append("<db:verify");
        sb.append(" from=\"").append(recipient).append("\"");
        sb.append(" to=\"").append(remoteDomain).append("\"");
        sb.append(" id=\"").append(streamID.getID()).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 (doc.attributeValue("id") == null || !streamID.equals(BasicStreamIDFactory.createStreamID(doc.attributeValue("id")))) {
                    // Include the invalid-id stream error condition in the response
                    writer.write(new StreamError(StreamError.Condition.invalid_id).toXML());
                    writer.flush();
                    // 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();
                    // condition is sent to the Originating Server
                    throw new RemoteConnectionFailedException("Host unknown");
                } else if (!remoteDomain.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();
                    // condition is sent to the Originating Server
                    throw new RemoteConnectionFailedException("Invalid From");
                } else if ("valid".equals(doc.attributeValue("type"))) {
                    log.debug("Key was VERIFIED by the Authoritative Server.");
                    result = VerifyResult.valid;
                } else if ("invalid".equals(doc.attributeValue("type"))) {
                    log.debug("Key was NOT VERIFIED by the Authoritative Server.");
                    result = VerifyResult.invalid;
                } else {
                    log.debug("Key was ERRORED by the Authoritative Server.");
                    result = VerifyResult.error;
                }
            } else {
                log.debug("db:verify answer was: " + doc.asXML());
            }
        } catch (DocumentException | RuntimeException e) {
            log.error("An error occurred while connecting to the Authoritative Server:", e);
            // 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();
        // sent to the Originating Server
        throw new RemoteConnectionFailedException("Invalid namespace");
    }
    return result;
}
Also used : ConnectionManagerImpl(org.jivesoftware.openfire.spi.ConnectionManagerImpl) InputStreamReader(java.io.InputStreamReader) Element(org.dom4j.Element) XmlPullParser(org.xmlpull.v1.XmlPullParser) Logger(org.slf4j.Logger) Document(org.dom4j.Document) BufferedWriter(java.io.BufferedWriter) StreamError(org.xmpp.packet.StreamError) DocumentException(org.dom4j.DocumentException) OutputStreamWriter(java.io.OutputStreamWriter)

Example 23 with StreamError

use of org.xmpp.packet.StreamError in project Openfire by igniterealtime.

the class LocalClientSession method createSession.

/**
     * Returns a newly created session between the server and a client. The session will
     * be created and returned only if correct name/prefix (i.e. 'stream' or 'flash')
     * and namespace were provided by the client.
     *
     * @param serverName the name of the server where the session is connecting to.
     * @param xpp the parser that is reading the provided XML through the connection.
     * @param connection the connection with the client.
     * @return a newly created session between the server and a client.
     * @throws org.xmlpull.v1.XmlPullParserException if an error occurs while parsing incoming data.
     */
public static LocalClientSession createSession(String serverName, XmlPullParser xpp, Connection connection) throws XmlPullParserException {
    boolean isFlashClient = xpp.getPrefix().equals("flash");
    connection.setFlashClient(isFlashClient);
    // in the 'etherx' namespace
    if (!xpp.getName().equals("stream") && !isFlashClient) {
        throw new XmlPullParserException(LocaleUtils.getLocalizedString("admin.error.bad-stream"));
    }
    if (!xpp.getNamespace(xpp.getPrefix()).equals(ETHERX_NAMESPACE) && !(isFlashClient && xpp.getNamespace(xpp.getPrefix()).equals(FLASH_NAMESPACE))) {
        throw new XmlPullParserException(LocaleUtils.getLocalizedString("admin.error.bad-namespace"));
    }
    if (!isAllowed(connection)) {
        // Client cannot connect from this IP address so end the stream and TCP connection.
        String hostAddress = "Unknown";
        try {
            hostAddress = connection.getHostAddress();
        } catch (UnknownHostException e) {
        // Do nothing
        }
        Log.debug("LocalClientSession: Closed connection to client attempting to connect from: " + hostAddress);
        // Include the not-authorized error in the response
        StreamError error = new StreamError(StreamError.Condition.not_authorized);
        connection.deliverRawText(error.toXML());
        // Close the underlying connection
        connection.close();
        return null;
    }
    // Default language is English ("en").
    Locale language = Locale.forLanguageTag("en");
    // Default to a version of "0.0". Clients written before the XMPP 1.0 spec may
    // not report a version in which case "0.0" should be assumed (per rfc3920
    // section 4.4.1).
    int majorVersion = 0;
    int minorVersion = 0;
    for (int i = 0; i < xpp.getAttributeCount(); i++) {
        if ("lang".equals(xpp.getAttributeName(i))) {
            language = Locale.forLanguageTag(xpp.getAttributeValue(i));
        }
        if ("version".equals(xpp.getAttributeName(i))) {
            try {
                int[] version = decodeVersion(xpp.getAttributeValue(i));
                majorVersion = version[0];
                minorVersion = version[1];
            } catch (Exception e) {
                Log.error(e.getMessage(), e);
            }
        }
    }
    // set the version to the highest one the server supports.
    if (majorVersion > MAJOR_VERSION) {
        majorVersion = MAJOR_VERSION;
        minorVersion = MINOR_VERSION;
    } else if (majorVersion == MAJOR_VERSION) {
        // supports.
        if (minorVersion > MINOR_VERSION) {
            minorVersion = MINOR_VERSION;
        }
    }
    connection.setXMPPVersion(majorVersion, minorVersion);
    final ConnectionConfiguration connectionConfiguration = connection.getConfiguration();
    // Indicate the TLS policy to use for this connection
    if (!connection.isSecure()) {
        boolean hasCertificates = false;
        try {
            hasCertificates = connectionConfiguration.getIdentityStore().getAllCertificates().size() > 0;
        } catch (Exception e) {
            Log.error(e.getMessage(), e);
        }
        Connection.TLSPolicy tlsPolicy = connectionConfiguration.getTlsPolicy();
        if (Connection.TLSPolicy.required == tlsPolicy && !hasCertificates) {
            Log.error("Client session rejected. TLS is required but no certificates " + "were created.");
            return null;
        }
        // Set default TLS policy
        connection.setTlsPolicy(hasCertificates ? tlsPolicy : Connection.TLSPolicy.disabled);
    } else {
        // Set default TLS policy
        connection.setTlsPolicy(Connection.TLSPolicy.disabled);
    }
    // Indicate the compression policy to use for this connection
    connection.setCompressionPolicy(connectionConfiguration.getCompressionPolicy());
    // Create a ClientSession for this user.
    LocalClientSession session = SessionManager.getInstance().createClientSession(connection, language);
    // Build the start packet response
    StringBuilder sb = new StringBuilder(200);
    sb.append("<?xml version='1.0' encoding='");
    sb.append(CHARSET);
    sb.append("'?>");
    if (isFlashClient) {
        sb.append("<flash:stream xmlns:flash=\"http://www.jabber.com/streams/flash\" ");
    } else {
        sb.append("<stream:stream ");
    }
    sb.append("xmlns:stream=\"http://etherx.jabber.org/streams\" xmlns=\"jabber:client\" from=\"");
    sb.append(serverName);
    sb.append("\" id=\"");
    sb.append(session.getStreamID().toString());
    sb.append("\" xml:lang=\"");
    sb.append(language.toLanguageTag());
    // Don't include version info if the version is 0.0.
    if (majorVersion != 0) {
        sb.append("\" version=\"");
        sb.append(majorVersion).append('.').append(minorVersion);
    }
    sb.append("\">");
    connection.deliverRawText(sb.toString());
    // return to allow normal packet parsing.
    if (majorVersion == 0) {
        return session;
    }
    // Otherwise, this is at least XMPP 1.0 so we need to announce stream features.
    sb = new StringBuilder(490);
    sb.append("<stream:features>");
    if (connection.getTlsPolicy() != Connection.TLSPolicy.disabled) {
        sb.append("<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\">");
        if (connection.getTlsPolicy() == Connection.TLSPolicy.required) {
            sb.append("<required/>");
        }
        sb.append("</starttls>");
    }
    // Include available SASL Mechanisms
    sb.append(SASLAuthentication.getSASLMechanisms(session));
    // Include Stream features
    String specificFeatures = session.getAvailableStreamFeatures();
    if (specificFeatures != null) {
        sb.append(specificFeatures);
    }
    sb.append("</stream:features>");
    connection.deliverRawText(sb.toString());
    return session;
}
Also used : UnknownHostException(java.net.UnknownHostException) Connection(org.jivesoftware.openfire.Connection) UnauthorizedException(org.jivesoftware.openfire.auth.UnauthorizedException) UnknownHostException(java.net.UnknownHostException) UserNotFoundException(org.jivesoftware.openfire.user.UserNotFoundException) XmlPullParserException(org.xmlpull.v1.XmlPullParserException) StreamError(org.xmpp.packet.StreamError) ConnectionConfiguration(org.jivesoftware.openfire.spi.ConnectionConfiguration) XmlPullParserException(org.xmlpull.v1.XmlPullParserException)

Example 24 with StreamError

use of org.xmpp.packet.StreamError in project Openfire by igniterealtime.

the class LocalComponentSession method createSession.

/**
     * Returns a newly created session between the server and a component. The session will be
     * created and returned only if all the checkings were correct.<p>
     *
     * A domain will be binded for the new connecting component. This method is following
     * the JEP-114 where the domain to bind is sent in the TO attribute of the stream header.
     *
     * @param serverName the name of the server where the session is connecting to.
     * @param xpp     the parser that is reading the provided XML through the connection.
     * @param connection the connection with the component.
     * @return a newly created session between the server and a component.
     * @throws XmlPullParserException if there was an XML error while creating the session.
     */
public static LocalComponentSession createSession(String serverName, XmlPullParser xpp, Connection connection) throws XmlPullParserException {
    String domain = xpp.getAttributeValue("", "to");
    Boolean allowMultiple = xpp.getAttributeValue("", "allowMultiple") != null;
    Log.debug("LocalComponentSession: [ExComp] Starting registration of new external component for domain: " + domain);
    // Default answer header in case of an error
    StringBuilder sb = new StringBuilder();
    sb.append("<?xml version='1.0' encoding='");
    sb.append(CHARSET);
    sb.append("'?>");
    sb.append("<stream:stream ");
    sb.append("xmlns:stream=\"http://etherx.jabber.org/streams\" ");
    sb.append("xmlns=\"jabber:component:accept\" from=\"");
    sb.append(domain);
    sb.append("\">");
    // Check that a domain was provided in the stream header
    if (domain == null) {
        Log.debug("LocalComponentSession: [ExComp] Domain not specified in stanza: " + xpp.getText());
        // Include the bad-format in the response
        StreamError error = new StreamError(StreamError.Condition.bad_format);
        sb.append(error.toXML());
        connection.deliverRawText(sb.toString());
        // Close the underlying connection
        connection.close();
        return null;
    }
    // Get the requested subdomain
    String subdomain = domain;
    int index = domain.indexOf(serverName);
    if (index > -1) {
        subdomain = domain.substring(0, index - 1);
    }
    domain = subdomain + "." + serverName;
    JID componentJID = new JID(domain);
    // Check that an external component for the specified subdomain may connect to this server
    if (!ExternalComponentManager.canAccess(subdomain)) {
        Log.debug("LocalComponentSession: [ExComp] Component is not allowed to connect with subdomain: " + subdomain);
        StreamError error = new StreamError(StreamError.Condition.host_unknown);
        sb.append(error.toXML());
        connection.deliverRawText(sb.toString());
        // Close the underlying connection
        connection.close();
        return null;
    }
    // Check that a secret key was configured in the server
    String secretKey = ExternalComponentManager.getSecretForComponent(subdomain);
    if (secretKey == null) {
        Log.debug("LocalComponentSession: [ExComp] A shared secret for the component was not found.");
        // Include the internal-server-error in the response
        StreamError error = new StreamError(StreamError.Condition.internal_server_error);
        sb.append(error.toXML());
        connection.deliverRawText(sb.toString());
        // Close the underlying connection
        connection.close();
        return null;
    }
    // Check that the requested subdomain is not already in use
    if (!allowMultiple && InternalComponentManager.getInstance().hasComponent(componentJID)) {
        Log.debug("LocalComponentSession: [ExComp] Another component is already using domain: " + domain);
        // Domain already occupied so return a conflict error and close the connection
        // Include the conflict error in the response
        StreamError error = new StreamError(StreamError.Condition.conflict);
        sb.append(error.toXML());
        connection.deliverRawText(sb.toString());
        // Close the underlying connection
        connection.close();
        return null;
    }
    // Create a ComponentSession for the external component
    LocalComponentSession session = SessionManager.getInstance().createComponentSession(componentJID, connection);
    session.component = new LocalExternalComponent(session, connection);
    try {
        Log.debug("LocalComponentSession: [ExComp] Send stream header with ID: " + session.getStreamID() + " for component with domain: " + domain);
        // Build the start packet response
        sb = new StringBuilder();
        sb.append("<?xml version='1.0' encoding='");
        sb.append(CHARSET);
        sb.append("'?>");
        sb.append("<stream:stream ");
        sb.append("xmlns:stream=\"http://etherx.jabber.org/streams\" ");
        sb.append("xmlns=\"jabber:component:accept\" from=\"");
        sb.append(domain);
        sb.append("\" id=\"");
        sb.append(session.getStreamID().toString());
        sb.append("\">");
        connection.deliverRawText(sb.toString());
        // Return session although session has not been authentication yet. Until
        // it is authenticated traffic will be rejected except for authentication
        // requests
        session.defaultSubdomain = subdomain;
        return session;
    } catch (Exception e) {
        Log.error("An error occured while creating a ComponentSession", e);
        // Close the underlying connection
        connection.close();
        return null;
    }
}
Also used : StreamError(org.xmpp.packet.StreamError) JID(org.xmpp.packet.JID) ComponentException(org.xmpp.component.ComponentException) PacketException(org.jivesoftware.openfire.PacketException) XmlPullParserException(org.xmlpull.v1.XmlPullParserException)

Example 25 with StreamError

use of org.xmpp.packet.StreamError in project Openfire by igniterealtime.

the class IQAuthHandler method login.

private IQ login(String username, Element iq, IQ packet, String password, LocalClientSession session, String digest) throws UnauthorizedException, UserNotFoundException, ConnectionException, InternalUnauthenticatedException {
    // Verify the validity of the username
    if (username == null || username.trim().length() == 0) {
        throw new UnauthorizedException("Invalid username (empty or null).");
    }
    try {
        Stringprep.nodeprep(username);
    } catch (StringprepException e) {
        throw new UnauthorizedException("Invalid username: " + username, e);
    }
    // Verify that specified resource is not violating any string prep rule
    String resource = iq.elementText("resource");
    if (resource != null) {
        try {
            resource = JID.resourceprep(resource);
        } catch (StringprepException e) {
            throw new UnauthorizedException("Invalid resource: " + resource, e);
        }
    } else {
        // Answer a not_acceptable error since a resource was not supplied
        IQ response = IQ.createResultIQ(packet);
        response.setChildElement(packet.getChildElement().createCopy());
        response.setError(PacketError.Condition.not_acceptable);
        return response;
    }
    if (!JiveGlobals.getBooleanProperty("xmpp.auth.iqauth", true)) {
        throw new UnauthorizedException();
    }
    username = username.toLowerCase();
    // Verify that supplied username and password are correct (i.e. user authentication was successful)
    AuthToken token = null;
    if (AuthFactory.supportsPasswordRetrieval()) {
        if (password != null) {
            token = AuthFactory.authenticate(username, password);
        } else if (digest != null) {
            token = authenticate(username, session.getStreamID().toString(), digest);
        }
    }
    if (token == null) {
        throw new UnauthorizedException();
    }
    // Verify if there is a resource conflict between new resource and existing one.
    // Check if a session already exists with the requested full JID and verify if
    // we should kick it off or refuse the new connection
    ClientSession oldSession = routingTable.getClientRoute(new JID(username, serverName, resource, true));
    if (oldSession != null) {
        try {
            int conflictLimit = sessionManager.getConflictKickLimit();
            if (conflictLimit == SessionManager.NEVER_KICK) {
                IQ response = IQ.createResultIQ(packet);
                response.setChildElement(packet.getChildElement().createCopy());
                response.setError(PacketError.Condition.forbidden);
                return response;
            }
            int conflictCount = oldSession.incrementConflictCount();
            if (conflictCount > conflictLimit) {
                // Send a stream:error before closing the old connection
                StreamError error = new StreamError(StreamError.Condition.conflict);
                oldSession.deliverRawText(error.toXML());
                oldSession.close();
            } else {
                IQ response = IQ.createResultIQ(packet);
                response.setChildElement(packet.getChildElement().createCopy());
                response.setError(PacketError.Condition.forbidden);
                return response;
            }
        } catch (Exception e) {
            Log.error("Error during login", e);
        }
    }
    // Set that the new session has been authenticated successfully
    session.setAuthToken(token, resource);
    packet.setFrom(session.getAddress());
    return IQ.createResultIQ(packet);
}
Also used : StringprepException(gnu.inet.encoding.StringprepException) StreamError(org.xmpp.packet.StreamError) JID(org.xmpp.packet.JID) LocalClientSession(org.jivesoftware.openfire.session.LocalClientSession) ClientSession(org.jivesoftware.openfire.session.ClientSession) UnauthorizedException(org.jivesoftware.openfire.auth.UnauthorizedException) IQ(org.xmpp.packet.IQ) AuthToken(org.jivesoftware.openfire.auth.AuthToken) StringprepException(gnu.inet.encoding.StringprepException) PacketException(org.jivesoftware.openfire.PacketException) UnauthorizedException(org.jivesoftware.openfire.auth.UnauthorizedException) ConnectionException(org.jivesoftware.openfire.auth.ConnectionException) UserNotFoundException(org.jivesoftware.openfire.user.UserNotFoundException) InternalUnauthenticatedException(org.jivesoftware.openfire.auth.InternalUnauthenticatedException)

Aggregations

StreamError (org.xmpp.packet.StreamError)25 ClientSession (org.jivesoftware.openfire.session.ClientSession)7 IOException (java.io.IOException)6 UnauthorizedException (org.jivesoftware.openfire.auth.UnauthorizedException)6 XmlPullParserException (org.xmlpull.v1.XmlPullParserException)6 JID (org.xmpp.packet.JID)5 SSLHandshakeException (javax.net.ssl.SSLHandshakeException)4 DocumentException (org.dom4j.DocumentException)4 Element (org.dom4j.Element)4 LocalIncomingServerSession (org.jivesoftware.openfire.session.LocalIncomingServerSession)4 XmlPullParser (org.xmlpull.v1.XmlPullParser)4 StringprepException (gnu.inet.encoding.StringprepException)3 PacketException (org.jivesoftware.openfire.PacketException)3 LocalClientSession (org.jivesoftware.openfire.session.LocalClientSession)3 UserNotFoundException (org.jivesoftware.openfire.user.UserNotFoundException)3 Logger (org.slf4j.Logger)3 IQ (org.xmpp.packet.IQ)3 InputStreamReader (java.io.InputStreamReader)2 Socket (java.net.Socket)2 Connection (org.jivesoftware.openfire.Connection)2