Hello,
I am currently working with Smack 4.0.2 on android (using the asmack 4.0.2 lib) and found the following bug related to SASL-Authentication to the facebook chat:
When connecting to chat.facebook.com via SASL PLAIN mechanism, I couldn't connect and got the the following log output:
W/IQReplyFilter(7334): Rejected potentially spoofed reply to IQ-packet. Filter settings: packetId=25bp0-0, to=null, local=null,
server=chat.facebook.com. Received packet with from=user.name.1@chat.facebook.com
When digging further into the issue, I found out that problem originates in the IQReplyFilter class which, according to the javadoc checks the "from" adress to ignore forged replies:
(Excerpt from javadoc)
We accept a from address if one of the following is true:
It matches the to address of the request.
The to address of the request was empty and the from address matches either the bare jid of the server or the (bare or full jid) of the client.
To to was our bare address and the from is empty.
Well, I thought, the facebook server responds with a "from" adress of user.name.1@chat.facebook.com, so actually IT SHOULD WORK right? (that's case 2 of the conditions mentioned in the javadoc above: the from matches the bare jid of the client)
So why doesn't it work?
Digging further into the code of IQReplyFilter I found the problem: (see marked-up code and explanation below)
public IQReplyFilter(IQ iqPacket, XMPPConnection conn) { to = iqPacket.getTo(); if (conn.getUser() == null) { // We have not yet been assigned a username, this can happen if the connection is // in an early stage, i.e. when performing the SASL auth. local = null; }else{ local = conn.getUser().toLowerCase(Locale.US); } server = conn.getServiceName().toLowerCase(Locale.US); packetId = iqPacket.getPacketID(); PacketFilter iqFilter = new OrFilter(new IQTypeFilter(IQ.Type.ERROR), new IQTypeFilter(IQ.Type.RESULT)); PacketFilter idFilter = new PacketIDFilter(iqPacket); iqAndIdFilter = new AndFilter(iqFilter, idFilter); fromFilter = new OrFilter(); fromFilter.addFilter(FromMatchesFilter.createFull(to)); if (to == null) { if (local != null) fromFilter.addFilter(FromMatchesFilter.createBare(local)); fromFilter.addFilter(FromMatchesFilter.createFull(server)); } elseif (local != null&& to.toLowerCase(Locale.US).equals(StringUtils.parseBareAddress(local))) { fromFilter.addFilter(FromMatchesFilter.createFull(null)); } }
So what happened here?
Well, because the username has not yet been assigned in the early stages of SASL authentication, "local" is set to null. This means that when in the same constructor a few lines down the fromFilter is built, the local attribute is not yet set, and so it just creates a matching filter for the server jid (in this case chat.facebook.com).
So when facebook responds not with the bare server id but with the bare client jid in the "from" field of the IQ packet (user.name.1@chat.facebook.com) it leads to the packet being rejected. (from filter incorrectly only matches server jid chat.facebook.com when it should also match client jid user.name.1@chat.facebook.com)
Possible fix:
for the time being I use my own subclass of IQReplyFilter which overwrites the accept method to not check the fromFilter and so basically let all the packets through regardless of the from attribute. This is working for testing purposes but obviously not satisfactory for security purposes.
A possible fix might include to somehow add the bare and full client jid to the fromFilter in later stages of the SASL auth when the username has been aquired? Sorry I don't know enough about xmpp to really say...
P.S. Oh yeah, I hope this is the right place to report this issue? If not feel free to move it to the right place. I was also searching for an email adress to report this but couldn't find any.