Search in sources :

Example 71 with Element

use of org.dom4j.Element in project Openfire by igniterealtime.

the class LocalMUCRole method updatePresence.

private void updatePresence() {
    if (extendedInformation != null && presence != null) {
        // Remove any previous extendedInformation, then re-add it.
        Element mucUser = presence.getElement().element(QName.get("x", "http://jabber.org/protocol/muc#user"));
        if (mucUser != null) {
            // Remove any previous extendedInformation, then re-add it.
            presence.getElement().remove(mucUser);
        }
        Element exi = extendedInformation.createCopy();
        presence.getElement().add(exi);
    }
}
Also used : Element(org.dom4j.Element)

Example 72 with Element

use of org.dom4j.Element in project Openfire by igniterealtime.

the class LocalMUCRole method setPresence.

@Override
public void setPresence(Presence newPresence) {
    // Try to remove the element whose namespace is "http://jabber.org/protocol/muc" since we
    // don't need to include that element in future presence broadcasts
    Element element = newPresence.getElement().element(QName.get("x", "http://jabber.org/protocol/muc"));
    if (element != null) {
        newPresence.getElement().remove(element);
    }
    this.presence = newPresence;
    this.presence.setFrom(getRoleAddress());
    updatePresence();
}
Also used : Element(org.dom4j.Element)

Example 73 with Element

use of org.dom4j.Element in project Openfire by igniterealtime.

the class LocalOutgoingServerSession method secureAndAuthenticate.

private static LocalOutgoingServerSession secureAndAuthenticate(String remoteDomain, SocketConnection connection, XMPPPacketReader reader, StringBuilder openingStream, String localDomain) throws Exception {
    final Logger log = LoggerFactory.getLogger(Log.getName() + "[Secure/Authenticate connection for: " + localDomain + " to: " + remoteDomain + "]");
    Element features;
    log.debug("Securing and authenticating connection ...");
    log.debug("Indicating we want TLS and wait for response.");
    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("Received 'proceed' from remote server. Negotiating TLS...");
        try {
            //                boolean needed = JiveGlobals.getBooleanProperty(ConnectionSettings.Server.TLS_CERTIFICATE_VERIFY, true) &&
            //                        		 JiveGlobals.getBooleanProperty(ConnectionSettings.Server.TLS_CERTIFICATE_CHAIN_VERIFY, true) &&
            //                        		 !JiveGlobals.getBooleanProperty(ConnectionSettings.Server.TLS_ACCEPT_SELFSIGNED_CERTS, false);
            connection.startTLS(true);
        } catch (Exception e) {
            log.debug("TLS negotiation failed: " + e.getMessage());
            throw e;
        }
        log.debug("TLS negotiation was successful. Connection secured. Proceeding with authentication...");
        if (!SASLAuthentication.verifyCertificates(connection.getPeerCertificates(), remoteDomain, true)) {
            if (ServerDialback.isEnabled() || ServerDialback.isEnabledForSelfSigned()) {
                log.debug("SASL authentication failed. Will continue with dialback.");
            } else {
                log.warn("Unable to authenticated the connection: SASL authentication failed (and dialback is not available).");
                return null;
            }
        }
        log.debug("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(), StandardCharsets.UTF_8));
        // Skip new stream element
        for (int eventType = xpp.getEventType(); eventType != XmlPullParser.START_TAG; ) {
            eventType = xpp.next();
        }
        // Get the stream ID 
        String id = xpp.getAttributeValue("", "id");
        // Get new stream features
        features = reader.parseDocument().getRootElement();
        if (features != null) {
            // Bookkeeping: determine what functionality the remote server offers.
            boolean saslEXTERNALoffered = false;
            if (features.element("mechanisms") != null) {
                Iterator<Element> it = features.element("mechanisms").elementIterator();
                while (it.hasNext()) {
                    Element mechanism = it.next();
                    if ("EXTERNAL".equals(mechanism.getTextTrim())) {
                        saslEXTERNALoffered = true;
                        break;
                    }
                }
            }
            final boolean dialbackOffered = features.element("dialback") != null;
            log.debug("Remote server is offering dialback: {}, EXTERNAL SASL:", dialbackOffered, saslEXTERNALoffered);
            LocalOutgoingServerSession result = null;
            // first, try SASL
            if (saslEXTERNALoffered) {
                log.debug("Trying to authenticate with EXTERNAL SASL.");
                result = attemptSASLexternal(connection, xpp, reader, localDomain, remoteDomain, id, openingStream);
                if (result == null) {
                    log.debug("Failed to authenticate with EXTERNAL SASL.");
                } else {
                    log.debug("Successfully authenticated with EXTERNAL SASL.");
                }
            }
            // SASL unavailable or failed, try dialback.
            if (result == null) {
                log.debug("Trying to authenticate with dialback.");
                result = attemptDialbackOverTLS(connection, reader, localDomain, remoteDomain, id);
                if (result == null) {
                    log.debug("Failed to authenticate with dialback.");
                } else {
                    log.debug("Successfully authenticated with dialback.");
                }
            }
            if (result != null) {
                log.debug("Successfully secured and authenticated connection!");
                return result;
            } else {
                log.warn("Unable to secure and authenticate connection: Exhausted all options.");
                return null;
            }
        } else {
            log.debug("Failed to secure and authenticate connection: neither SASL mechanisms nor SERVER DIALBACK were offered by the remote host.");
            return null;
        }
    } else {
        log.debug("Failed to secure and authenticate connection: <proceed> was not received!");
        return null;
    }
}
Also used : InputStreamReader(java.io.InputStreamReader) Element(org.dom4j.Element) Logger(org.slf4j.Logger) UnauthorizedException(org.jivesoftware.openfire.auth.UnauthorizedException) DocumentException(org.dom4j.DocumentException) SSLHandshakeException(javax.net.ssl.SSLHandshakeException) IOException(java.io.IOException) XmlPullParserException(org.xmlpull.v1.XmlPullParserException)

Example 74 with Element

use of org.dom4j.Element in project Openfire by igniterealtime.

the class LocalOutgoingServerSession method createOutgoingSession.

/**
     * Establishes a new outgoing session to a remote domain. If the remote domain 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 domain or if an error occurred while securing or authenticating the connection using SASL
     * then server dialback will be used.
     *
     * @param localDomain the local domain to authenticate with the remote domain.
     * @param remoteDomain the remote domain.
     * @param port default port to use to establish the connection.
     * @return new outgoing session to a remote domain, or null.
     */
private static LocalOutgoingServerSession createOutgoingSession(String localDomain, String remoteDomain, int port) {
    final Logger log = LoggerFactory.getLogger(Log.getName() + "[Create outgoing session for: " + localDomain + " to " + remoteDomain + "]");
    log.debug("Creating new session...");
    // Connect to remote server using XMPP 1.0 (TLS + SASL EXTERNAL or TLS + server dialback or server dialback)
    log.debug("Creating plain socket connection to a host that belongs to the remote XMPP domain.");
    final Socket socket = SocketUtil.createSocketToXmppDomain(remoteDomain, port);
    if (socket == null) {
        log.info("Unable to create new session: Cannot create a plain socket connection with any applicable remote host.");
        return null;
    }
    SocketConnection connection = null;
    try {
        connection = new SocketConnection(XMPPServer.getInstance().getPacketDeliverer(), socket, false);
        log.debug("Send the stream header and wait for response...");
        StringBuilder openingStream = new StringBuilder();
        openingStream.append("<stream:stream");
        openingStream.append(" xmlns:db=\"jabber:server:dialback\"");
        openingStream.append(" xmlns:stream=\"http://etherx.jabber.org/streams\"");
        openingStream.append(" xmlns=\"jabber:server\"");
        // OF-673
        openingStream.append(" from=\"").append(localDomain).append("\"");
        openingStream.append(" to=\"").append(remoteDomain).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(), StandardCharsets.UTF_8));
        // 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");
        String id = xpp.getAttributeValue("", "id");
        log.debug("Got a response (stream ID: {}, version: {}). Check if the remote server is XMPP 1.0 compliant...", id, serverVersion);
        if (serverVersion != null && decodeVersion(serverVersion)[0] >= 1) {
            log.debug("The remote server is XMPP 1.0 compliant (or at least reports to be).");
            // Restore default timeout
            socket.setSoTimeout(soTimeout);
            log.debug("Processing stream features of the remote domain...");
            Element features = reader.parseDocument().getRootElement();
            if (features != null) {
                log.debug("Check if both us as well as the remote server have enabled STARTTLS and/or dialback ...");
                final boolean useTLS = JiveGlobals.getBooleanProperty(ConnectionSettings.Server.TLS_ENABLED, true);
                if (useTLS && features.element("starttls") != null) {
                    log.debug("Both us and the remote server support the STARTTLS feature. Secure and authenticate the connection with TLS & SASL...");
                    LocalOutgoingServerSession answer = secureAndAuthenticate(remoteDomain, connection, reader, openingStream, localDomain);
                    if (answer != null) {
                        log.debug("Successfully secured/authenticated the connection with TLS/SASL)!");
                        // Everything went fine so return the secured and
                        // authenticated connection
                        log.debug("Successfully created new session!");
                        return answer;
                    }
                    log.debug("Unable to secure and authenticate the connection with TLS & SASL.");
                } else if (connection.getTlsPolicy() == Connection.TLSPolicy.required) {
                    log.debug("I have no StartTLS yet I must TLS");
                    connection.close();
                    return null;
                } else // Check if we are going to try server dialback (XMPP 1.0)
                if (ServerDialback.isEnabled() && features.element("dialback") != null) {
                    log.debug("Both us and the remote server support the 'dialback' feature. Authenticate the connection with dialback...");
                    ServerDialback method = new ServerDialback(connection, localDomain);
                    OutgoingServerSocketReader newSocketReader = new OutgoingServerSocketReader(reader);
                    if (method.authenticateDomain(newSocketReader, localDomain, remoteDomain, id)) {
                        log.debug("Successfully authenticated the connection with dialback!");
                        StreamID streamID = new BasicStreamIDFactory().createStreamID(id);
                        LocalOutgoingServerSession session = new LocalOutgoingServerSession(localDomain, connection, newSocketReader, streamID);
                        connection.init(session);
                        // Set the hostname as the address of the session
                        session.setAddress(new JID(null, remoteDomain, null));
                        log.debug("Successfully created new session!");
                        return session;
                    } else {
                        log.debug("Unable to authenticate the connection with dialback.");
                    }
                }
            } else {
                log.debug("Error! No data from the remote server (expected a 'feature' element).");
            }
        } else {
            log.debug("The remote server is not XMPP 1.0 compliant.");
        }
        log.debug("Something went wrong so close the connection and try server dialback over a plain connection");
        if (connection.getTlsPolicy() == Connection.TLSPolicy.required) {
            log.debug("I have no StartTLS yet I must TLS");
            connection.close();
            return null;
        }
        connection.close();
    } catch (SSLHandshakeException e) {
        // This is a failure as described in RFC3620, section 5.4.3.2 "STARTTLS Failure".
        log.info("STARTTLS negotiation failed. Closing connection (without sending any data such as <failure/> or </stream>).", e);
        // It is probably (see OF-794) best if we, as the initiating entity, therefor don't send any data either.
        if (connection != null) {
            connection.forceClose();
        }
    } catch (Exception e) {
        // This might be RFC3620, section 5.4.2.2 "Failure Case" or even an unrelated problem. Handle 'normally'.
        log.warn("An exception occurred while creating an encrypted session. Closing connection.", e);
        if (connection != null) {
            connection.close();
        }
    }
    if (ServerDialback.isEnabled()) {
        log.debug("Unable to create a new session. Going to try connecting using server dialback as a fallback.");
        // Use server dialback (pre XMPP 1.0) over a plain connection
        final LocalOutgoingServerSession outgoingSession = new ServerDialback().createOutgoingSession(localDomain, remoteDomain, port);
        if (outgoingSession != null) {
            // TODO this success handler behaves differently from a similar success handler above. Shouldn't those be the same?
            log.debug("Successfully created new session (using dialback as a fallback)!");
            return outgoingSession;
        } else {
            log.warn("Unable to create a new session: Dialback (as a fallback) failed.");
            return null;
        }
    } else {
        log.warn("Unable to create a new session: exhausted all options (not trying dialback as a fallback, as server dialback is disabled by configuration.");
        return null;
    }
}
Also used : StreamID(org.jivesoftware.openfire.StreamID) XMPPPacketReader(org.dom4j.io.XMPPPacketReader) InputStreamReader(java.io.InputStreamReader) JID(org.xmpp.packet.JID) Element(org.dom4j.Element) XmlPullParser(org.xmlpull.v1.XmlPullParser) Logger(org.slf4j.Logger) ServerDialback(org.jivesoftware.openfire.server.ServerDialback) SSLHandshakeException(javax.net.ssl.SSLHandshakeException) UnauthorizedException(org.jivesoftware.openfire.auth.UnauthorizedException) DocumentException(org.dom4j.DocumentException) SSLHandshakeException(javax.net.ssl.SSLHandshakeException) IOException(java.io.IOException) XmlPullParserException(org.xmlpull.v1.XmlPullParserException) OutgoingServerSocketReader(org.jivesoftware.openfire.server.OutgoingServerSocketReader) BasicStreamIDFactory(org.jivesoftware.openfire.spi.BasicStreamIDFactory) Socket(java.net.Socket)

Example 75 with Element

use of org.dom4j.Element in project Openfire by igniterealtime.

the class Workgroup method sendInvitation.

/**
     * An agent has accepted the offer and was choosen to answer the user's requests. The workgroup
     * will create a new room where the agent can answer the user's needs. Once the room has been
     * created, the Agent and the user that made the request will receive invitiations to join the
     * newly created room.<p>
     * <p/>
     * The workgroup will listen for all the packets sent to the room and generate a conversation
     * transcript.
     *
     * @param agent   the AgentSession that accepted and was choosen to respond the user's requests.
     * @param request the request made by a user.
     */
public void sendInvitation(AgentSession agent, UserRequest request) {
    // we need to destroy all MUC rooms created by workgroups
    try {
        RoomInterceptorManager interceptorManager = RoomInterceptorManager.getInstance();
        WorkgroupManager workgroupManager = WorkgroupManager.getInstance();
        String userJID = request.getUserJID().toString();
        final Workgroup sessionWorkgroup = request.getWorkgroup();
        final String sessionID = request.getSessionID();
        String workgroupName = getJID().getNode();
        final String serviceName = workgroupManager.getMUCServiceName();
        final String roomName = sessionID + "@" + serviceName;
        final String roomJID = roomName + "/" + workgroupName;
        // Create the room by joining it. The workgroup will be the owner of the room and will
        // invite the Agent and the user to join the room
        JoinRoom joinRoom = new JoinRoom(getFullJID().toString(), roomJID);
        interceptorManager.invokeInterceptors(getJID().toBareJID(), joinRoom, false, false);
        send(joinRoom);
        interceptorManager.invokeInterceptors(getJID().toBareJID(), joinRoom, false, true);
        // Configure the newly created room
        Map<String, Collection<String>> fields = new HashMap<String, Collection<String>>();
        // Make a non-public room
        List<String> values = new ArrayList<String>();
        values.add("0");
        fields.put("muc#roomconfig_publicroom", values);
        // Set the room description
        values = new ArrayList<String>();
        values.add(roomName);
        fields.put("muc#roomconfig_roomdesc", values);
        // Set that anyone can change the room subject
        values = new ArrayList<String>();
        values.add("1");
        fields.put("muc#roomconfig_changesubject", values);
        // Make the room temporary
        values = new ArrayList<String>();
        values.add("0");
        fields.put("muc#roomconfig_persistentroom", values);
        // Set that only moderators can see the occupants' JID
        values = new ArrayList<String>();
        values.add("moderators");
        fields.put("muc#roomconfig_whois", values);
        // Set that we want packets to include the real JID
        values = new ArrayList<String>();
        values.add("0");
        fields.put("anonymous", values);
        // Only broadcast presences of participants and visitors
        values = new ArrayList<String>();
        values.add("participant");
        values.add("visitor");
        fields.put("muc#roomconfig_presencebroadcast", values);
        RoomConfiguration conf = new RoomConfiguration(fields);
        conf.setTo(roomName);
        conf.setFrom(getFullJID());
        interceptorManager.invokeInterceptors(getJID().toBareJID(), conf, false, false);
        send(conf);
        interceptorManager.invokeInterceptors(getJID().toBareJID(), conf, false, true);
        // Create a new entry for the active session and the request made by the user
        requests.put(sessionID, request);
        // Invite the Agent to the new room
        Invitation invitation = new Invitation(agent.getJID().toString(), sessionID);
        invitation.setTo(roomName);
        invitation.setFrom(getFullJID());
        // Add workgroup extension that includes the JID of the user that made the request
        Element element = invitation.addChildElement("offer", "http://jabber.org/protocol/workgroup");
        element.addAttribute("jid", userJID);
        // Add custom extension that includes the sessionID
        element = invitation.addChildElement("session", "http://jivesoftware.com/protocol/workgroup");
        element.addAttribute("workgroup", sessionWorkgroup.getJID().toString());
        element.addAttribute("id", sessionID);
        // anonymous user
        if (request.isAnonymousUser()) {
            element = invitation.addChildElement("user", "http://jivesoftware.com/protocol/workgroup");
            element.addAttribute("id", request.getUserID());
        }
        interceptorManager.invokeInterceptors(getJID().toBareJID(), invitation, false, false);
        send(invitation);
        interceptorManager.invokeInterceptors(getJID().toBareJID(), invitation, false, true);
        // Invite the user to the new room
        sendUserInvitiation(request, roomName);
        // Notify the request that invitations for support have been sent
        request.invitationsSent(sessionID);
    } catch (Exception e) {
        Log.error(e.getMessage(), e);
    }
}
Also used : ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Element(org.dom4j.Element) ArrayList(java.util.ArrayList) Invitation(org.xmpp.muc.Invitation) JoinRoom(org.xmpp.muc.JoinRoom) DbWorkgroup(org.jivesoftware.xmpp.workgroup.utils.DbWorkgroup) RoomInterceptorManager(org.jivesoftware.xmpp.workgroup.interceptor.RoomInterceptorManager) PacketRejectedException(org.jivesoftware.xmpp.workgroup.interceptor.PacketRejectedException) SQLException(java.sql.SQLException) NotFoundException(org.jivesoftware.util.NotFoundException) RoomConfiguration(org.xmpp.muc.RoomConfiguration) Collection(java.util.Collection)

Aggregations

Element (org.dom4j.Element)2207 Document (org.dom4j.Document)500 ArrayList (java.util.ArrayList)294 List (java.util.List)249 SAXReader (org.dom4j.io.SAXReader)196 Iterator (java.util.Iterator)163 IQ (org.xmpp.packet.IQ)142 HashMap (java.util.HashMap)135 IOException (java.io.IOException)114 File (java.io.File)101 Attribute (org.dom4j.Attribute)97 StringReader (java.io.StringReader)90 DefaultElement (org.dom4j.tree.DefaultElement)87 JID (org.xmpp.packet.JID)87 Test (org.junit.jupiter.api.Test)78 DocumentException (org.dom4j.DocumentException)74 QName (org.dom4j.QName)68 AnnotatedElement (java.lang.reflect.AnnotatedElement)64 Node (org.dom4j.Node)64 Test (org.junit.Test)64