public override void StreamParserOnStreamElement(object sender, ElementEventArgs eventArgs) { base.StreamParserOnStreamElement (sender, eventArgs); var e = eventArgs.Element; if (e is Handshake) { m_Authenticated = true; if (OnLogin != null) OnLogin(this); if (KeepAlive) CreateKeepAliveTimer(); eventArgs.Handled = true; } else if (e is Route) { if (OnRoute != null) OnRoute(this, e as Route); eventArgs.Handled = true; } else if (e is protocol.Error) { protocol.Error streamErr = e as protocol.Error; switch (streamErr.Condition) { // Auth errors are important for the users here, so throw catch auth errors // in a separate event here case agsXMPP.protocol.StreamErrorCondition.NotAuthorized: // Authentication Error if (OnAuthError != null) OnAuthError(this, e as Element); break; default: if (OnStreamError != null) OnStreamError(this, e as Element); break; } eventArgs.Handled = true; } else if (e is Message) { if (OnMessage != null) { OnMessage(this, e as Message); eventArgs.Handled = true; } } else if (e is Presence) { if (OnPresence != null) { OnPresence(this, e as Presence); eventArgs.Handled = true; } } else if (e is IQ) { if (OnIq != null) { var iqEventArgs = new protocol.client.IQEventArgs((IQ)e); OnIq(this, iqEventArgs); if (iqEventArgs.Handled) { eventArgs.Handled = true; } } } }
internal void OnStreamElement(object sender, ElementEventArgs eventArgs) { if (m_XmppClient == null) return; if ( m_XmppClient.XmppConnectionState == XmppConnectionState.Securing || m_XmppClient.XmppConnectionState == XmppConnectionState.StartCompression) return; var e = eventArgs.Element; if (e is Features) { Features f = e as Features; if (!m_XmppClient.Authenticated) { // RECV: <stream:features><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> // <mechanism>DIGEST-MD5</mechanism><mechanism>PLAIN</mechanism> // </mechanisms> // <register xmlns='http://jabber.org/features/iq-register'/> // </stream:features> // SENT: <auth mechanism="DIGEST-MD5" xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/> // Select a SASL mechanism SaslEventArgs args = new SaslEventArgs(f.Mechanisms); if (OnSaslStart != null) OnSaslStart(this, args); if (args.Auto) { // Library handles the Sasl stuff if (f.Mechanisms!=null) { if (m_XmppClient.UseStartTLS == false && m_XmppClient.UseSSL == false && f.Mechanisms.SupportsMechanism(MechanismType.X_GOOGLE_TOKEN) ) { // This is the only way to connect to GTalk on a unsecure Socket for now // Secure authentication is done over https requests to pass the // authentication credentials on a secure connection args.Mechanism = protocol.sasl.Mechanism.GetMechanismName(MechanismType.X_GOOGLE_TOKEN); } #if !(CF || CF_2) else if (m_XmppClient.UseSso && f.Mechanisms.SupportsMechanism(MechanismType.GSSAPI)) { args.Mechanism = protocol.sasl.Mechanism.GetMechanismName(MechanismType.GSSAPI); string kerbPrinc = f.Mechanisms.GetMechanism(MechanismType.GSSAPI).KerberosPrincipal; if (kerbPrinc != null) m_XmppClient.KerberosPrincipal = f.Mechanisms.GetMechanism(MechanismType.GSSAPI).KerberosPrincipal; } #endif else if (f.Mechanisms.SupportsMechanism(MechanismType.SCRAM_SHA_1)) { args.Mechanism = protocol.sasl.Mechanism.GetMechanismName(MechanismType.SCRAM_SHA_1); } else if (f.Mechanisms.SupportsMechanism(MechanismType.DIGEST_MD5)) { args.Mechanism = protocol.sasl.Mechanism.GetMechanismName(MechanismType.DIGEST_MD5); } else if (f.Mechanisms.SupportsMechanism(MechanismType.PLAIN)) { args.Mechanism = protocol.sasl.Mechanism.GetMechanismName(MechanismType.PLAIN); } else { args.Mechanism = null; } } else { // Hack for Google // TODO: i don't think we need this anymore. This was in an very early version of the gtalk server. args.Mechanism = null; //args.Mechanism = agsXMPP.protocol.sasl.Mechanism.GetMechanismName(agsXMPP.protocol.sasl.MechanismType.PLAIN); } } if (args.Mechanism != null) { m_Mechanism = Factory.SaslFactory.GetMechanism(args.Mechanism); // Set properties for the SASL mechanism m_Mechanism.Username = m_XmppClient.Username; m_Mechanism.Password = m_XmppClient.Password; m_Mechanism.Server = m_XmppClient.Server; m_Mechanism.ExtentedData = args.ExtentedData; // Call Init Method on the mechanism m_Mechanism.Init(m_XmppClient); } else { m_XmppClient.RequestLoginInfo(); } } else if(!m_XmppClient.Binded) { if (f.SupportsBind) { m_XmppClient.DoChangeXmppConnectionState(XmppConnectionState.Binding); BindIq bIq = string.IsNullOrEmpty(m_XmppClient.Resource) ? new BindIq(IqType.set) : new BindIq(IqType.set, m_XmppClient.Resource); m_XmppClient.IqGrabber.SendIq(bIq, BindResult); } } } else if (e is Challenge) { if (m_Mechanism != null && !m_XmppClient.Authenticated) { m_Mechanism.Parse(e); } } else if (e is Success) { // SASL authentication was successfull if (OnSaslEnd!=null) OnSaslEnd(this); m_XmppClient.DoChangeXmppConnectionState(XmppConnectionState.Authenticated); m_Mechanism = null; m_XmppClient.Reset(); } else if (e is Failure) { // Authentication failure m_XmppClient.FireOnAuthError(e as Element); } }
private void OnRegisterResult(IQEventArgs e, Element data) { /* Example 6. Host Informs Entity of Failed Registration (Username Conflict) <iq type='error' id='reg2'> <query xmlns='jabber:iq:register'> <username>bill</username> <password>m1cro$oft</password> <email>[email protected]</email> </query> <error code='409' type='cancel'> <conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq> Example 7. Host Informs Entity of Failed Registration (Some Required Information Not Provided) <iq type='error' id='reg2'> <query xmlns='jabber:iq:register'> <username>bill</username> <password>Calliope</password> </query> <error code='406' type='modify'> <not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error> </iq> */ if (e.IQ.Type == IqType.result) { DoChangeXmppConnectionState(XmppConnectionState.Registered); if (OnRegistered != null) OnRegistered(this); if (this.StreamVersion != null && this.StreamVersion.StartsWith("1.")) { // init sasl login InitSaslHandler(); var eventArgs = new ElementEventArgs(data); m_SaslHandler.OnStreamElement(this, eventArgs); if (eventArgs.Handled) { e.Handled = true; } } else { // old jabber style login RequestLoginInfo(); e.Handled = true; } } else if (e.IQ.Type == IqType.error) { if (OnRegisterError != null) OnRegisterError(this, e.IQ); } }
public override void StreamParserOnStreamElement(object sender, ElementEventArgs eventArgs) { base.StreamParserOnStreamElement(sender, eventArgs); bool handled = false; var e = eventArgs.Element; if (e is IQ) { IQ iq = e as IQ; if (OnIq != null) { var ev = new IQEventArgs(iq); OnIq(this, ev); handled = handled || ev.Handled; } if ( iq != null && iq.Query != null) { // Roster if (iq.Query is Roster) { OnRosterIQ(iq); handled = true; } } } else if (e is Message) { if (OnMessage != null) { OnMessage(this, e as Message); handled = true; } } else if (e is Presence) { if (OnPresence != null) { OnPresence(this, e as Presence); handled = true; } } else if (e is protocol.stream.Features) { // Stream Features // StartTLS stuff protocol.stream.Features f = e as protocol.stream.Features; #if SSL || BCCRYPTO || CF_2 if (f.SupportsStartTls && m_UseStartTLS) { DoChangeXmppConnectionState(XmppConnectionState.Securing); Send(new StartTls()); } // connection is not encrypted, doesn't support starttls but tls is forced else if (!ClientSocket.IsEncrypted && !f.SupportsStartTls && ForceStartTls) { FireOnError(this, new StartTlsException("StartTls is not supported on this server")); Close(); } else #endif if (m_UseCompression && f.SupportsCompression && f.Compression.SupportsMethod(CompressionMethod.zlib)) { // Check for Stream Compression // we support only ZLIB because its a free algorithm without patents // yes ePatents suck DoChangeXmppConnectionState(XmppConnectionState.StartCompression); Send(new Compress(CompressionMethod.zlib)); } else if (m_RegisterAccount) { // Do registration after TLS when possible if (f.SupportsRegistration) GetRegistrationFields(e); else { // registration is not enabled on this server FireOnError(this, new RegisterException("Registration is not allowed on this server")); Close(); // Close the stream } } ServerCapabilities = f.Capabilities; } #if SSL || BCCRYPTO || CF_2 else if (e is Proceed) { StreamParser.Reset(); if (ClientSocket.StartTls()) { SendStreamHeader(false); DoChangeXmppConnectionState(XmppConnectionState.Authenticating); handled = true; } } #endif else if (e is Compressed) { //DoChangeXmppConnectionState(XmppConnectionState.StartCompression); StreamParser.Reset(); ClientSocket.StartCompression(); // Start new Stream Header compressed. SendStreamHeader(false); DoChangeXmppConnectionState(XmppConnectionState.Compressed); handled = true; } else if (e is agsXMPP.protocol.Error) { if (OnStreamError != null) { OnStreamError(this, e as Element); handled = true; } } if (handled) { eventArgs.Handled = true; } }
/// <summary> /// If users didnt use the library correctly and had no local error handles /// it always crashed here and disconencted the socket. /// Catch this errors here now and foreward them. /// </summary> /// <param name="el"></param> internal void DoRaiseOnStreamElement(Element el) { try { if (OnStreamElement != null) { var eventArgs = new ElementEventArgs(el); OnStreamElement(this, eventArgs); if (!eventArgs.Handled) { OnStreamElementNotHandled(el); } } } catch (Exception ex) { if (OnError != null) OnError(this, ex); } }