Not logged in. · Lost password · Register
Forum: agsXMPP RSS
Avatar
preraksanghvi #1
Member since Nov 2008 · 6 posts
Group memberships: Members
Show profile · Link to this post
Subject: Openfire with BOSH + Digest-MD5 + "@" sign in username fails auth; PLAIN text succeeds
I am using agsXMPP to connect to Openfire using BOSH.  It works fine and defaults to DIGEST-MD5 auth just fine, until I try a username with "@" in it.  Debugging the code indicated the agsXMPP is escaping the @ sign to \40 correctly, but when the challenge response reaches the server, openfire reads "user@domain.com" as "user40domain.com".  It "loses" the \ and hence authentication fails.

At first glance, it looks like this may be an Openfire issue rather than agsXMPP, but I was wondering if someone has experience with this setup. 

If I switch the SASL mechanism to PLAIN in OnSaslStart event, then the authentication succeeds just fine, but of course this is not ideal.

Thanks in advance,
Prerak
This post was edited on 2008-12-11, 18:43 by preraksanghvi.
Avatar
Alex #2
Member since Feb 2003 · 4297 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
Hello Prerak,

its the job of the client to escape jids. agsXMPP escapes the "@" to "\40". The user should also be registered with \40 on the server, there is no need to unescape the jid on the server.
Did you try this jids on other servers?

Alex
Avatar
preraksanghvi #3
Member since Nov 2008 · 6 posts
Group memberships: Members
Show profile · Link to this post
Thanks for the reply, Alex.  I did see that agsXMPP escaped the @ sign to \40.  The GenerateResponse method in agsXMPP.sasl.DigestMD5.Step2 seems to use the correctly escaped string to generate the response.

The user is registered on openfire with \40 (as "p\40gammafs.com").  I debugged Openfire's SASLAuthentication routine and found that after decoding the Base64 string, the username was indeed correctly set with \40.  Openfire is messing up somewhere later in the processing. (This is a bit disconcerting because Openfire uses the standard sun library for sasl - com.sun.security.sasl.digest.* classes).

Thanks for your help - I will raise this issue in the Openfire support forum.
Avatar
preraksanghvi #4
Member since Nov 2008 · 6 posts
Group memberships: Members
Show profile · Link to this post
Found the reason - not sure whose problem it is though.

Java standard DigestMD5Server will ignore all instances of backslashes ('\\') if the value being parsed from the MD5 message is quoted (by using double quotes).  agsXMPP adds quotes around the username and this converts the username from u\40d.com to u40d.com.

The simple hack that makes it work is below. In agsXMPP.sasl.DigestMD5.Step2 in GenerateMessage(), I replaced:

sb.Append(AddQuotes(this.Username));

with:

sb.Append(this.Username);

I am not sure which is correct - whether to put the username in quotes or not. 

Alex, can you comment on this please?

Thanks,
Prerak
Avatar
Alex #5
Member since Feb 2003 · 4297 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
IMHO the quotes are required, otherwise it should fail also for "normal" in escaped jids.
In Step 1 RFC2831 is very clear to me about the quotes, but does not mention them in Step 2, but all the examples at the end of the RFC show the usernames in quotes.

Alex

[1] http://www.ietf.org/rfc/rfc2831.txt
This post was edited on 2008-12-16, 15:43 by Alex.
Avatar
preraksanghvi #6
Member since Nov 2008 · 6 posts
Group memberships: Members
Show profile · Link to this post
You're right about the RFC in that it allows, or even mandates, quotes (http://www.faqs.org/rfcs/rfc2831.html).

However, section 7.2 says this:

   The backslash character ("\") MAY be used as a single-character
   quoting mechanism only within qdstr-val and comment constructs.

       quoted-pair    = "\" CHAR

   The value of this construct is CHAR. Note that an effect of this rule
   is that backslash must be quoted.

Java is doing the right thing because according to the RFC, "\" CHAR => CHAR in a quoted string.  In our case, the xmpp encoded \40, should actually be sent down as \\40.

To test this, I changed GenerateMessage() again to:

sb.Append(AddQuotes(this.Username.Replace(@"\",@"\\")));

This works.

Now I think that agsXMPP should be escaping all backslashes with double backslashes wherever it adds quotes in the MD5 Response.

Please let me know what you think.

Thanks,
Prerak
Avatar
Alex #7
Member since Feb 2003 · 4297 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
Hi Prerak,

thanks for finding this issue. I changed the AddQuotes function to:

  1. /// return the given string with quotes
  2. /// </summary>
  3. /// <param name="s"></param>
  4. /// <returns></returns>
  5. private string AddQuotes(string s)
  6. {
  7.      s = s.Replace(@"\", @"\\");
  8.     string quote = "\"";
  9.     return quote + s + quote;
  10. }

because this rule applies to all values I think it belows to this function. Any concerns?

Thanks,
Alex
Avatar
preraksanghvi #8
Member since Nov 2008 · 6 posts
Group memberships: Members
Show profile · Link to this post
That seems correct - it does apply to all quoted values.  I also ended up applying the change to AddQuotes on my computer eventually.

Thanks a lot for taking the time to look into this - I appreciate it.

Prerak
Avatar
ngboonseong #9
Member since Jan 2010 · 19 posts
Group memberships: Members
Show profile · Link to this post
Hi Alex,

Has the AddQuotes fix being applied to sdk v1.1 ? When I checked the log in Openfire 3.6.4, it seems like the "\" is missing (red below) hence openfire
cannot match the user. (In relation to the id 4871 posted earlier)

2010.05.18 15:41:58 SASLAuthentication: SaslException
javax.security.sasl.SaslException: DIGEST-MD5: IO error acquiring password [Caused by java.io.IOException: org.jivesoftware.openfire.user.UserNotFoundException: user140domain]
    at com.sun.security.sasl.digest.DigestMD5Server.validateClientResponse(Unknown Source)
    at com.sun.security.sasl.digest.DigestMD5Server.evaluateResponse(Unknown Source)
    at org.jivesoftware.openfire.net.SASLAuthentication.handle(SASLAuthentication.java:296)
    at org.jivesoftware.openfire.net.StanzaHandler.process(StanzaHandler.java:165)
    at org.jivesoftware.openfire.nio.ConnectionHandler.messageReceived(ConnectionHandler.java:133)
    at org.apache.mina.common.support.AbstractIoFilterChain$TailFilter.messageReceived(AbstractIoFilterChain.java:570)
    at org.apache.mina.common.support.AbstractIoFilterChain.callNextMessageReceived(AbstractIoFilterChain.java:299)
    at org.apache.mina.common.support.AbstractIoFilterChain.access$1100(AbstractIoFilterChain.java:53)
    at org.apache.mina.common.support.AbstractIoFilterChain$EntryImpl$1.messageReceived(AbstractIoFilterChain.java:648)
    at org.apache.mina.common.IoFilterAdapter.messageReceived(IoFilterAdapter.java:80)
    at org.apache.mina.common.support.AbstractIoFilterChain.callNextMessageReceived(AbstractIoFilterChain.java:299)
    at org.apache.mina.common.support.AbstractIoFilterChain.access$1100(AbstractIoFilterChain.java:53)
    at org.apache.mina.common.support.AbstractIoFilterChain$EntryImpl$1.messageReceived(AbstractIoFilterChain.java:648)
    at org.apache.mina.filter.codec.support.SimpleProtocolDecoderOutput.flush(SimpleProtocolDecoderOutput.java:58)
    at org.apache.mina.filter.codec.ProtocolCodecFilter.messageReceived(ProtocolCodecFilter.java:185)
    at org.apache.mina.common.support.AbstractIoFilterChain.callNextMessageReceived(AbstractIoFilterChain.java:299)
    at org.apache.mina.common.support.AbstractIoFilterChain.access$1100(AbstractIoFilterChain.java:53)
    at org.apache.mina.common.support.AbstractIoFilterChain$EntryImpl$1.messageReceived(AbstractIoFilterChain.java:648)
    at org.apache.mina.filter.executor.ExecutorFilter.processEvent(ExecutorFilter.java:239)
    at org.apache.mina.filter.executor.ExecutorFilter$ProcessEventsRunnable.run(ExecutorFilter.java:283)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at org.apache.mina.util.NamePreservingRunnable.run(NamePreservingRunnable.java:51)
    at java.lang.Thread.run(Unknown Source)

Thanks.

Regards,
Boon Seong
This post was edited on 2010-05-18, 09:50 by ngboonseong.
Avatar
Alex #10
Member since Feb 2003 · 4297 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
I can't remember if this was fixed after or before release 1.1. If you run in problems you should first always update to latest SVN.
Here you can download the latest binaries:
http://www.ag-software.net/downloads.html

Alex
Avatar
ngboonseong #11
Member since Jan 2010 · 19 posts
Group memberships: Members
Show profile · Link to this post
Thanks Alex. The latest ver 1.1.1.0 fixed the problem.
Avatar
ngboonseong #12
Member since Jan 2010 · 19 posts
Group memberships: Members
Show profile · Link to this post
In reply to post #10
Hi Alex,

I encountered one more issue. When I try to use the XmppClientConnection.ChangePassword, it seems the the user id with @ being escaped twice (line highlighted in red below).

My code as following :

         public void execute()
        {
            string userId = "User1@aaa";
            string server = "Server1";

            xmpp = new XmppClientConnection(server);

            xmpp.AutoAgents = true;
            xmpp.AutoPresence = true;
            xmpp.AutoRoster = true;
            xmpp.AutoResolveConnectServer = false;
            xmpp.RegisterAccount = false;
            xmpp.ClientVersion = "1.0.0";
            xmpp.OnLogin += new ObjectHandler(XmppCon_OnLogin);           
            xmpp.Open(userId, Password);
           
        }


        private void XmppCon_OnLogin(object sender)
        {
           // if I add the following line prior to ChangePassword, it works
           //xmpp.Username to "User1@aaa";

            xmpp.ChangePassword(Password); // here I noticed the Jid was being escaped as User1\5c40aaa instead of User1\40aaa
            xmpp.Close();
        }

Can you advise ?

Thanks.

Regards,
Boon Seong

Regards,
Boon Seong
Avatar
Alex #13
Member since Feb 2003 · 4297 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
I looked at the sources. ChangePassword is using the username member variable for password changes. This is exactly the same as for the login. Did you look at your Xml logs?

Alex
Close Smaller – Larger + Reply to this post:
Verification code: VeriCode Please enter the word from the image into the text field below. (Type the letters only, lower case is okay.)
Smileys: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Special characters:
Forum: agsXMPP RSS