Beispiel #1
0
        /// <summary>
        /// Handle the last set of stream:features we have received, 
        /// based on the current state.
        /// </summary>
        protected virtual void ProcessFeatures()
        {
            // don't do starttls if we're already on an SSL socket.
            // bad server setup, but no skin off our teeth, we're already
            // SSL'd.  Also, start-tls won't work when polling.
            if ((bool)this[Options.AUTO_TLS] &&
                m_features.StartTLS != null &&
                !m_sslOn &&
                m_stanzas.SupportsTLS)
            {
                // start-tls
                lock (m_stateLock)
                {
                    State = StartTLSState.Instance;
                }
                this.Write(new StartTLS(m_doc));
                return;
            }

            Compression comp = m_features.Compression;

            if ((bool)this[Options.AUTO_COMPRESS] &&
                comp != null &&
                comp.HasMethod("zlib") &&
                !m_compressionOn &&
                m_stanzas.SupportsCompression)
            {
                // start compression
                lock (m_stateLock)
                {
                    State = CompressionState.Instance;
                }
                Compress c = new Compress(m_doc);
                c.Method = "zlib";
                this.Write(c);
                return;
            }

            // not authenticated yet.  Note: we'll get a stream:features
            // after the last sasl restart, so we shouldn't try to iq:auth
            // at that point.
            if (!IsAuthenticated)
            {
                Mechanisms ms = m_features.Mechanisms;
                m_saslProc = null;

                MechanismType types = MechanismType.NONE;

                if (ms != null)
                {
                    // if SASL_MECHANISMS is set in the options, it is the limited set
                    // of mechanisms we're willing to try.  Mask them off of the offered set.
                    object smt = this[Options.SASL_MECHANISMS];

                    if (smt != null)
                        types = (MechanismType)smt & ms.Types;
                    else
                        types = ms.Types;
                }

                // If we're doing SASL, and there are mechanisms implemented by both
                // client and server.
                if (types != MechanismType.NONE && (bool)this[Options.SASL])
                {
                    lock (m_stateLock)
                    {
                        State = SASLState.Instance;
                    }

                    //FF
                    m_saslProc = SASLProcessor.createProcessor(types,
                                                               m_sslOn || (bool)this[Options.PLAINTEXT],
                                                               ms,
                                                               (bool)this[Options.ANONYMOUS]);
                    if (m_saslProc == null)
                    {
                        FireOnError(new NotImplementedException("No implemented mechanisms in: " + types.ToString()));
                        return;
                    }

                    if (OnSASLStart != null)
                        OnSASLStart(this, m_saslProc);

                    lock (m_stateLock)
                    {
                        // probably manual authentication
                        if (State != SASLState.Instance)
                            return;
                    }

                    try
                    {
                        Step s = m_saslProc.step(null, this.Document);

                        if (s != null)
                            this.Write(s);
                    }
                    catch (Exception e)
                    {
                        FireOnError(new SASLException(e.Message));
                        return;
                    }
                }

                if (m_saslProc == null)
                { // no SASL mechanisms.  Try iq:auth.
                    if ((bool)this[Options.REQUIRE_SASL])
                    {
                        FireOnError(new SASLException("No SASL mechanisms available"));
                        return;
                    }
                    lock (m_stateLock)
                    {
                        State = NonSASLAuthState.Instance;
                    }

                    if (OnSASLStart != null)
                        OnSASLStart(this, null); // HACK: old-style auth for jabberclient.
                }
            }
        }