Example #1
0
        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        public override Tag Initialize()
        {
            base.Initialize();
            Logger.Debug(this, "Initializing SCRAM Processor");

            Logger.Debug(this, "Generating nonce");
            _nonce = NextInt64().ToString();
            Logger.DebugFormat(this, "Nonce: {0}", _nonce);
            Logger.Debug(this, "Building Initial Message");
            var msg = new StringBuilder();

            msg.Append("n,,n=");
            msg.Append(Id.User);
            msg.Append(",r=");
            msg.Append(_nonce);
            Logger.DebugFormat(this, "Message: {0}", msg.ToString());

            _clientFirst = msg.ToString().Substring(3);

            var tag = TagRegistry.GetTag <Auth>("auth", Namespaces.SASL);

            tag.Mechanism = Mechanism.GetMechanism(MechanismType.SCRAM);
            tag.Bytes     = _utf.GetBytes(msg.ToString());
            return(tag);
        }
Example #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="tag"></param>
        /// <returns></returns>
        public override Tag Step(Tag tag)
        {
            if (tag.Name == "success")
            {
                var succ = tag;
                PopulateDirectives(succ);
                Logger.DebugFormat(this, "rspauth = {0}", this["rspauth"]);

                return(succ);
            }

            if (tag.Name == "failure")
            {
                Errors.SendError(this, ErrorType.AuthorizationFailed, "Failed authorization");
                return(tag);
            }

            var chall = tag;

            Logger.Debug(this, _enc.GetString(tag.Bytes));
            PopulateDirectives(chall);
            var res = TagRegistry.GetTag <GenericTag>("response", Namespaces.SASL);

            if (this["rspauth"] == null)
            {
                GenerateResponseHash();
                res.Bytes = GenerateResponse();
            }

            return(res);
        }
Example #3
0
        /// <summary>
        /// </summary>
        /// <param name="data"></param>
        public void Execute(Tag data = null)
        {
            if (data == null)
            {
                var iq   = TagRegistry.GetTag <Iq>("iq", Namespaces.Client);
                var sess = TagRegistry.GetTag <GenericTag>("session", Namespaces.Session);

                iq.From    = ProtocolState.Settings.Id;
                iq.To      = ProtocolState.Settings.Id.Server;
                iq.IqType  = IqType.Set;
                iq.Payload = sess;

                ProtocolState.Socket.Write(iq);
            }
            else
            {
                if (ProtocolState.Features.HasFlag(ProtocolFeatures.StreamManagement))
                {
                    Log.Debug("Intiating Stream Management");
                    ProtocolState.State = new StreamManagementState();
                    ProtocolState.State.Execute();
                }
                else
                {
                    ProtocolState.State = new RunningState();
                }
            }
        }
Example #4
0
        /// <summary>
        ///     Process the next step in the authentication process
        /// </summary>
        /// <param name="tag">The tag we received from the server</param>
        /// <returns>The next tag to send in the process</returns>
        public override Tag Step(Tag tag)
        {
            switch (tag.Name)
            {
            case "success":
                var succ = tag;
                PopulateDirectives(succ);

                return(succ);

            case "failure":
                ProtocolState.Events.Error(this, ErrorType.AuthorizationFailed, ErrorSeverity.Fatal, "Unable to authorize current user credentials.");
                return(tag);
            }

            var chall = tag;

            PopulateDirectives(chall);
            var res = TagRegistry.GetTag <GenericTag>("response", Namespaces.Sasl);

            if (this["rspauth"] != null)
            {
                return(res);
            }
            GenerateResponseHash();
            res.Bytes = GenerateResponse();

            return(res);
        }
Example #5
0
        /// <summary>
        /// </summary>
        /// <param name="data"></param>
        public void Execute(Tag data = null)
        {
            if (data is R)
            {
                var ack = TagRegistry.GetTag <A>(new XmlQualifiedName("a", Namespaces.StreamManagementV3));
                ack.H = ProtocolState.StanzaCount;
                ProtocolState.Socket.Write(ack);
            }
            else if (data is A)
            {
                var ack     = (A)data;
                var handled = ack.H;
                var delta   = handled - ProtocolState.StanzaCount;

                for (var i = 0; i < delta; i++)
                {
                    if (ProtocolState.UnacknowlegedStanzas.Count == 0)
                    {
                        continue;
                    }

                    var ackStanza = ProtocolState.UnacknowlegedStanzas.Dequeue();
                }
            }

            if (ProtocolState.RosterManager == null)
            {
                ProtocolState.RosterManager = new DefaultRosterManager();
            }

            ProtocolState.RosterManager.RequestRoster();
        }
Example #6
0
        /// <summary>
        ///     Initialize the processor
        /// </summary>
        /// <returns>An auth tag to start the authentication process</returns>
        public override Tag Initialize(string id, string password)
        {
            base.Initialize(id, password);

            var tag = TagRegistry.GetTag <Auth>("auth", Namespaces.Sasl);

            tag.Mechanism = Mechanism.GetMechanism(MechanismType.DigestMd5);
            return(tag);
        }
Example #7
0
        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        public override Tag Initialize()
        {
            base.Initialize();

            var tag = TagRegistry.GetTag <Auth>("auth", Namespaces.SASL);

            tag.Mechanism = Mechanism.GetMechanism(MechanismType.DigestMD5);
            return(tag);
        }
Example #8
0
        /// <summary>
        /// </summary>
        /// <param name="tag"></param>
        /// <returns></returns>
        public override Tag Step(Tag tag)
        {
            switch (tag.Name)
            {
            case "challenge":
            {
                _serverFirst = tag.Bytes;
                var response = _utf.GetString(tag.Bytes);

                // Split challenge into pieces
                var tokens = response.Split(',');

                _snonce = tokens[0].Substring(2);
                // Ensure that the first length of nonce is the same nonce we sent.
                var r = _snonce.Substring(0, _nonce.Length);
                if (0 != string.CompareOrdinal(r, _nonce))
                {
                    throw new Exception("Error in authenticating server nonce.");
                }

                var a = tokens[1].Substring(2);
                _salt = Convert.FromBase64String(a);

                var i = tokens[2].Substring(2);
                _i = int.Parse(i);

                var final = new StringBuilder();
                final.Append("c=biws,r=");
                final.Append(_snonce);

                _clientFinal = final.ToString();

                CalculateProofs();

                final.Append(",p=");
                final.Append(_clientProof);

                var resp = TagRegistry.GetTag <GenericTag>("response", Namespaces.Sasl);
                resp.Bytes = _utf.GetBytes(final.ToString());

                return(resp);
            }

            case "success":
            {
                var response  = _utf.GetString(tag.Bytes);
                var signature = Convert.FromBase64String(response.Substring(2));
                return(_utf.GetString(signature) == _utf.GetString(_serverSignature) ? tag : null);
            }

            case "failure":
                return(tag);
            }

            return(null);
        }
Example #9
0
        /// <summary>
        /// Executes the state sending the tag to the just connected socket.
        /// </summary>
        /// <param name="data">
        /// The <see cref="Tag"/> to parse.  In this case null.
        /// </param>
        public override void Execute(Tag data = null)
        {
            var stream = TagRegistry.GetTag <Stream>("stream", Namespaces.Stream);

            stream.Version   = "1.0";
            stream.To        = ProtocolState.Settings.Id.Server;
            stream.Namespace = Namespaces.Client;
            stream.Language  = "en";
            ProtocolState.Socket.Write("<?xml version='1.0' encoding='UTF-8'?>" + stream.StartTag());
            ProtocolState.State = new ServerFeaturesState();
        }
Example #10
0
 public void Execute(Tag data = null)
 {
     if (data == null)
     {
         var enable = TagRegistry.GetTag <Enable>("enable", Namespaces.StreamManagementV3);
         ProtocolState.Socket.Write(enable);
     }
     else
     {
         ProtocolState.State = new RunningState();
     }
 }
Example #11
0
        /// <summary>
        ///
        /// </summary>
        public void RequestRoster()
        {
            var iq = TagRegistry.GetTag <Iq>("iq", Namespaces.Client);

            iq.IqType = IqType.Get;
            iq.From   = ProtocolState.Settings.Id;

            var query = TagRegistry.GetTag <Query>("query", Namespaces.Roster);

            iq.Payload = query;

            ProtocolState.Events.Send(this, iq);
        }
Example #12
0
        public override void Execute(Tag data = null)
        {
            if (data == null)
            {
                var a = TagRegistry.GetTag <Bind>("bind", Namespaces.Bind);
                var b = TagRegistry.GetTag <Iq>("iq", Namespaces.Client);

                if (UbietySettings.Id.Resource != null)
                {
                    var res = TagRegistry.GetTag <GenericTag>("resource", Namespaces.Bind);
                    res.InnerText = UbietySettings.Id.Resource;
                    a.AddChildTag(res);
                }

                b.IqType  = IqType.Set;
                b.Payload = a;

                ProtocolState.Socket.Write(b);
            }
            else
            {
                var  iq   = data as Iq;
                Bind bind = null;
                if (iq != null)
                {
                    if (iq.IqType == IqType.Error)
                    {
                        var e = iq["error"];
                        if (e != null)
                        {
                            Errors.SendError(this, ErrorType.XMLError, e.InnerText);
                        }
                    }
                    bind = iq.Payload as Bind;
                }
                if (bind != null)
                {
                    UbietySettings.Id = bind.JidTag.JID;
                }
                Logger.InfoFormat(this, "Current XID is now: {0}", UbietySettings.Id);

                ProtocolState.State = new SessionState();
                ProtocolState.State.Execute();
            }
        }
Example #13
0
        /// <summary>
        /// </summary>
        /// <exception cref="NotImplementedException"></exception>
        public override Tag Initialize(String id, String password)
        {
            base.Initialize(id, password);

            var sb = new StringBuilder();

            sb.Append((char)0);
            sb.Append(Id.User);
            sb.Append((char)0);
            sb.Append(Password);

            var auth = TagRegistry.GetTag <Auth>("auth", Namespaces.Sasl);

            auth.Text      = Convert.ToBase64String(Encoding.UTF8.GetBytes(sb.ToString()));
            auth.Mechanism = Mechanism.GetMechanism(MechanismType.Plain);

            return(auth);
        }
Example #14
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="data"></param>
        public override void Execute(Tag data = null)
        {
            if (data == null)
            {
                var a = TagRegistry.GetTag <Bind>("bind", Namespaces.Bind);
                var b = TagRegistry.GetTag <Iq>("iq", Namespaces.Client);

                if (ProtocolState.Settings.Id.Resource != null)
                {
                    var res = TagRegistry.GetTag <GenericTag>("resource", Namespaces.Bind);
                    res.InnerText = ProtocolState.Settings.Id.Resource;
                    a.AddChildTag(res);
                }

                b.IqType  = IqType.Set;
                b.Payload = a;

                ProtocolState.Socket.Write(b);
            }
            else
            {
                var  iq   = data as Iq;
                Bind bind = null;
                if (iq != null)
                {
                    if (iq.IqType == IqType.Error)
                    {
                        var e = iq["error"];
                        if (e != null)
                        {
                            ProtocolState.Events.Error(this, ErrorType.XmlError, ErrorSeverity.Reconnect, e.InnerText);
                        }
                    }
                    bind = iq.Payload as Bind;
                }
                if (bind != null)
                {
                    ProtocolState.Settings.Id = bind.JidTag.JID;
                }

                ProtocolState.State = new SessionState();
                ProtocolState.State.Execute();
            }
        }
Example #15
0
        ///<summary>
        ///</summary>
        ///<exception cref="NotImplementedException"></exception>
        public override Tag Initialize()
        {
            Logger.Debug(this, "Initializing Plain Processor");
            Logger.DebugFormat(this, "ID User: {0}", UbietySettings.Id.User);

            var sb = new StringBuilder();

            sb.Append((char)0);
            sb.Append(UbietySettings.Id.User);
            sb.Append((char)0);
            sb.Append(UbietySettings.Password);

            var auth = TagRegistry.GetTag <Auth>("auth", Namespaces.SASL);

            auth.Text      = Convert.ToBase64String(Encoding.UTF8.GetBytes(sb.ToString()));
            auth.Mechanism = Mechanism.GetMechanism(MechanismType.Plain);

            return(auth);
        }
Example #16
0
        /// <summary>
        /// </summary>
        /// <returns></returns>
        public override Tag Initialize(string id, string password)
        {
            base.Initialize(id, password);

            _nonce = NextInt64().ToString(CultureInfo.InvariantCulture);
            var msg = new StringBuilder();

            msg.Append("n,,n=");
            msg.Append(Id.User);
            msg.Append(",r=");
            msg.Append(_nonce);

            _clientFirst = msg.ToString().Substring(3);

            var tag = TagRegistry.GetTag <Auth>("auth", Namespaces.Sasl);

            tag.Mechanism = Mechanism.GetMechanism(MechanismType.Scram);
            tag.Bytes     = _utf.GetBytes(msg.ToString());
            return(tag);
        }
Example #17
0
        public override void Execute(Tag data = null)
        {
            if (data == null)
            {
                var iq   = TagRegistry.GetTag <Iq>("iq", Namespaces.Client);
                var sess = TagRegistry.GetTag <GenericTag>("session", Namespaces.Session);

                iq.From    = UbietySettings.Id;
                iq.To      = UbietySettings.Id.Server;
                iq.IqType  = IqType.Set;
                iq.Payload = sess;

                ProtocolState.Socket.Write(iq);
            }
            else
            {
                var p = TagRegistry.GetTag <GenericTag>("presence", Namespaces.Client);
                ProtocolState.Socket.Write(p);

                ProtocolState.State = new RunningState();
            }
        }
Example #18
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="tag"></param>
        /// <returns></returns>
        public override Tag Step(Tag tag)
        {
            switch (tag.Name)
            {
            case "challenge":
            {
                _serverFirst = tag.Bytes;
                var response = _utf.GetString(tag.Bytes);
                Logger.DebugFormat(this, "Challenge: {0}", response);

                // Split challenge into pieces
                var tokens = response.Split(',');

                _snonce = tokens[0].Substring(2);
                // Ensure that the first length of nonce is the same nonce we sent.
                var r = _snonce.Substring(0, _nonce.Length);
                if (0 != String.Compare(r, _nonce))
                {
                    Logger.DebugFormat(this, "{0} does not match {1}", r, _nonce);
                }

                Logger.Debug(this, "Getting Salt");
                var a = tokens[1].Substring(2);
                _salt = Convert.FromBase64String(a);

                Logger.Debug(this, "Getting Iterations");
                var i = tokens[2].Substring(2);
                _i = int.Parse(i);
                Logger.DebugFormat(this, "Iterations: {0}", _i);

                var final = new StringBuilder();
                final.Append("c=biws,r=");
                final.Append(_snonce);

                _clientFinal = final.ToString();

                CalculateProofs();

                final.Append(",p=");
                final.Append(_clientProof);

                Logger.DebugFormat(this, "Final Message: {0}", final.ToString());

                var resp = TagRegistry.GetTag <GenericTag>("response", Namespaces.SASL);
                resp.Bytes = _utf.GetBytes(final.ToString());

                return(resp);
            }

            case "success":
            {
                var response  = _utf.GetString(tag.Bytes);
                var signature = Convert.FromBase64String(response.Substring(2));
                return(_utf.GetString(signature) == _utf.GetString(_serverSignature) ? tag : null);
            }

            case "failure":
                return(tag);
            }

            return(null);
        }
Example #19
0
        private static void StartTag()
        {
            var ht = new Hashtable();

            if (_reader.HasAttributes)
            {
                while (_reader.MoveToNextAttribute())
                {
                    if (_reader.Prefix.Equals("xmlns"))
                    {
                        Ns.AddNamespace(_reader.LocalName, _reader.Value);
                    }
                    else if (_reader.Name.Equals("xmlns"))
                    {
                        Ns.AddNamespace(string.Empty, _reader.Value);
                    }
                    else
                    {
                        ht.Add(_reader.Name, _reader.Value);
                    }
                }
                _reader.MoveToElement();
            }

            var        ns   = Ns.LookupNamespace(_reader.Prefix);
            var        q    = new XmlQualifiedName(_reader.LocalName, ns);
            XmlElement elem = TagRegistry.GetTag <Tag>(q) ?? new ubiety.core.GenericTag(q);

            foreach (string attrname in ht.Keys)
            {
                var colon = attrname.IndexOf(':');
                if (colon > 0)
                {
                    var prefix = attrname.Substring(0, colon);
                    var name   = attrname.Substring(colon + 1);

                    var attr = ProtocolState.Document.CreateAttribute(prefix, name, Ns.LookupNamespace(prefix));
                    attr.InnerXml = (string)ht[attrname];

                    elem.SetAttributeNode(attr);
                }
                else
                {
                    var attr = ProtocolState.Document.CreateAttribute(attrname);
                    attr.InnerXml = (string)ht[attrname];

                    elem.SetAttributeNode(attr);
                }
            }

            if (_root == null)
            {
                if (elem.Name != "stream:stream")
                {
                    Errors.SendError(typeof(ProtocolParser), ErrorType.WrongProtocolVersion,
                                     "Missing stream:stream from server");
                    return;
                }

                _root = elem;
            }
            else
            {
                if (_elem != null)
                {
                    _elem.AppendChild(elem);
                }
                _elem = elem;
            }
        }
Example #20
0
        private static void StartTag()
        {
            var ht = new Hashtable();

            if (_reader.HasAttributes)
            {
                while (_reader.MoveToNextAttribute())
                {
                    if (_reader.Prefix.Equals("xmlns"))
                    {
                        NamespaceManager.AddNamespace(_reader.LocalName, _reader.Value);
                    }
                    else if (_reader.Name.Equals("xmlns"))
                    {
                        NamespaceManager.AddNamespace(string.Empty, _reader.Value);
                    }
                    else
                    {
                        ht.Add(_reader.Name, _reader.Value);
                    }
                }
                _reader.MoveToElement();
            }

            var        ns   = NamespaceManager.LookupNamespace(_reader.Prefix);
            var        q    = new XmlQualifiedName(_reader.LocalName, ns);
            XmlElement elem = TagRegistry.GetTag <Tag>(q);

            foreach (string attrname in ht.Keys)
            {
                var colon = attrname.IndexOf(':');
                if (colon > 0)
                {
                    var prefix = attrname.Substring(0, colon);
                    var name   = attrname.Substring(colon + 1);

                    var attr = Tag.Document.CreateAttribute(prefix, name,
                                                            NamespaceManager.LookupNamespace(prefix));
                    attr.InnerXml = (string)ht[attrname];

                    elem.SetAttributeNode(attr);
                }
                else
                {
                    var attr = Tag.Document.CreateAttribute(attrname);
                    attr.InnerXml = (string)ht[attrname];

                    elem.SetAttributeNode(attr);
                }
            }

            if (_root == null)
            {
                if (elem.Name != "stream:stream")
                {
                    ProtocolState.Events.Error(null, ErrorType.WrongProtocolVersion, ErrorSeverity.Fatal, "Missing proper stream:stream header from server.");
                    return;
                }

                _root = elem;
            }
            else
            {
                _element?.AppendChild(elem);
                _element = elem;
            }
        }
Example #21
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="data">
        /// A <see cref="Tag"/>
        /// </param>
        public override void Execute(Tag data = null)
        {
            Features f;

            if (data is Stream)
            {
                var s = data as Stream;
                if (!s.Version.StartsWith("1."))
                {
                    Errors.SendError(this, ErrorType.WrongProtocolVersion, "Expecting stream:features from 1.x server");
                    return;
                }
                f = s.Features;
            }
            else
            {
                f = data as Features;
            }

            if (f != null)
            {
                if (f.StartTLS != null && UbietySettings.SSL)
                {
                    ProtocolState.State = new StartTLSState();
                    var tls = TagRegistry.GetTag <StartTLS>("starttls", Namespaces.StartTLS);
                    ProtocolState.Socket.Write(tls);
                    return;
                }

                if (!ProtocolState.Authenticated)
                {
                    Logger.Debug(this, "Creating SASL Processor");
                    ProtocolState.Processor = SASLProcessor.CreateProcessor(f.StartSASL.SupportedTypes);
                    if (ProtocolState.Processor == null)
                    {
                        Logger.Debug(this, "No allowed type available. Allow more authentication options.");
                        ProtocolState.State = new DisconnectState();
                        ProtocolState.State.Execute();
                        return;
                    }
                    Logger.Debug(this, "Sending auth with mechanism type");
                    ProtocolState.Socket.Write(ProtocolState.Processor.Initialize());

                    ProtocolState.State = new SASLState();
                    return;
                }

                // Takes place after authentication according to XEP-0170
                if (!ProtocolState.Compressed && CompressionRegistry.AlgorithmsAvailable && !UbietySettings.SSL && f.Compression != null)
                {
                    Logger.Info(this, "Starting compression");
                    // Do we have a stream for any of the compressions supported by the server?
                    foreach (var algorithm in
                             f.Compression.Algorithms.Where(CompressionRegistry.SupportsAlgorithm))
                    {
                        Logger.DebugFormat(this, "Using {0} for compression", algorithm);
                        var c = TagRegistry.GetTag <GenericTag>("compress", Namespaces.CompressionProtocol);
                        var m = TagRegistry.GetTag <GenericTag>("method", Namespaces.CompressionProtocol);

                        m.InnerText = ProtocolState.Algorithm = algorithm;
                        c.AddChildTag(m);
                        ProtocolState.Socket.Write(c);
                        ProtocolState.State = new CompressedState();
                        return;
                    }
                }
            }

            Logger.Debug(this, "Authenticated");
            ProtocolState.State = new BindingState();
            ProtocolState.State.Execute();
        }
Example #22
0
        /// <summary>
        /// </summary>
        /// <param name="data">
        ///     A <see cref="Tag" />
        /// </param>
        public override void Execute(Tag data = null)
        {
            Features f;

            if (data is Stream)
            {
                var s = data as Stream;
                if (!s.Version.StartsWith("1."))
                {
                    ProtocolState.Events.Error(this, ErrorType.WrongProtocolVersion, ErrorSeverity.Fatal, "Didn't receive expected stream:features tag from 1.x compliant server.");
                    return;
                }
                f = s.Features;
            }
            else
            {
                f = data as Features;
            }

            if (f != null)
            {
                if (f.StartTls != null && ProtocolState.Settings.Ssl)
                {
                    ProtocolState.State = new StartTlsState();
                    var tls = TagRegistry.GetTag <StartTls>("starttls", Namespaces.StartTls);
                    ProtocolState.Socket.Write(tls);
                    return;
                }

                if (!ProtocolState.Authenticated)
                {
                    ProtocolState.Processor = SaslProcessor.CreateProcessor(f.StartSasl.SupportedTypes, ProtocolState.Settings.AuthenticationTypes);
                    if (ProtocolState.Processor == null)
                    {
                        ProtocolState.State = new DisconnectState();
                        ProtocolState.State.Execute();
                        return;
                    }
                    ProtocolState.Socket.Write(ProtocolState.Processor.Initialize(ProtocolState.Settings.Id, ProtocolState.Settings.Password));

                    ProtocolState.State = new SaslState();
                    return;
                }

                // Takes place after authentication according to XEP-0170
                if (!ProtocolState.Compressed && CompressionRegistry.AlgorithmsAvailable && !ProtocolState.Settings.Ssl &&
                    f.Compression != null)
                {
                    // Do we have a stream for any of the compressions supported by the server?
                    foreach (string algorithm in
                             f.Compression.Algorithms.Where(CompressionRegistry.SupportsAlgorithm))
                    {
                        var c = TagRegistry.GetTag <GenericTag>("compress", Namespaces.CompressionProtocol);
                        var m = TagRegistry.GetTag <GenericTag>("method", Namespaces.CompressionProtocol);

                        m.InnerText = ProtocolState.Algorithm = algorithm;
                        c.AddChildTag(m);
                        ProtocolState.Socket.Write(c);
                        ProtocolState.State = new CompressedState();
                        return;
                    }
                }
            }

            ProtocolState.State = new BindingState();
            ProtocolState.State.Execute();
        }
Example #23
0
        /// <summary>
        /// </summary>
        /// <param name="data">
        ///     A <see cref="Tag" />
        /// </param>
        public void Execute(Tag data = null)
        {
            Features features;

            var stream = data as Stream;

            if (stream != null)
            {
                var s = stream;
                if (!s.Version.StartsWith("1."))
                {
                    ProtocolState.Events.Error(this, ErrorType.WrongProtocolVersion, ErrorSeverity.Fatal,
                                               "Didn't receive expected stream:features tag from 1.x compliant server.");
                    return;
                }
                features = s.Features;
            }
            else
            {
                features = data as Features;
            }

            if (features != null)
            {
                // We have features available so make sure we have them set
                features.Update();

                // Should we use SSL and is it required
                if ((ProtocolState.Features.HasFlag(ProtocolFeatures.StartTls) && ProtocolState.Settings.Ssl) ||
                    (ProtocolState.Features.HasFlag(ProtocolFeatures.StartTls) &&
                     ProtocolState.Features.HasFlag(ProtocolFeatures.SslRequired)) && !ProtocolState.Encrypted)
                {
                    Log.Debug("Starting SSL...");
                    ProtocolState.State = new StartTlsState();
                    var tls = TagRegistry.GetTag <StartTls>("starttls", Namespaces.StartTls);
                    ProtocolState.Socket.Write(tls);
                    return;
                }

                if (!ProtocolState.Authenticated)
                {
                    Log.Debug("Starting Authentication...");
                    ProtocolState.Processor = SaslProcessor.CreateProcessor(features.StartSasl.SupportedTypes,
                                                                            ProtocolState.Settings.AuthenticationTypes);
                    if (ProtocolState.Processor == null)
                    {
                        ProtocolState.State = new DisconnectState();
                        ProtocolState.State.Execute();
                        return;
                    }
                    ProtocolState.Socket.Write(
                        ProtocolState.Processor.Initialize(ProtocolState.Settings.Id, ProtocolState.Settings.Password));

                    ProtocolState.State = new SaslState();
                    return;
                }

                // Takes place after authentication according to XEP-0170
                if (!ProtocolState.Compressed && CompressionRegistry.AlgorithmsAvailable &&
                    !ProtocolState.Settings.Ssl &&
                    features.Compression != null)
                {
                    Log.Debug("Starting Compression...");
                    // Do we have a stream for any of the compressions supported by the server?
                    foreach (var algorithm in
                             features.Compression.Algorithms.Where(CompressionRegistry.SupportsAlgorithm))
                    {
                        var c = TagRegistry.GetTag <GenericTag>("compress", Namespaces.CompressionProtocol);
                        var m = TagRegistry.GetTag <GenericTag>("method", Namespaces.CompressionProtocol);

                        m.InnerText = ProtocolState.Algorithm = algorithm;
                        c.AddChildTag(m);
                        ProtocolState.Socket.Write(c);
                        ProtocolState.State = new CompressedState();
                        return;
                    }
                }

                if (ProtocolState.Authenticated)
                {
                    Log.Debug("Switching to Binding state");
                    ProtocolState.State = new BindingState();
                    ProtocolState.State.Execute();
                }
            }
        }