Search in sources :

Example 11 with ForbiddenException

use of org.jivesoftware.openfire.muc.ForbiddenException in project Openfire by igniterealtime.

the class LocalMUCRoom method addNone.

@Override
public List<Presence> addNone(JID jid, MUCRole senderRole) throws ForbiddenException, ConflictException {
    final JID bareJID = jid.asBareJID();
    MUCRole.Affiliation oldAffiliation = MUCRole.Affiliation.none;
    boolean jidWasAffiliated = false;
    lock.writeLock().lock();
    try {
        if (MUCRole.Affiliation.admin != senderRole.getAffiliation() && MUCRole.Affiliation.owner != senderRole.getAffiliation()) {
            throw new ForbiddenException();
        }
        // Check that the room always has an owner
        if (owners.contains(bareJID) && owners.size() == 1) {
            throw new ConflictException();
        }
        // Remove the jid from ALL the affiliation lists
        if (removeOwner(bareJID)) {
            oldAffiliation = MUCRole.Affiliation.owner;
            jidWasAffiliated = true;
        } else if (removeAdmin(bareJID)) {
            oldAffiliation = MUCRole.Affiliation.admin;
            jidWasAffiliated = true;
        } else if (removeMember(bareJID)) {
            oldAffiliation = MUCRole.Affiliation.member;
            jidWasAffiliated = true;
        } else if (removeOutcast(bareJID)) {
            oldAffiliation = MUCRole.Affiliation.outcast;
        }
        // Remove the affiliation of this user from the DB if the room is persistent
        MUCPersistenceManager.removeAffiliationFromDB(this, bareJID, oldAffiliation);
    } finally {
        lock.writeLock().unlock();
    }
    // Update other cluster nodes with new affiliation
    CacheFactory.doClusterTask(new AddAffiliation(this, jid.toBareJID(), MUCRole.Affiliation.none));
    if (jidWasAffiliated) {
        // based on the group(s) of the affected user(s)
        return applyAffiliationChange(senderRole, bareJID, null);
    } else {
        // no presence updates needed
        return Collections.emptyList();
    }
}
Also used : ForbiddenException(org.jivesoftware.openfire.muc.ForbiddenException) MUCRole(org.jivesoftware.openfire.muc.MUCRole) GroupJID(org.jivesoftware.openfire.group.GroupJID) JID(org.xmpp.packet.JID) ConflictException(org.jivesoftware.openfire.muc.ConflictException) AddAffiliation(org.jivesoftware.openfire.muc.cluster.AddAffiliation)

Example 12 with ForbiddenException

use of org.jivesoftware.openfire.muc.ForbiddenException in project Openfire by igniterealtime.

the class MultiUserChatServiceImpl method process.

/**
 * Processes an IQ stanza.
 *
 * @param packet          The stanza to route
 * @param room            The room that the stanza was addressed to.
 * @param preExistingRole The role of this user in the addressed room prior to processing of this stanza, if any.
 */
private void process(@Nonnull final IQ packet, @Nullable final MUCRoom room, @Nullable final MUCRole preExistingRole) {
    // Packets to a specific node/group/room
    if (preExistingRole == null || room == null) {
        Log.debug("Ignoring stanza received from a non-occupant of a room (room might not even exist): {}", packet.toXML());
        if (packet.isRequest()) {
            // If a non-occupant sends a disco to an address of the form <room@service/nick>, a MUC service MUST
            // return a <bad-request/> error. http://xmpp.org/extensions/xep-0045.html#disco-occupant
            sendErrorPacket(packet, PacketError.Condition.bad_request, "You are not an occupant of this room.");
        }
        return;
    }
    if (packet.isResponse()) {
        // Only process IQ result packet if it's a private packet sent to another room occupant
        if (packet.getTo().getResource() != null) {
            try {
                // User is sending an IQ result packet to another room occupant
                room.sendPrivatePacket(packet, preExistingRole);
            } catch (NotFoundException | ForbiddenException e) {
                // Do nothing. No error will be sent to the sender of the IQ result packet
                Log.debug("Silently ignoring an IQ response sent to the room as a private message that caused an exception while being processed: {}", packet.toXML(), e);
            }
        } else {
            Log.trace("Silently ignoring an IQ response sent to the room, but not as a private message: {}", packet.toXML());
        }
    } else {
        // Check and reject conflicting packets with conflicting roles In other words, another user already has this nickname
        if (!preExistingRole.getUserAddress().equals(packet.getFrom())) {
            Log.debug("Rejecting conflicting stanza with conflicting roles: {}", packet.toXML());
            sendErrorPacket(packet, PacketError.Condition.conflict, "Another user uses this nickname.");
            return;
        }
        try {
            // TODO Analyze if it is correct for these first two blocks to be processed without evaluating if they're addressed to the room or if they're a PM.
            Element query = packet.getElement().element("query");
            if (query != null && "http://jabber.org/protocol/muc#owner".equals(query.getNamespaceURI())) {
                room.getIQOwnerHandler().handleIQ(packet, preExistingRole);
            } else if (query != null && "http://jabber.org/protocol/muc#admin".equals(query.getNamespaceURI())) {
                room.getIQAdminHandler().handleIQ(packet, preExistingRole);
            } else {
                final String toNickname = packet.getTo().getResource();
                if (toNickname != null) {
                    // User is sending to a room occupant.
                    final boolean selfPingEnabled = JiveGlobals.getBooleanProperty("xmpp.muc.self-ping.enabled", true);
                    if (selfPingEnabled && toNickname.equals(preExistingRole.getNickname()) && packet.isRequest() && packet.getElement().element(QName.get(IQPingHandler.ELEMENT_NAME, IQPingHandler.NAMESPACE)) != null) {
                        Log.trace("User '{}' is sending an IQ 'ping' to itself. See XEP-0410: MUC Self-Ping (Schrödinger's Chat).", packet.getFrom());
                        XMPPServer.getInstance().getPacketRouter().route(IQ.createResultIQ(packet));
                    } else {
                        Log.trace("User '{}' is sending an IQ stanza to another room occupant (as a PM) with nickname: '{}'.", packet.getFrom(), toNickname);
                        room.sendPrivatePacket(packet, preExistingRole);
                    }
                } else {
                    Log.debug("An IQ request was addressed to the MUC room '{}' which cannot answer it: {}", room.getName(), packet.toXML());
                    sendErrorPacket(packet, PacketError.Condition.bad_request, "IQ request cannot be processed by the MUC room itself.");
                }
            }
        } catch (NotAcceptableException e) {
            Log.debug("Unable to process IQ stanza: room requires a password, but none was supplied.", e);
            sendErrorPacket(packet, PacketError.Condition.not_acceptable, "Room requires a password, but none was supplied.");
        } catch (ForbiddenException e) {
            Log.debug("Unable to process IQ stanza: sender don't have authorization to perform the request.", e);
            sendErrorPacket(packet, PacketError.Condition.forbidden, "You don't have authorization to perform this request.");
        } catch (NotFoundException e) {
            Log.debug("Unable to process IQ stanza: the intended recipient is not available.", e);
            sendErrorPacket(packet, PacketError.Condition.recipient_unavailable, "The intended recipient is not available.");
        } catch (ConflictException e) {
            Log.debug("Unable to process IQ stanza: processing this request would leave the room in an invalid state (eg: without owners).", e);
            sendErrorPacket(packet, PacketError.Condition.conflict, "Processing this request would leave the room in an invalid state (eg: without owners).");
        } catch (NotAllowedException e) {
            Log.debug("Unable to process IQ stanza: an owner or administrator cannot be banned from the room.", e);
            sendErrorPacket(packet, PacketError.Condition.not_allowed, "An owner or administrator cannot be banned from the room.");
        } catch (CannotBeInvitedException e) {
            Log.debug("Unable to process IQ stanza: user being invited as a result of being added to a members-only room still does not have permission.", e);
            sendErrorPacket(packet, PacketError.Condition.not_acceptable, "User being invited as a result of being added to a members-only room still does not have permission.");
        } catch (Exception e) {
            Log.error("An unexpected exception occurred while processing IQ stanza: {}", packet.toXML(), e);
            sendErrorPacket(packet, PacketError.Condition.internal_server_error, "An unexpected exception occurred while processing your request.");
        }
    }
}
Also used : ForbiddenException(org.jivesoftware.openfire.muc.ForbiddenException) CannotBeInvitedException(org.jivesoftware.openfire.muc.CannotBeInvitedException) NotAllowedException(org.jivesoftware.openfire.muc.NotAllowedException) ConflictException(org.jivesoftware.openfire.muc.ConflictException) NotAcceptableException(org.jivesoftware.openfire.muc.NotAcceptableException) Element(org.dom4j.Element) NotFoundException(org.jivesoftware.util.NotFoundException) UserNotFoundException(org.jivesoftware.openfire.user.UserNotFoundException) ForbiddenException(org.jivesoftware.openfire.muc.ForbiddenException) RoomLockedException(org.jivesoftware.openfire.muc.RoomLockedException) CannotBeInvitedException(org.jivesoftware.openfire.muc.CannotBeInvitedException) NotAllowedException(org.jivesoftware.openfire.muc.NotAllowedException) PacketException(org.jivesoftware.openfire.PacketException) UnauthorizedException(org.jivesoftware.openfire.auth.UnauthorizedException) NotFoundException(org.jivesoftware.util.NotFoundException) ConflictException(org.jivesoftware.openfire.muc.ConflictException) RegistrationRequiredException(org.jivesoftware.openfire.muc.RegistrationRequiredException) UserAlreadyExistsException(org.jivesoftware.openfire.user.UserAlreadyExistsException) UserNotFoundException(org.jivesoftware.openfire.user.UserNotFoundException) NotAcceptableException(org.jivesoftware.openfire.muc.NotAcceptableException) ServiceUnavailableException(org.jivesoftware.openfire.muc.ServiceUnavailableException)

Example 13 with ForbiddenException

use of org.jivesoftware.openfire.muc.ForbiddenException in project Openfire by igniterealtime.

the class MultiUserChatServiceImpl method processRoomJoinRequest.

/**
 * Process a request to join a room.
 *
 * This method might be invoked for a room that does not yet exist (when the presence is a room-creation request).
 *
 * @param packet   The stanza representing the nickname-change request.
 * @param roomName The name of the room that the stanza was addressed to.
 * @param room     The room that the stanza was addressed to, if it exists.
 * @param nickname The requested nickname.
 * @return the room that handled the request
 */
private MUCRoom processRoomJoinRequest(@Nonnull final Presence packet, @Nonnull final String roomName, @Nullable MUCRoom room, @Nullable String nickname) {
    Log.trace("Processing join request from '{}' for room '{}'", packet.getFrom(), roomName);
    if (nickname == null) {
        Log.debug("Request from '{}' to join room '{}' rejected: request did not specify a nickname", packet.getFrom(), roomName);
        // If the user does not specify a room nickname (note the bare JID on the 'from' address in the following example), the service MUST return a <jid-malformed/> error
        if (packet.getType() != Presence.Type.error) {
            sendErrorPacket(packet, PacketError.Condition.jid_malformed, "A nickname (resource-part) is required in order to join a room.");
        }
        return null;
    }
    if (!packet.isAvailable()) {
        Log.debug("Request from '{}' to join room '{}' rejected: request unexpectedly provided a presence stanza of type '{}'. Expected none.", packet.getFrom(), roomName, packet.getType());
        if (packet.getType() != Presence.Type.error) {
            sendErrorPacket(packet, PacketError.Condition.unexpected_request, "Unexpected stanza type: " + packet.getType());
        }
        return null;
    }
    if (room == null) {
        try {
            // Create the room
            room = getChatRoom(roomName, packet.getFrom());
        } catch (NotAllowedException e) {
            Log.debug("Request from '{}' to join room '{}' rejected: user does not have permission to create a new room.", packet.getFrom(), roomName, e);
            sendErrorPacket(packet, PacketError.Condition.not_allowed, "You do not have permission to create a new room.");
            return null;
        }
    }
    try {
        // User must support MUC in order to create a room
        HistoryRequest historyRequest = null;
        String password = null;
        // Check for password & requested history if client supports MUC
        final Element mucInfo = packet.getChildElement("x", "http://jabber.org/protocol/muc");
        if (mucInfo != null) {
            password = mucInfo.elementTextTrim("password");
            if (mucInfo.element("history") != null) {
                historyRequest = new HistoryRequest(mucInfo);
            }
        }
        // The user joins the room
        final MUCRole role = room.joinRoom(nickname, password, historyRequest, packet.getFrom(), packet.createCopy());
        // unlock the room thus creating an "instant" room
        if (mucInfo == null && room.isLocked() && !room.isManuallyLocked()) {
            room.unlock(role);
        }
    } catch (UnauthorizedException e) {
        Log.debug("Request from '{}' to join room '{}' rejected: user not authorized to create or join the room.", packet.getFrom(), roomName, e);
        sendErrorPacket(packet, PacketError.Condition.not_authorized, "You're not authorized to create or join the room.");
    } catch (ServiceUnavailableException e) {
        Log.debug("Request from '{}' to join room '{}' rejected: the maximum number of users of the room has been reached.", packet.getFrom(), roomName, e);
        sendErrorPacket(packet, PacketError.Condition.service_unavailable, "The maximum number of users of the room has been reached.");
    } catch (UserAlreadyExistsException | ConflictException e) {
        Log.debug("Request from '{}' to join room '{}' rejected: the requested nickname '{}' is being used by someone else in the room.", packet.getFrom(), roomName, nickname, e);
        sendErrorPacket(packet, PacketError.Condition.conflict, "The nickname that is being used is used by someone else.");
    } catch (RoomLockedException e) {
        // If a user attempts to enter a room while it is "locked" (i.e., before the room creator provides an initial configuration and therefore before the room officially exists), the service MUST refuse entry and return an <item-not-found/> error to the user
        Log.debug("Request from '{}' to join room '{}' rejected: room is locked.", packet.getFrom(), roomName, e);
        sendErrorPacket(packet, PacketError.Condition.item_not_found, "This room is locked (it might not have been configured yet).");
    } catch (ForbiddenException e) {
        Log.debug("Request from '{}' to join room '{}' rejected: user not authorized join the room.", packet.getFrom(), roomName, e);
        sendErrorPacket(packet, PacketError.Condition.forbidden, "You're not allowed to join this room.");
    } catch (RegistrationRequiredException e) {
        Log.debug("Request from '{}' to join room '{}' rejected: room is member-only, user is not a member.", packet.getFrom(), roomName, e);
        sendErrorPacket(packet, PacketError.Condition.registration_required, "This is a member-only room. Membership is required.");
    } catch (NotAcceptableException e) {
        Log.debug("Request from '{}' to join room '{}' rejected: user attempts to use nickname '{}' which is different from the reserved nickname.", packet.getFrom(), roomName, nickname, e);
        sendErrorPacket(packet, PacketError.Condition.not_acceptable, "You're trying to join with a nickname different than the reserved nickname.");
    }
    return room;
}
Also used : ForbiddenException(org.jivesoftware.openfire.muc.ForbiddenException) NotAllowedException(org.jivesoftware.openfire.muc.NotAllowedException) ConflictException(org.jivesoftware.openfire.muc.ConflictException) Element(org.dom4j.Element) HistoryRequest(org.jivesoftware.openfire.muc.HistoryRequest) ServiceUnavailableException(org.jivesoftware.openfire.muc.ServiceUnavailableException) UserAlreadyExistsException(org.jivesoftware.openfire.user.UserAlreadyExistsException) MUCRole(org.jivesoftware.openfire.muc.MUCRole) NotAcceptableException(org.jivesoftware.openfire.muc.NotAcceptableException) RoomLockedException(org.jivesoftware.openfire.muc.RoomLockedException) UnauthorizedException(org.jivesoftware.openfire.auth.UnauthorizedException) RegistrationRequiredException(org.jivesoftware.openfire.muc.RegistrationRequiredException)

Example 14 with ForbiddenException

use of org.jivesoftware.openfire.muc.ForbiddenException in project Openfire by igniterealtime.

the class IQMUCRegisterHandler method handleIQ.

public IQ handleIQ(IQ packet) {
    IQ reply = null;
    // Get the target room
    MUCRoom room = null;
    String name = packet.getTo().getNode();
    if (name == null) {
        // Can't register with the service itself, so answer a feature-not-implemented error
        reply = IQ.createResultIQ(packet);
        reply.setChildElement(packet.getChildElement().createCopy());
        reply.setError(PacketError.Condition.feature_not_implemented);
        return reply;
    }
    final Lock lock = mucService.getChatRoomLock(name);
    lock.lock();
    try {
        room = mucService.getChatRoom(name);
        if (room == null) {
            // The room doesn't exist so answer a NOT_FOUND error
            reply = IQ.createResultIQ(packet);
            reply.setChildElement(packet.getChildElement().createCopy());
            reply.setError(PacketError.Condition.item_not_found);
            return reply;
        } else if (!room.isRegistrationEnabled() || (packet.getFrom() != null && MUCRole.Affiliation.outcast == room.getAffiliation(packet.getFrom().asBareJID()))) {
            // The room does not accept users to register or
            // the user is an outcast and is not allowed to register
            reply = IQ.createResultIQ(packet);
            reply.setChildElement(packet.getChildElement().createCopy());
            reply.setError(PacketError.Condition.not_allowed);
            return reply;
        }
        if (IQ.Type.get == packet.getType()) {
            reply = IQ.createResultIQ(packet);
            String nickname = room.getReservedNickname(packet.getFrom());
            Element currentRegistration = probeResult.createCopy();
            if (nickname != null) {
                // The user is already registered with the room so answer a completed form
                ElementUtil.setProperty(currentRegistration, "query.registered", null);
                currentRegistration.addElement("username").addText(nickname);
                Element form = currentRegistration.element(QName.get("x", "jabber:x:data"));
                currentRegistration.remove(form);
                // @SuppressWarnings("unchecked")
                // Iterator<Element> fields = form.elementIterator("field");
                // 
                // Element field;
                // while (fields.hasNext()) {
                // field = fields.next();
                // if ("muc#register_roomnick".equals(field.attributeValue("var"))) {
                // field.addElement("value").addText(nickname);
                // }
                // }
                reply.setChildElement(currentRegistration);
            } else {
                // The user is not registered with the room so answer an empty form
                reply.setChildElement(currentRegistration);
            }
        } else if (IQ.Type.set == packet.getType()) {
            try {
                // Keep a registry of the updated presences
                List<Presence> presences = new ArrayList<>();
                reply = IQ.createResultIQ(packet);
                Element iq = packet.getChildElement();
                if (ElementUtil.includesProperty(iq, "query.remove")) {
                    // The user is deleting his registration
                    presences.addAll(room.addNone(packet.getFrom(), room.getRole()));
                } else {
                    // The user is trying to register with a room
                    Element formElement = iq.element("x");
                    // Check if a form was used to provide the registration info
                    if (formElement != null) {
                        // Get the sent form
                        final DataForm registrationForm = new DataForm(formElement);
                        // Get the desired nickname sent in the form
                        List<String> values = registrationForm.getField("muc#register_roomnick").getValues();
                        String nickname = (!values.isEmpty() ? values.get(0) : null);
                        // TODO The rest of the fields of the form are ignored. If we have a
                        // requirement in the future where we need those fields we'll have to change
                        // MUCRoom.addMember in order to receive a RegistrationInfo (new class)
                        // Add the new member to the members list
                        presences.addAll(room.addMember(packet.getFrom(), nickname, room.getRole()));
                    } else {
                        reply.setChildElement(packet.getChildElement().createCopy());
                        reply.setError(PacketError.Condition.bad_request);
                    }
                }
                // Send the updated presences to the room occupants
                for (Presence presence : presences) {
                    room.send(presence, room.getRole());
                }
            } catch (ForbiddenException e) {
                reply = IQ.createResultIQ(packet);
                reply.setChildElement(packet.getChildElement().createCopy());
                reply.setError(PacketError.Condition.forbidden);
            } catch (ConflictException e) {
                reply = IQ.createResultIQ(packet);
                reply.setChildElement(packet.getChildElement().createCopy());
                reply.setError(PacketError.Condition.conflict);
            } catch (Exception e) {
                Log.error(e.getMessage(), e);
            }
        }
        // Ensure that other cluster nodes see the changes applied above.
        mucService.syncChatRoom(room);
    } finally {
        lock.unlock();
    }
    return reply;
}
Also used : ForbiddenException(org.jivesoftware.openfire.muc.ForbiddenException) MUCRoom(org.jivesoftware.openfire.muc.MUCRoom) ConflictException(org.jivesoftware.openfire.muc.ConflictException) Element(org.dom4j.Element) IQ(org.xmpp.packet.IQ) DataForm(org.xmpp.forms.DataForm) Presence(org.xmpp.packet.Presence) ArrayList(java.util.ArrayList) List(java.util.List) ForbiddenException(org.jivesoftware.openfire.muc.ForbiddenException) ConflictException(org.jivesoftware.openfire.muc.ConflictException) Lock(java.util.concurrent.locks.Lock)

Aggregations

ForbiddenException (org.jivesoftware.openfire.muc.ForbiddenException)14 ConflictException (org.jivesoftware.openfire.muc.ConflictException)10 MUCRole (org.jivesoftware.openfire.muc.MUCRole)8 JID (org.xmpp.packet.JID)8 GroupJID (org.jivesoftware.openfire.group.GroupJID)7 Element (org.dom4j.Element)5 CannotBeInvitedException (org.jivesoftware.openfire.muc.CannotBeInvitedException)4 AddAffiliation (org.jivesoftware.openfire.muc.cluster.AddAffiliation)4 UnauthorizedException (org.jivesoftware.openfire.auth.UnauthorizedException)3 NotAcceptableException (org.jivesoftware.openfire.muc.NotAcceptableException)3 NotAllowedException (org.jivesoftware.openfire.muc.NotAllowedException)3 RegistrationRequiredException (org.jivesoftware.openfire.muc.RegistrationRequiredException)3 RoomLockedException (org.jivesoftware.openfire.muc.RoomLockedException)3 ServiceUnavailableException (org.jivesoftware.openfire.muc.ServiceUnavailableException)3 UserAlreadyExistsException (org.jivesoftware.openfire.user.UserAlreadyExistsException)3 UserNotFoundException (org.jivesoftware.openfire.user.UserNotFoundException)3 NotFoundException (org.jivesoftware.util.NotFoundException)3 Message (org.xmpp.packet.Message)3 Presence (org.xmpp.packet.Presence)3 GroupNotFoundException (org.jivesoftware.openfire.group.GroupNotFoundException)2