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);
}
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;
}
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;
}
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;
}
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;
}
}
}
}
Aggregations