Exemple #1
0
        protected override void OnConnected(bool bSuccess, string strErrors)
        {
            if (bSuccess == true)
            {
                this.Client.NoDelay  = true;
                XMPPClient.XMPPState = XMPPState.Connected;
                XMPPClient.FireConnectAttemptFinished(true);
                System.Diagnostics.Debug.WriteLine(string.Format("Successful TCP connection"));
            }
            else
            {
                XMPPClient.XMPPState = XMPPState.Unknown;
                XMPPClient.FireConnectAttemptFinished(false);
                System.Diagnostics.Debug.WriteLine(string.Format("Failed to connect: {0}", strErrors));
                return;
            }

            if (XMPPClient.UseOldStyleTLS == true)
            {
                StartTLS();
            }


            /// Send stream header if we haven't yet
            XMPPClient.XMPPState = XMPPState.Authenticating;

            OpenStreamStanza open    = new OpenStreamStanza(this.XMPPClient);
            string           strSend = open.XML;

            byte[] bStanza = System.Text.UTF8Encoding.UTF8.GetBytes(strSend);
            this.Send(bStanza);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="stanza"></param>
        /// <returns></returns>
        public override bool NewXMLFragment(XMPPStanza stanza)
        {
            /// Looks like the crippled windows phone 7 libraries can't use output from xsd.exe, have to do this the hard way
            ///
            //XDocument doc = XDocument.Load(new StringReader(stanza.XML));
            //XmlReader reader = XmlReader.Create(new StringReader(stanza.XML));


            stanza.XML = stanza.XML.Replace("stream:", "");  // no support for namespaces in windows phone 7, remove them

            XElement xmlElem = XElement.Parse(stanza.XML);

            if (XMPPClient.XMPPState >= XMPPState.Authenticated)
            {
                if (xmlElem.Name == "features")
                {
                    return(true);  /// If we hit this and parse the stream featurs a second time we re-authenticate.  Just return for now
                }
                //if (xmlElem.Name == "stream")
                //{
                //     XMPPClient.XMPPState = XMPPState.CanBind;
                //}
                /// TODO.. see if this new stream supports bind
            }


            if (xmlElem.Name == "features")
            {
                //foreach (XElement node in xmlElem.Descendants())
                //{
                //    System.Diagnostics.Debug.WriteLine(node.Name);
                //}
                var Mechanisms = from mech in xmlElem.Descendants("{urn:ietf:params:xml:ns:xmpp-sasl}mechanism")
                                 select new Mechanism
                {
                    Name = mech.Value,
                };
                foreach (Mechanism mech in Mechanisms)
                {
                    if (mech.Name == "DIGEST-MD5")
                    {
                        AuthMethodsSupported |= AuthMethod.MD5;
                    }
                    else if (mech.Name == "PLAIN")
                    {
                        AuthMethodsSupported |= AuthMethod.Plain;
                    }
                    //  else if (mech.Name == "X-GOOGLE-TOKEN")
                    //    AuthMethodsSupported |= AuthMethod.googletoken;
                }

                if (AuthMethodsSupported == AuthMethod.NotSpecified)
                {
                    throw new Exception("No acceptable authentication method was supplied");
                }

                var tls = xmlElem.Descendants("{urn:ietf:params:xml:ns:xmpp-tls}starttls");
                if (tls.Count() > 0)
                {
                    FeatureTLS = true;
                }

                if ((FeatureTLS == true) && (XMPPClient.UseTLS == true))
                {
                    /// Tell the man we want to negotiate TLS
                    XMPPClient.SendRawXML(StartTLS);
                }
                else
                {
                    StartAuthentication();
                }

                return(true);
            }
            else if (xmlElem.Name == "{urn:ietf:params:xml:ns:xmpp-tls}proceed")
            {
                XMPPClient.XMPPConnection.StartTLS();

                /// After starting TLS, start our normal digest authentication (or plain)
                ///
                StartAuthentication();
            }
            else if (xmlElem.Name == "{urn:ietf:params:xml:ns:xmpp-sasl}challenge")
            {
                /// Build and send response
                ///
                string strChallenge        = xmlElem.Value;
                byte[] bData               = Convert.FromBase64String(strChallenge);
                string strUnbasedChallenge = System.Text.UTF8Encoding.UTF8.GetString(bData, 0, bData.Length);

                //realm="ninethumbs.com",nonce="oFun3YWfVm/6nHCkNI/9a4XpcWIdQ5RH9E0IDVKH",qop="auth",charset=utf-8,algorithm=md5-sess

                //string strExampleResponse = "dXNlcm5hbWU9InRlc3QiLHJlYWxtPSJuaW5ldGh1bWJzLmNvbSIsbm9uY2U9InJaNjgreS9BeGp2SjJ6cjBCVUNxVUhQcG9ocFE4ZFkzR29JclpJcFkiLGNub25jZT0iVkdFRDNqNHUrUHE1M3IxYzNab2NhcGFzaWp1eTh2NjhoYXFzRC9IWjVKTT0iLG5jPTAwMDAwMDAxLGRpZ2VzdC11cmk9InhtcHAvbmluZXRodW1icy5jb20iLHFvcD1hdXRoLHJlc3BvbnNlPTdiM2MzOTVjZjU2MDA2Njg5MDg5MzdlYTk2YjEzZjI2LGNoYXJzZXQ9dXRmLTg=";
                //bData = Convert.FromBase64String(strExampleResponse);
                //string strUnbasedResponse = System.Text.UTF8Encoding.UTF8.GetString(bData, 0, bData.Length);
                //"username=\"test\",realm=\"ninethumbs.com\",nonce=\"rZ68+y/AxjvJ2zr0BUCqUHPpohpQ8dY3GoIrZIpY\",cnonce=\"VGED3j4u+Pq53r1c3Zocapasijuy8v68haqsD/HZ5JM=\",nc=00000001,digest-uri=\"xmpp/ninethumbs.com\",qop=auth,response=7b3c395cf5600668908937ea96b13f26,charset=utf-8";

                if (AuthMethodUsed == AuthMethod.MD5)
                {
                    string strRealm   = XMPPClient.Domain;
                    Match  matchrealm = Regex.Match(strUnbasedChallenge, @"realm=""([^""]+)""", RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase);
                    if (matchrealm.Success == true)
                    {
                        strRealm = matchrealm.Groups[1].Value;
                    }

                    string strNonce   = "";
                    Match  matchnonce = Regex.Match(strUnbasedChallenge, @"nonce=""([^""]+)""", RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline);
                    if (matchnonce.Success == true)
                    {
                        strNonce = matchnonce.Groups[1].Value;
                    }


                    string strQop   = "auth";
                    Match  matchqop = Regex.Match(strUnbasedChallenge, @"qop=""([^""]+)""", RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase);
                    if (matchqop.Success == true)
                    {
                        strQop = matchqop.Groups[1].Value;
                    }

                    string strAlgo   = "md5-sess";
                    Match  matchalgo = Regex.Match(strUnbasedChallenge, @"algorithm=([^\s,]+)", RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase);
                    if (matchalgo.Success == true)
                    {
                        strAlgo = matchalgo.Groups[1].Value;
                    }

                    Random rand      = new Random();
                    string strCnonce = rand.Next().ToString("X8").ToLower();
                    // Compute our MD5 response, then base64 it
                    string strResponse = GenerateMD5Response(strAlgo, XMPPClient.UserName, XMPPClient.Domain, XMPPClient.Password, strNonce, strCnonce);

                    string ResponseMessage = MD5Response.Replace("##RESPONSE##", strResponse);
                    XMPPClient.SendRawXML(ResponseMessage);
                }
                else if (AuthMethodUsed == AuthMethod.Plain)
                {
                    /// Send plain text stuff
                    ///
                }
            }
            else if (xmlElem.Name == "{urn:ietf:params:xml:ns:xmpp-sasl}success") /// Success
            {
                XMPPClient.XMPPState = XMPPState.Authenticated;

                if (XMPPClient.UseTLS == true)
                {
                    /// Start a new stream for some strange reason, but don't close the old one.
                    ///
                    OpenStreamStanza open = new OpenStreamStanza(this.XMPPClient);
                    XMPPClient.SendRawXML(open.XML);
                }
                else
                {
                    XMPPClient.XMPPState = XMPPState.CanBind;
                }
            }
            else if (xmlElem.Name == "{urn:ietf:params:xml:ns:xmpp-sasl}failure")  /// Failed to authorize
            {
                XMPPClient.XMPPState = XMPPState.AuthenticationFailed;
            }


            return(false);
        }
        /// <summary>
        ///  
        /// </summary>
        /// <param name="stanza"></param>
        /// <returns></returns>
        public override bool NewXMLFragment(XMPPStanza stanza)
        {
            /// Looks like the crippled windows phone 7 libraries can't use output from xsd.exe, have to do this the hard way
            ///
            //XDocument doc = XDocument.Load(new StringReader(stanza.XML));
            //XmlReader reader = XmlReader.Create(new StringReader(stanza.XML));

            stanza.XML = stanza.XML.Replace("stream:", "");  // no support for namespaces in windows phone 7, remove them

            XElement xmlElem = XElement.Parse(stanza.XML);

            if (XMPPClient.XMPPState >= XMPPState.Authenticated)
            {
                if (xmlElem.Name == "features")
                    return true;  /// If we hit this and parse the stream featurs a second time we re-authenticate.  Just return for now

                //if (xmlElem.Name == "stream")
                //{
                //     XMPPClient.XMPPState = XMPPState.CanBind;
                //}
                /// TODO.. see if this new stream supports bind
            }

            if (xmlElem.Name== "features")
            {
                //foreach (XElement node in xmlElem.Descendants())
                //{
                //    System.Diagnostics.Debug.WriteLine(node.Name);
                //}
                var Mechanisms = from mech in xmlElem.Descendants("{urn:ietf:params:xml:ns:xmpp-sasl}mechanism")
                                 select new Mechanism
                                 {
                                     Name = mech.Value,
                                 };
                foreach (Mechanism mech in Mechanisms)
                {
                    if (mech.Name == "DIGEST-MD5")
                        AuthMethodsSupported |= AuthMethod.MD5;
                    else if (mech.Name == "PLAIN")
                        AuthMethodsSupported |= AuthMethod.Plain;
                  //  else if (mech.Name == "X-GOOGLE-TOKEN")
                    //    AuthMethodsSupported |= AuthMethod.googletoken;
                }

                if (AuthMethodsSupported == AuthMethod.NotSpecified)
                    throw new Exception("No acceptable authentication method was supplied");

                var tls = xmlElem.Descendants("{urn:ietf:params:xml:ns:xmpp-tls}starttls");
                if (tls.Count() > 0)
                    FeatureTLS = true;

                if ((FeatureTLS == true) && (XMPPClient.UseTLS == true))
                {
                    /// Tell the man we want to negotiate TLS
                    XMPPClient.SendRawXML(StartTLS);
                }
                else
                {
                    StartAuthentication();
                }

                return true;
            }
            else if (xmlElem.Name == "{urn:ietf:params:xml:ns:xmpp-tls}proceed")
            {
                XMPPClient.XMPPConnection.StartTLS();

                /// After starting TLS, start our normal digest authentication (or plain)
                ///
                StartAuthentication();
            }
            else if (xmlElem.Name == "{urn:ietf:params:xml:ns:xmpp-sasl}challenge")
            {
                /// Build and send response
                ///
                string strChallenge = xmlElem.Value;
                byte[] bData = Convert.FromBase64String(strChallenge);
                string strUnbasedChallenge = System.Text.UTF8Encoding.UTF8.GetString(bData, 0, bData.Length);

                //realm="ninethumbs.com",nonce="oFun3YWfVm/6nHCkNI/9a4XpcWIdQ5RH9E0IDVKH",qop="auth",charset=utf-8,algorithm=md5-sess

                //string strExampleResponse = "dXNlcm5hbWU9InRlc3QiLHJlYWxtPSJuaW5ldGh1bWJzLmNvbSIsbm9uY2U9InJaNjgreS9BeGp2SjJ6cjBCVUNxVUhQcG9ocFE4ZFkzR29JclpJcFkiLGNub25jZT0iVkdFRDNqNHUrUHE1M3IxYzNab2NhcGFzaWp1eTh2NjhoYXFzRC9IWjVKTT0iLG5jPTAwMDAwMDAxLGRpZ2VzdC11cmk9InhtcHAvbmluZXRodW1icy5jb20iLHFvcD1hdXRoLHJlc3BvbnNlPTdiM2MzOTVjZjU2MDA2Njg5MDg5MzdlYTk2YjEzZjI2LGNoYXJzZXQ9dXRmLTg=";
                //bData = Convert.FromBase64String(strExampleResponse);
                //string strUnbasedResponse = System.Text.UTF8Encoding.UTF8.GetString(bData, 0, bData.Length);
                //"username=\"test\",realm=\"ninethumbs.com\",nonce=\"rZ68+y/AxjvJ2zr0BUCqUHPpohpQ8dY3GoIrZIpY\",cnonce=\"VGED3j4u+Pq53r1c3Zocapasijuy8v68haqsD/HZ5JM=\",nc=00000001,digest-uri=\"xmpp/ninethumbs.com\",qop=auth,response=7b3c395cf5600668908937ea96b13f26,charset=utf-8";

                if (AuthMethodUsed == AuthMethod.MD5)
                {
                    string strRealm = XMPPClient.Domain;
                    Match matchrealm = Regex.Match(strUnbasedChallenge, @"realm=""([^""]+)""", RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase);
                    if (matchrealm.Success == true)
                        strRealm = matchrealm.Groups[1].Value;

                    string strNonce = "";
                    Match matchnonce = Regex.Match(strUnbasedChallenge, @"nonce=""([^""]+)""", RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline);
                    if (matchnonce.Success == true)
                        strNonce = matchnonce.Groups[1].Value;

                    string strQop = "auth";
                    Match matchqop = Regex.Match(strUnbasedChallenge, @"qop=""([^""]+)""", RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase);
                    if (matchqop.Success == true)
                        strQop = matchqop.Groups[1].Value;

                    string strAlgo = "md5-sess";
                    Match matchalgo = Regex.Match(strUnbasedChallenge, @"algorithm=([^\s,]+)", RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase);
                    if (matchalgo.Success == true)
                        strAlgo = matchalgo.Groups[1].Value;

                    Random rand = new Random();
                    string strCnonce = rand.Next().ToString("X8").ToLower();
                    // Compute our MD5 response, then base64 it
                    string strResponse = GenerateMD5Response(strAlgo, XMPPClient.UserName, XMPPClient.Domain, XMPPClient.Password, strNonce, strCnonce);

                    string ResponseMessage = MD5Response.Replace("##RESPONSE##", strResponse);
                    XMPPClient.SendRawXML(ResponseMessage);
                }
                else if (AuthMethodUsed == AuthMethod.Plain)
                {
                    /// Send plain text stuff
                    ///

                }

            }
            else if (xmlElem.Name == "{urn:ietf:params:xml:ns:xmpp-sasl}success") /// Success
            {
                XMPPClient.XMPPState = XMPPState.Authenticated;

                if (XMPPClient.UseTLS == true)
                {
                    /// Start a new stream for some strange reason, but don't close the old one.
                    ///
                    OpenStreamStanza open = new OpenStreamStanza(this.XMPPClient);
                    XMPPClient.SendRawXML(open.XML);
                }
                else
                {
                    XMPPClient.XMPPState = XMPPState.CanBind;
                }
            }
            else if (xmlElem.Name == "{urn:ietf:params:xml:ns:xmpp-sasl}failure")  /// Failed to authorize
            {
                XMPPClient.XMPPState = XMPPState.AuthenticationFailed;
            }

            return false;
        }