Exemplo n.º 1
0
        /// <summary>
        /// Informs the client that an XML element was received and
        /// invokes the OnProtocol event.
        /// </summary>
        /// <param name="sender">The object that called this method.</param>
        /// <param name="tag">XML element that contains the new tag.</param>
        protected virtual void OnElement(object sender, System.Xml.XmlElement tag)
        {
            //Debug.WriteLine(tag.OuterXml);

            if (tag is jabber.protocol.stream.Error)
            {
                // Stream error.  Race condition!  Two cases:
                // 1) OnClose has already fired, in which case we are in ClosedState, and the reconnect timer is pending.
                // 2) OnClose hasn't fired, in which case we trick it into not starting the reconnect timer.
                lock (m_stateLock)
                {
                    if (m_state != ClosedState.Instance)
                    {
                        State = ClosingState.Instance;
                    }
                    else if (m_reconnectTimer != null)
                    {
                        Debug.WriteLine("Disposing of timer");
                        m_reconnectTimer.Dispose();
                    }
                }

                if (OnStreamError != null)
                {
                    if (InvokeRequired)
                        CheckedInvoke(OnStreamError, new object[] { this, tag });
                    else
                        OnStreamError(this, tag);
                }
                return;
            }

            if (State == ServerFeaturesState.Instance)
            {
                Features f = tag as Features;
                if (f == null)
                {
                    FireOnError(new InvalidOperationException("Expecting stream:features from a version='1.0' server"));
                    return;
                }
                m_features = f;
                ProcessFeatures();
                return;
            }
            else if (State == SASLState.Instance)
            {
                if (tag is Success)
                {
                    // restart the stream again
                    SendNewStreamHeader();
                }
                else if (tag is SASLFailure)
                {
                    m_saslProc = null;

                    lock (m_stateLock)
                    {
                        State = SASLFailedState.Instance;
                    }
                    SASLFailure sf = tag as SASLFailure;
                    // TODO: I18N
                    if (OnSASLError != null)
                    {
                        m_reconnect = false;
                        OnSASLError(this, sf);
                    }
                    else
                        FireOnError(new SASLException("SASL failure: " + sf.InnerXml));
                    return;
                }
                else if (tag is Step)
                {
                    try
                    {
                        Step s = m_saslProc.step(tag as Step, this.Document);
                        if (s != null)
                            Write(s);
                    }
                    catch (Exception e)
                    {
                        FireOnError(new SASLException(e.Message));
                        return;
                    }
                }
                else
                {
                    m_saslProc = null;
                    FireOnError(new SASLException("Invalid SASL protocol"));
                    return;
                }
            }
            else if (State == StartTLSState.Instance)
            {
                switch (tag.Name)
                {
                case "proceed":
                    if (!StartTLS())
                        return;
                    SendNewStreamHeader();
                    break;
                case "failure":
                    FireOnError(new AuthenticationFailedException());
                    return;
                }
            }
            else if (State == CompressionState.Instance)
            {
                switch (tag.Name)
                {
                case "compressed":
                    if (!StartCompression())
                        return;
                    SendNewStreamHeader();
                    break;
                case "failure":
                    CompressionFailure fail = tag as CompressionFailure;
                    FireOnError(new bedrock.io.CompressionFailedException(fail.Error));
                    return;
                }

            }
            else if (State == SASLAuthedState.Instance)
            {
                Features f = tag as Features;
                if (f == null)
                {
                    FireOnError(new InvalidOperationException("Expecting stream:features from a version='1.0' server"));
                    return;
                }
                if (OnSASLEnd != null)
                    OnSASLEnd(this, f);
                m_saslProc = null;
            }
            else
            {
                if (OnProtocol != null)
                {
                    if (InvokeRequired)
                        CheckedInvoke(OnProtocol, new object[] { this, tag });
                    else
                        OnProtocol(this, tag);
                }
            }
            CheckAll(tag);
        }
Exemplo n.º 2
0
        private void JabberClient_OnSASLStart(Object sender, SASLProcessor proc)
        {
            BaseState s;
            lock (StateLock)
            {
                s = State;
            }

            // HACK: fire OnSASLStart with state of NonSASLAuthState to initiate old-style auth.
            if (s == NonSASLAuthState.Instance)
            {
                if ((bool)this[Options.AUTO_LOGIN_THISPASS])
                    Login();
                else
                    LoginRequired(ManualLoginState.Instance);
            }
            else
            {
                if ((bool)this[Options.AUTO_LOGIN_THISPASS])
                {
                    // TODO: integrate SASL params into XmppStream params
                    proc[SASLProcessor.USERNAME] = User;
                    proc[SASLProcessor.PASSWORD] = Password;
                    proc[MD5Processor.REALM] = Server;
                    object creds = this[KerbProcessor.USE_WINDOWS_CREDS];
                    if (creds == null)
                        creds = false;
                    proc[KerbProcessor.USE_WINDOWS_CREDS] = creds.ToString();
                }
                else
                {
                    LoginRequired(ManualSASLLoginState.Instance);
                }
            }
        }
Exemplo n.º 3
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;
                    }
                    m_saslProc = SASLProcessor.createProcessor(types, m_sslOn || (bool)this[Options.PLAINTEXT], ms);
                    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.
                }
            }
        }