Search in sources :

Example 16 with PacketError

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

the class ChatSettingsManager method getChatSettingsByType.

/**
     * Send all WebChat settings for a particular Workgroup and type.
     *
     * @param packet the original packet that made the request.
     * @param workgroup the workgroup the packet was sent to.
     * @param type the type.
     */
public void getChatSettingsByType(IQ packet, Workgroup workgroup, int type) {
    IQ reply = IQ.createResultIQ(packet);
    // Retrieve the web chat setting.
    ChatSettings chatSettings = getChatSettings(workgroup);
    if (chatSettings == null) {
        reply.setChildElement(packet.getChildElement().createCopy());
        reply.setError(new PacketError(PacketError.Condition.item_not_found));
        workgroup.send(reply);
        return;
    }
    Element webSettings = reply.setChildElement("chat-settings", "http://jivesoftware.com/protocol/workgroup");
    for (ChatSetting setting : chatSettings.getChatSettings()) {
        if (setting.getType().getType() == type) {
            Element root = webSettings.addElement("chat-setting");
            root.addElement("key").setText(setting.getKey().toString());
            root.addElement("value").setText(setting.getValue());
            root.addElement("type").setText(Integer.toString(setting.getType().getType()));
        }
    }
    workgroup.send(reply);
}
Also used : Element(org.dom4j.Element) IQ(org.xmpp.packet.IQ) PacketError(org.xmpp.packet.PacketError)

Example 17 with PacketError

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

the class SearchPlugin method handleIQRequest.

/**
	 * Handles IQ requests. This method throws an IllegalArgumentException if an IQ stanza is supplied that is not a request (if the stanza
	 * is not of type 'get' or 'set'). This method will either throw an Exception, or return a non-null IQ stanza of type 'error' or
	 * 'result', as XMPP Core specifies that <strong>all</strong> IQ request stanza's (type 'get' or 'set') MUST be replied to.
	 * 
	 * @param iq
	 *            The IQ stanza that forms the request.
	 * @return The response to the request.
	 */
private IQ handleIQRequest(IQ iq) {
    // 'final' to ensure that it is set.
    final IQ replyPacket;
    if (iq == null) {
        throw new IllegalArgumentException("Argument 'iq' cannot be null.");
    }
    final IQ.Type type = iq.getType();
    if (type != IQ.Type.get && type != IQ.Type.set) {
        throw new IllegalArgumentException("Argument 'iq' must be of type 'get' or 'set'");
    }
    final Element childElement = iq.getChildElement();
    if (childElement == null) {
        replyPacket = IQ.createResultIQ(iq);
        replyPacket.setError(new PacketError(Condition.bad_request, org.xmpp.packet.PacketError.Type.modify, "IQ stanzas of type 'get' and 'set' MUST contain one and only one child element (RFC 3920 section 9.2.3)."));
        return replyPacket;
    }
    final String namespace = childElement.getNamespaceURI();
    if (namespace == null) {
        replyPacket = IQ.createResultIQ(iq);
        replyPacket.setError(Condition.feature_not_implemented);
        return replyPacket;
    }
    if (namespace.equals(NAMESPACE_JABBER_IQ_SEARCH)) {
        replyPacket = handleSearchRequest(iq);
    } else if (namespace.equals(IQDiscoInfoHandler.NAMESPACE_DISCO_INFO)) {
        replyPacket = handleDiscoInfo(iq);
    } else if (namespace.equals(IQDiscoItemsHandler.NAMESPACE_DISCO_ITEMS)) {
        replyPacket = IQ.createResultIQ(iq);
        replyPacket.setChildElement("query", IQDiscoItemsHandler.NAMESPACE_DISCO_ITEMS);
    } else {
        // don't known what to do with this.
        replyPacket = IQ.createResultIQ(iq);
        replyPacket.setError(Condition.feature_not_implemented);
    }
    return replyPacket;
}
Also used : Element(org.dom4j.Element) IQ(org.xmpp.packet.IQ) PacketError(org.xmpp.packet.PacketError) Type(org.xmpp.packet.IQ.Type)

Example 18 with PacketError

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

the class IQRosterHandler method manageRoster.

/**
     * The packet is a typical 'set' or 'get' update targeted at the server.
     * Notice that the set could be a roster removal in which case we have to
     * generate a local roster removal update as well as a new roster removal
     * to send to the the roster item's owner.
     *
     * @param packet The packet that triggered this update
     * @return Either a response to the roster update or null if the packet is corrupt and the session was closed down
     */
private IQ manageRoster(org.xmpp.packet.Roster packet) throws UnauthorizedException, UserAlreadyExistsException, SharedGroupException {
    IQ returnPacket = null;
    JID sender = packet.getFrom();
    IQ.Type type = packet.getType();
    try {
        if ((sender.getNode() == null || !RosterManager.isRosterServiceEnabled() || !userManager.isRegisteredUser(sender.getNode())) && IQ.Type.get == type) {
            // If anonymous user asks for his roster or roster service is disabled then
            // return an empty roster
            IQ reply = IQ.createResultIQ(packet);
            reply.setChildElement("query", "jabber:iq:roster");
            return reply;
        }
        if (!localServer.isLocal(sender)) {
            // Sender belongs to a remote server so discard this IQ request
            Log.warn("Discarding IQ roster packet of remote user: " + packet);
            return null;
        }
        Roster cachedRoster = userManager.getUser(sender.getNode()).getRoster();
        if (IQ.Type.get == type) {
            returnPacket = cachedRoster.getReset();
            returnPacket.setType(IQ.Type.result);
            returnPacket.setTo(sender);
            returnPacket.setID(packet.getID());
            // Force delivery of the response because we need to trigger
            // a presence probe from all contacts
            deliverer.deliver(returnPacket);
            returnPacket = null;
        } else if (IQ.Type.set == type) {
            returnPacket = IQ.createResultIQ(packet);
            // The <query/> element contains more than one <item/> child element.
            if (packet.getItems().size() > 1) {
                returnPacket.setError(new PacketError(PacketError.Condition.bad_request, PacketError.Type.modify, "Query contains more than one item"));
            } else {
                for (org.xmpp.packet.Roster.Item item : packet.getItems()) {
                    if (item.getSubscription() == org.xmpp.packet.Roster.Subscription.remove) {
                        if (removeItem(cachedRoster, packet.getFrom(), item) == null) {
                            // RFC 6121 2.5.3.  Error Cases: If the value of the 'jid' attribute specifies an item that is not in the roster, then the server MUST return an <item-not-found/> stanza error.
                            returnPacket.setError(PacketError.Condition.item_not_found);
                        }
                    } else {
                        PacketError error = checkGroups(item.getGroups());
                        if (error != null) {
                            returnPacket.setError(error);
                        } else {
                            if (cachedRoster.isRosterItem(item.getJID())) {
                                // existing item
                                RosterItem cachedItem = cachedRoster.getRosterItem(item.getJID());
                                cachedItem.setAsCopyOf(item);
                                cachedRoster.updateRosterItem(cachedItem);
                            } else {
                                // new item
                                cachedRoster.createRosterItem(item);
                            }
                        }
                    }
                }
            }
        }
    } catch (UserNotFoundException e) {
        throw new UnauthorizedException(e);
    }
    return returnPacket;
}
Also used : UserNotFoundException(org.jivesoftware.openfire.user.UserNotFoundException) RosterItem(org.jivesoftware.openfire.roster.RosterItem) RosterItem(org.jivesoftware.openfire.roster.RosterItem) JID(org.xmpp.packet.JID) Roster(org.jivesoftware.openfire.roster.Roster) IQ(org.xmpp.packet.IQ) UnauthorizedException(org.jivesoftware.openfire.auth.UnauthorizedException) PacketError(org.xmpp.packet.PacketError)

Example 19 with PacketError

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

the class FileTransferProxy method handleIQ.

public boolean handleIQ(IQ packet) throws UnauthorizedException {
    Element childElement = packet.getChildElement();
    String namespace = null;
    // ignore errors
    if (packet.getType() == IQ.Type.error) {
        return true;
    }
    if (childElement != null) {
        namespace = childElement.getNamespaceURI();
    }
    if ("http://jabber.org/protocol/disco#info".equals(namespace)) {
        IQ reply = XMPPServer.getInstance().getIQDiscoInfoHandler().handleIQ(packet);
        router.route(reply);
        return true;
    } else if ("http://jabber.org/protocol/disco#items".equals(namespace)) {
        // a component
        IQ reply = XMPPServer.getInstance().getIQDiscoItemsHandler().handleIQ(packet);
        router.route(reply);
        return true;
    } else if (FileTransferManager.NAMESPACE_BYTESTREAMS.equals(namespace)) {
        if (packet.getType() == IQ.Type.get) {
            IQ reply = IQ.createResultIQ(packet);
            Element newChild = reply.setChildElement("query", FileTransferManager.NAMESPACE_BYTESTREAMS);
            final String externalIP = JiveGlobals.getProperty(PROPERTY_EXTERNALIP);
            if (externalIP != null && !externalIP.isEmpty()) {
                // OF-512: Override the automatic detection with a specific address (useful for NATs, proxies, etc)
                final Element response = newChild.addElement("streamhost");
                response.addAttribute("jid", getServiceDomain());
                response.addAttribute("host", externalIP);
                response.addAttribute("port", String.valueOf(connectionManager.getProxyPort()));
            } else {
                // Report all network addresses that we know that we're servicing.
                for (final InetAddress address : getAddresses()) {
                    final Element response = newChild.addElement("streamhost");
                    response.addAttribute("jid", getServiceDomain());
                    response.addAttribute("host", address.getHostAddress());
                    response.addAttribute("port", String.valueOf(connectionManager.getProxyPort()));
                }
            }
            router.route(reply);
            return true;
        } else if (packet.getType() == IQ.Type.set) {
            String sid = childElement.attributeValue("sid");
            JID from = packet.getFrom();
            JID to = new JID(childElement.elementTextTrim("activate"));
            IQ reply = IQ.createResultIQ(packet);
            try {
                connectionManager.activate(from, to, sid);
            } catch (IllegalArgumentException ie) {
                Log.error("Error activating connection", ie);
                reply.setType(IQ.Type.error);
                reply.setError(new PacketError(PacketError.Condition.not_allowed));
            }
            router.route(reply);
            return true;
        }
    }
    return false;
}
Also used : JID(org.xmpp.packet.JID) Element(org.dom4j.Element) IQ(org.xmpp.packet.IQ) PacketError(org.xmpp.packet.PacketError) InetAddress(java.net.InetAddress)

Example 20 with PacketError

use of org.xmpp.packet.PacketError 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)

Aggregations

PacketError (org.xmpp.packet.PacketError)35 IQ (org.xmpp.packet.IQ)31 Element (org.dom4j.Element)29 AgentNotFoundException (org.jivesoftware.xmpp.workgroup.AgentNotFoundException)10 JID (org.xmpp.packet.JID)7 AgentSession (org.jivesoftware.xmpp.workgroup.AgentSession)4 Connection (java.sql.Connection)3 PreparedStatement (java.sql.PreparedStatement)3 ResultSet (java.sql.ResultSet)3 File (java.io.File)2 IOException (java.io.IOException)2 SQLException (java.sql.SQLException)2 HashMap (java.util.HashMap)2 UserNotFoundException (org.jivesoftware.openfire.user.UserNotFoundException)2 NotFoundException (org.jivesoftware.util.NotFoundException)2 Agent (org.jivesoftware.xmpp.workgroup.Agent)2 DbProperties (org.jivesoftware.xmpp.workgroup.DbProperties)2 WorkgroupManager (org.jivesoftware.xmpp.workgroup.WorkgroupManager)2 PacketRejectedException (org.jivesoftware.xmpp.workgroup.interceptor.PacketRejectedException)2 UserRequest (org.jivesoftware.xmpp.workgroup.request.UserRequest)2